Diff for /np2/i386c/ia32/cpu_mem.c between versions 1.4 and 1.7

version 1.4, 2004/01/07 14:49:10 version 1.7, 2004/01/25 07:53:08
Line 31 Line 31
 #include "cpu.h"  #include "cpu.h"
 #include "memory.h"  #include "memory.h"
   
 // ¤¢¤È¤Ç¡Ä  // static BYTE *cpumem = 0;
 // extern DWORD cpumem_addrmask;                // -> CPU_STAT_ADRSMASK  // static DWORD extmem_size = 0;
   
   #define cpumem          i386core.e.ext
   #define extmem_size     i386core.e.extsize
   
 BYTE *cpumem = 0;  
 DWORD extmem_size = 0;  
 BYTE protectmem_size = 0;  
   
 /*  /*
  * initialize 1MB-16MB memory   * initialize 1MB-16MB memory
  */   */
   
 int  int
 init_cpumem(BYTE usemem)  init_cpumem(UINT8 usemem)
 {  {
         DWORD size;          UINT32  size;
   
         if (usemem > 13)  
                 usemem = 13;  
         size = usemem << 20;          size = usemem << 20;
           if (size >= (LOWMEM - 0x100000)) {
         if (extmem_size != size - (LOWMEM - 0x100000)) {                  size -= (LOWMEM - 0x100000);
           }
           else {
                   size = 0;
           }
           if (extmem_size != size) {
                 if (cpumem) {                  if (cpumem) {
                         free(cpumem);                          free(cpumem);
                         cpumem = 0;                          cpumem = 0;
                 }                  }
                 if (size <= LOWMEM - 0x100000) {                  if (size) {
                         extmem_size = 0;                          cpumem = (BYTE *)malloc(size);
                         cpumem = 0;  
                 } else {  
                         extmem_size = size - (LOWMEM - 0x100000);  
                         cpumem = (BYTE *)malloc(extmem_size);  
                         if (cpumem == NULL) {                          if (cpumem == NULL) {
                                 protectmem_size = 0;                                  size = 0;
                                 return FAILURE;  
                         }                          }
                         memset(cpumem, 0, extmem_size);  
                 }                  }
                   extmem_size = size;
         }          }
         protectmem_size = usemem;  
         return SUCCESS;          return SUCCESS;
 }  }
   
Line 78  init_cpumem(BYTE usemem) Line 75  init_cpumem(BYTE usemem)
  * memory access check   * memory access check
  */   */
 void  void
 cpu_memoryread_check(descriptor_t* sd, DWORD madr, DWORD length, int e)  cpu_memoryread_check(descriptor_t* sd, DWORD offset, DWORD length, int e)
 {  {
           DWORD uplimit;
   
         if (CPU_STAT_PM) {          if (CPU_STAT_PM) {
                 /* invalid */                  /* invalid */
                 if (!sd->valid) {                  if (!sd->valid) {
                           VERBOSE(("cpu_memoryread_check: invalid"));
                         EXCEPTION(GP_EXCEPTION, 0);                          EXCEPTION(GP_EXCEPTION, 0);
                 }                  }
   
                 /* not present */                  /* not present */
                 if (!sd->p) {                  if (!sd->p) {
                           VERBOSE(("cpu_memoryread_check: not present"));
                         EXCEPTION(e, 0);                          EXCEPTION(e, 0);
                 }                  }
   
Line 97  cpu_memoryread_check(descriptor_t* sd, D Line 97  cpu_memoryread_check(descriptor_t* sd, D
                 case 2:  case 3:        /* rw */                  case 2:  case 3:        /* rw */
                 case 10: case 11:       /* rx */                  case 10: case 11:       /* rx */
                 case 14: case 15:       /* rxc */                  case 14: case 15:       /* rxc */
                         if ((madr > sd->u.seg.segend - length + 1)                          if (offset > sd->u.seg.limit - length + 1) {
                             || (length - 1 > sd->u.seg.limit)) {                                  VERBOSE(("cpu_memoryread_check: offset(%08x) > sd->u.seg.limit(%08x) - length(%08x) + 1", offset, sd->u.seg.limit, length));
                                   EXCEPTION(e, 0);
                           }
                           if (length - 1 > sd->u.seg.limit) {
                                   VERBOSE(("cpu_memoryread_check: length(%08x) - 1 > sd->u.seg.limit(%08x)", length, sd->u.seg.limit));
                                 EXCEPTION(e, 0);                                  EXCEPTION(e, 0);
                         }                          }
                         break;                          break;
   
                 case 4:  case 5:        /* ro (expand down) */                  case 4:  case 5:        /* ro (expand down) */
                 case 6:  case 7:        /* rw (expand down) */                  case 6:  case 7:        /* rw (expand down) */
                 {                          uplimit = sd->d ? 0xffffffff : 0x0000ffff;
                         DWORD uplimit = sd->d ? 0xffffffff : 0x0000ffff;                          if (offset <= sd->u.seg.limit) {
                         if ((madr <= sd->u.seg.segend)                                  VERBOSE(("cpu_memoryread_check: offset(%08x) <= sd->u.seg.limit(%08x)", offset, sd->u.seg.limit));
                             || (madr > uplimit)                                  EXCEPTION(e, 0);
                             || (uplimit - madr < length - 1)) {                          }
                           if (offset > uplimit) {
                                   VERBOSE(("cpu_memoryread_check: offset(%08x) > uplimit(%08x)", offset, uplimit));
                                   EXCEPTION(e, 0);
                           }
                           if (uplimit - offset < length - 1) {
                                   VERBOSE(("cpu_memoryread_check: uplimit(%08x) - offset(%08x) < length(%08x) - 1", uplimit, offset, length));
                                 EXCEPTION(e, 0);                                  EXCEPTION(e, 0);
                         }                          }
                 }  
                         break;                          break;
   
                 default:                  default:
                           VERBOSE(("cpu_memoryread_check: invalid type (type = %d)", sd->type));
                         EXCEPTION(e, 0);                          EXCEPTION(e, 0);
                         break;                          break;
                 }                  }
         }          }
         sd->flag |= CPU_DESC_READABLE;          sd->flag |= CPU_DESC_FLAG_READABLE;
 }  }
   
 void  void
 cpu_memorywrite_check(descriptor_t* sd, DWORD madr, DWORD length, int e)  cpu_memorywrite_check(descriptor_t* sd, DWORD offset, DWORD length, int e)
 {  {
           DWORD uplimit;
   
         if (CPU_STAT_PM) {          if (CPU_STAT_PM) {
                 /* invalid */                  /* invalid */
                 if (!sd->valid) {                  if (!sd->valid) {
                           VERBOSE(("cpu_memorywrite_check: invalid"));
                         EXCEPTION(GP_EXCEPTION, 0);                          EXCEPTION(GP_EXCEPTION, 0);
                 }                  }
   
                 /* not present */                  /* not present */
                 if (!sd->p) {                  if (!sd->p) {
                           VERBOSE(("cpu_memorywrite_check: not present"));
                           EXCEPTION(e, 0);
                   }
   
                   if (!sd->s) {
                           VERBOSE(("cpu_memorywrite_check: system segment"));
                         EXCEPTION(e, 0);                          EXCEPTION(e, 0);
                 }                  }
   
                 switch (sd->type) {                  switch (sd->type) {
                 case 2: case 3: /* rw */                  case 2: case 3: /* rw */
                         if ((madr > sd->u.seg.segend - length + 1)                          if (offset > sd->u.seg.limit - length + 1) {
                             || (length - 1 > sd->u.seg.limit)) {                                  VERBOSE(("cpu_memorywrite_check: offset(%08x) > sd->u.seg.limit(%08x) - length(%08x) + 1", offset, sd->u.seg.limit, length));
                                   EXCEPTION(e, 0);
                           }
                           if (length - 1 > sd->u.seg.limit) {
                                   VERBOSE(("cpu_memorywrite_check: length(%08x) - 1 > sd->u.seg.limit(%08x)", length, sd->u.seg.limit));
                                 EXCEPTION(e, 0);                                  EXCEPTION(e, 0);
                         }                          }
                         break;                          break;
   
                 case 6: case 7: /* rw (expand down) */                  case 6: case 7: /* rw (expand down) */
                 {                          uplimit = sd->d ? 0xffffffff : 0x0000ffff;
                         DWORD uplimit = sd->d ? 0xffffffff : 0x0000ffff;                          if (offset <= sd->u.seg.limit) {
                         if ((madr <= sd->u.seg.segend)                                  VERBOSE(("cpu_memorywrite_check: offset(%08x) <= sd->u.seg.limit(%08x)", offset, sd->u.seg.limit));
                             || (madr > uplimit)                                  EXCEPTION(e, 0);
                             || (uplimit - madr < length - 1)) {                          }
                           if (offset > uplimit) {
                                   VERBOSE(("cpu_memorywrite_check: offset(%08x) > uplimit(%08x)", offset, uplimit));
                                   EXCEPTION(e, 0);
                           }
                           if (uplimit - offset < length - 1) {
                                   VERBOSE(("cpu_memorywrite_check: uplimit(%08x) - offset(%08x) < length(%08x) - 1", uplimit, offset, length));
                                 EXCEPTION(e, 0);                                  EXCEPTION(e, 0);
                         }                          }
                 }  
                         break;                          break;
   
                 default:                  default:
                           VERBOSE(("cpu_memorywrite_check: invalid type (type = %d)", sd->type));
                         EXCEPTION(e, 0);                          EXCEPTION(e, 0);
                         break;                          break;
                 }                  }
         }          }
         sd->flag |= CPU_DESC_WRITABLE;          sd->flag |= CPU_DESC_FLAG_WRITABLE;
 }  }
   
 BOOL  BOOL
 cpu_stack_push_check(descriptor_t* sdp, DWORD esp, DWORD length)  cpu_stack_push_check(descriptor_t* sdp, DWORD esp, DWORD length)
 {  {
           DWORD limit;
   
         if (!CPU_STAT_PM)          if (!CPU_STAT_PM)
                 return TRUE;                  return TRUE;
   
         if (!sdp->valid || !sdp->p)          if (!sdp->valid || !sdp->p)
                 return FALSE;                  return FALSE;
 #ifdef _DEBUG  
         if (!sdp->s || sdp->u.seg.c || !sdp->u.seg.wr)          if (!sdp->s || sdp->u.seg.c || !sdp->u.seg.wr)
                 return FALSE;                  return FALSE;
 #endif  
   
         if (!sdp->d)          if (!sdp->d) {
                 esp &= 0xffff;                  esp &= 0xffff;
                   limit = 0xffff;
           } else {
                   limit = 0xffffffff;
           }
         if (sdp->u.seg.ec) {          if (sdp->u.seg.ec) {
                 DWORD limit = (sdp->d) ? 0xffffffff : 0xffff;                  /* expand-down stack */
                 if ((esp == 0)                  if ((esp == 0)
                  || (esp < length)                   || (esp < length)
                  || (esp - length <= sdp->u.seg.segend)                   || (esp - length <= sdp->u.seg.limit)
                  || (esp > limit))                   || (esp > limit))
                         return FALSE;                          return FALSE;
         } else {          } else {
Line 196  cpu_stack_push_check(descriptor_t* sdp,  Line 227  cpu_stack_push_check(descriptor_t* sdp, 
                                 return FALSE;                                  return FALSE;
                 } else {                  } else {
                         if ((esp < length)                          if ((esp < length)
                          || (esp - 1 > sdp->u.seg.segend))                           || (esp - 1 > sdp->u.seg.limit))
                                 return FALSE;                                  return FALSE;
                 }                  }
         }          }
Line 213  cpu_stack_pop_check(descriptor_t* sdp, D Line 244  cpu_stack_pop_check(descriptor_t* sdp, D
   
         if (!sdp->valid || !sdp->p)          if (!sdp->valid || !sdp->p)
                 return FALSE;                  return FALSE;
 #ifdef _DEBUG  
         if (!sdp->s || sdp->u.seg.c || !sdp->u.seg.wr)          if (!sdp->s || sdp->u.seg.c || !sdp->u.seg.wr)
                 return FALSE;                  return FALSE;
 #endif  
   
         if (!sdp->d) {          if (!sdp->d) {
                 esp &= 0xffff;                  esp &= 0xffff;
Line 225  cpu_stack_pop_check(descriptor_t* sdp, D Line 254  cpu_stack_pop_check(descriptor_t* sdp, D
                 limit = 0xffffffff;                  limit = 0xffffffff;
         }          }
         if (sdp->u.seg.ec) {          if (sdp->u.seg.ec) {
                   /* expand-down stack */
                 if ((esp == limit)                  if ((esp == limit)
                  || ((limit  - esp) + 1 < length))                   || ((limit - esp) + 1 < length))
                         return FALSE;                          return FALSE;
         } else {          } else {
                 /* expand-up stack */                  /* expand-up stack */
                 if ((esp == limit)                  if ((esp == limit)
                  || (sdp->u.seg.segend == 0)                   || (sdp->u.seg.segend == 0)
                  || (esp > sdp->u.seg.segend)                   || (esp > sdp->u.seg.limit)
                  || ((sdp->u.seg.segend - esp) + 1 < length))                   || ((sdp->u.seg.limit - esp) + 1 < length))
                         return FALSE;                          return FALSE;
         }          }
         return TRUE;          return TRUE;
 }  }
   
   
   #define AS32_NOCHECK
   #undef  OVERRUN_CHECK
   
   #if defined(OVERRUN_CHECK)
   #define OVERRUN_EXCEPTION()     EXCEPTION(GP_EXCEPTION, 0)
   #else
   #define OVERRUN_EXCEPTION()
   #endif
   
 /*  /*
  * code fetch   * code fetch
  */   */
 BYTE MEMCALL  BYTE MEMCALL
 cpu_codefetch(DWORD madr)  cpu_codefetch(DWORD offset)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         DWORD addr;          DWORD addr;
   
         sd = &CPU_STAT_SREG(CPU_CS_INDEX);          sd = &CPU_STAT_SREG(CPU_CS_INDEX);
   #ifndef AS32_NOCHECK
         if (!CPU_INST_AS32)          if (!CPU_INST_AS32)
                 madr &= 0xffff;                  offset &= 0xffff;
         if (madr <= sd->u.seg.segend) {  #endif
                 addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + madr;          if (offset <= sd->u.seg.limit) {
                   addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + offset;
                 if (!CPU_STAT_PM)                  if (!CPU_STAT_PM)
                         return cpu_memoryread(addr);                          return cpu_memoryread(addr);
                 return cpu_lcmemoryread(addr);                  return cpu_lcmemoryread(addr);
Line 263  cpu_codefetch(DWORD madr) Line 304  cpu_codefetch(DWORD madr)
 }  }
   
 WORD MEMCALL  WORD MEMCALL
 cpu_codefetch_w(DWORD madr)  cpu_codefetch_w(DWORD offset)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         DWORD addr;          DWORD addr;
   
         sd = &CPU_STAT_SREG(CPU_CS_INDEX);          sd = &CPU_STAT_SREG(CPU_CS_INDEX);
   #ifndef AS32_NOCHECK
         if (!CPU_INST_AS32)          if (!CPU_INST_AS32)
                 madr &= 0xffff;                  offset &= 0xffff;
         if (madr <= sd->u.seg.segend - 1) {  #endif
                 addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + madr;          if (offset <= sd->u.seg.limit - 1) {
                   addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + offset;
                 if (!CPU_STAT_PM)                  if (!CPU_STAT_PM)
                         return cpu_memoryread_w(addr);                          return cpu_memoryread_w(addr);
                 return cpu_lcmemoryread_w(addr);                  return cpu_lcmemoryread_w(addr);
Line 282  cpu_codefetch_w(DWORD madr) Line 325  cpu_codefetch_w(DWORD madr)
 }  }
   
 DWORD MEMCALL  DWORD MEMCALL
 cpu_codefetch_d(DWORD madr)  cpu_codefetch_d(DWORD offset)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         DWORD addr;          DWORD addr;
   
         sd = &CPU_STAT_SREG(CPU_CS_INDEX);          sd = &CPU_STAT_SREG(CPU_CS_INDEX);
   #ifndef AS32_NOCHECK
         if (!CPU_INST_AS32)          if (!CPU_INST_AS32)
                 madr &= 0xffff;                  offset &= 0xffff;
         if (madr <= sd->u.seg.segend - 3) {  #endif
                 addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + madr;          if (offset <= sd->u.seg.limit - 3) {
                   addr = CPU_STAT_SREGBASE(CPU_CS_INDEX) + offset;
                 if (!CPU_STAT_PM)                  if (!CPU_STAT_PM)
                         return cpu_memoryread_d(addr);                          return cpu_memoryread_d(addr);
                 return cpu_lcmemoryread_d(addr);                  return cpu_lcmemoryread_d(addr);
Line 305  cpu_codefetch_d(DWORD madr) Line 350  cpu_codefetch_d(DWORD madr)
  * virtual address -> linear address   * virtual address -> linear address
  */   */
 BYTE MEMCALL  BYTE MEMCALL
 cpu_vmemoryread(int idx, DWORD madr)  cpu_vmemoryread(int idx, DWORD offset)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         DWORD addr;          DWORD addr;
           int exc;
   
         __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);          __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
         sd = &CPU_STAT_SREG(idx);          sd = &CPU_STAT_SREG(idx);
         if (!sd->valid) {          if (!sd->valid) {
                 EXCEPTION(GP_EXCEPTION, 0);                  exc = GP_EXCEPTION;
                   goto err;
         }          }
   
   #ifndef AS32_NOCHECK
         if (!CPU_INST_AS32)          if (!CPU_INST_AS32)
                 madr &= 0xffff;                  offset &= 0xffff;
         for (;;) {  #endif
                 if ((sd->flag & CPU_DESC_READABLE)          if (!(sd->flag & CPU_DESC_FLAG_READABLE)) {
                     || (madr <= sd->u.seg.segend)) {                  cpu_memoryread_check(sd, offset, 1,
                         addr = CPU_STAT_SREGBASE(idx) + madr;  
                         if (!CPU_STAT_PM)  
                                 return cpu_memoryread(addr);  
                         return cpu_lmemoryread(addr);  
                 }  
                 cpu_memoryread_check(sd, madr, 1,  
                     (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);                      (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
           } else {
                   switch (sd->type) {
                   case 4: case 5: case 6: case 7:
                           if (offset <= sd->u.seg.limit) {
                                   if (idx == CPU_SS_INDEX)
                                           exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                           }
                           break;
   
                   default:
                           if (offset > sd->u.seg.limit) {
                                   if (idx == CPU_SS_INDEX)
                                           exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                           }
                           break;
                   }
         }          }
         /*NOTREACHED*/          addr = CPU_STAT_SREGBASE(idx) + offset;
           if (!CPU_STAT_PM)
                   return cpu_memoryread(addr);
           return cpu_lmemoryread(addr);
   
   err:
           EXCEPTION(exc, 0);
           return 0;       /* compiler happy */
 }  }
   
 WORD MEMCALL  WORD MEMCALL
 cpu_vmemoryread_w(int idx, DWORD madr)  cpu_vmemoryread_w(int idx, DWORD offset)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         DWORD addr;          DWORD addr;
           int exc;
   
         __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);          __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
         sd = &CPU_STAT_SREG(idx);          sd = &CPU_STAT_SREG(idx);
         if (!sd->valid) {          if (!sd->valid) {
                 EXCEPTION(GP_EXCEPTION, 0);                  exc = GP_EXCEPTION;
                   goto err;
         }          }
   
   #ifndef AS32_NOCHECK
         if (!CPU_INST_AS32)          if (!CPU_INST_AS32)
                 madr &= 0xffff;                  offset &= 0xffff;
         for (;;) {  #endif
                 if ((sd->flag & CPU_DESC_READABLE)          if (!(sd->flag & CPU_DESC_FLAG_READABLE)) {
                     || (madr <= sd->u.seg.segend - 1)) {                  cpu_memoryread_check(sd, offset, 2,
                         addr = CPU_STAT_SREGBASE(idx) + madr;  
                         if (!CPU_STAT_PM)  
                                 return cpu_memoryread_w(addr);  
                         return cpu_lmemoryread_w(addr);  
                 }  
                 cpu_memoryread_check(sd, madr, 2,  
                     (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);                      (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
         }          } else {
         /*NOTREACHED*/                  switch (sd->type) {
                   case 4: case 5: case 6: case 7:
                           if (offset - 1 <= sd->u.seg.limit) {
                                   if (idx == CPU_SS_INDEX)
                                           exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                           }
                           break;
   
                   default:
                           if (offset > sd->u.seg.limit - 1) {
                                   if (idx == CPU_SS_INDEX)
                                           exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                           }
                           break;
                   }
           } 
           addr = CPU_STAT_SREGBASE(idx) + offset;
           if (!CPU_STAT_PM)
                   return cpu_memoryread_w(addr);
           return cpu_lmemoryread_w(addr);
   
   err:
           EXCEPTION(exc, 0);
           return 0;       /* compiler happy */
 }  }
   
 DWORD MEMCALL  DWORD MEMCALL
 cpu_vmemoryread_d(int idx, DWORD madr)  cpu_vmemoryread_d(int idx, DWORD offset)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         DWORD addr;          DWORD addr;
           int exc;
   
         __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);          __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
         sd = &CPU_STAT_SREG(idx);          sd = &CPU_STAT_SREG(idx);
         if (!sd->valid) {          if (!sd->valid) {
                 EXCEPTION(GP_EXCEPTION, 0);                  exc = GP_EXCEPTION;
                   goto err;
         }          }
   
   #ifndef AS32_NOCHECK
         if (!CPU_INST_AS32)          if (!CPU_INST_AS32)
                 madr &= 0xffff;                  offset &= 0xffff;
         for (;;) {  #endif
                 if ((sd->flag & CPU_DESC_READABLE)          if (!(sd->flag & CPU_DESC_FLAG_READABLE)) {
                     || (madr <= sd->u.seg.segend - 3)) {                  cpu_memoryread_check(sd, offset, 4,
                         addr = CPU_STAT_SREGBASE(idx) + madr;  
                         if (!CPU_STAT_PM)  
                                 return cpu_memoryread_d(addr);  
                         return cpu_lmemoryread_d(addr);  
                 }  
                 cpu_memoryread_check(sd, madr, 4,  
                     (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);                      (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
           } else {
                   switch (sd->type) {
                   case 4: case 5: case 6: case 7:
                           if (offset - 3 <= sd->u.seg.limit) {
                                   if (idx == CPU_SS_INDEX)
                                           exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                           }
                           break;
   
                   default:
                           if (offset > sd->u.seg.limit - 3) {
                                   if (idx == CPU_SS_INDEX)
                                           exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                           }
                           break;
                   }
         }          }
         /*NOTREACHED*/          addr = CPU_STAT_SREGBASE(idx) + offset;
           if (!CPU_STAT_PM)
                   return cpu_memoryread_d(addr);
           return cpu_lmemoryread_d(addr);
   
   err:
           EXCEPTION(exc, 0);
           return 0;       /* compiler happy */
 }  }
   
 /* vaddr memory write */  /* vaddr memory write */
 void MEMCALL  void MEMCALL
 cpu_vmemorywrite(int idx, DWORD madr, BYTE val)  cpu_vmemorywrite(int idx, DWORD offset, BYTE val)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         DWORD addr;          DWORD addr;
           int exc;
   
         __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);          __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
         sd = &CPU_STAT_SREG(idx);          sd = &CPU_STAT_SREG(idx);
         if (!sd->valid) {          if (!sd->valid) {
                 EXCEPTION(GP_EXCEPTION, 0);                  exc = GP_EXCEPTION;
                   goto err;
         }          }
   
   #ifndef AS32_NOCHECK
         if (!CPU_INST_AS32)          if (!CPU_INST_AS32)
                 madr &= 0xffff;                  offset &= 0xffff;
         for (;;) {  #endif
                 if ((sd->flag & CPU_DESC_WRITABLE)          if (!(sd->flag & CPU_DESC_FLAG_WRITABLE)) {
                     || (madr <= sd->u.seg.segend)) {                  cpu_memorywrite_check(sd, offset, 1,
                         addr = CPU_STAT_SREGBASE(idx) + madr;                      (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
                         if (!CPU_STAT_PM) {          } else {
                                 /* real mode */                  switch (sd->type) {
                                 cpu_memorywrite(addr, val);                  case 6: case 7:
                         } else {                          if (offset <= sd->u.seg.limit) {
                                 /* protected mode */                                  if (idx == CPU_SS_INDEX)
                                 cpu_lmemorywrite(addr, val);                                          exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                           }
                           break;
   
                   default:
                           if (offset > sd->u.seg.limit) {
                                   if (idx == CPU_SS_INDEX)
                                           exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                         }                          }
                         return;                          break;
                 }                  }
                 cpu_memorywrite_check(sd, madr, 1,  
                     (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);  
         }          }
         /*NOTREACHED*/          addr = CPU_STAT_SREGBASE(idx) + offset;
           if (!CPU_STAT_PM) {
                   /* real mode */
                   cpu_memorywrite(addr, val);
           } else {
                   /* protected mode */
                   cpu_lmemorywrite(addr, val);
           }
           return;
   
   err:
           EXCEPTION(exc, 0);
 }  }
   
 void MEMCALL  void MEMCALL
 cpu_vmemorywrite_w(int idx, DWORD madr, WORD val)  cpu_vmemorywrite_w(int idx, DWORD offset, WORD val)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         DWORD addr;          DWORD addr;
           int exc;
   
         __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);          __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
         sd = &CPU_STAT_SREG(idx);          sd = &CPU_STAT_SREG(idx);
         if (!sd->valid) {          if (!sd->valid) {
                 EXCEPTION(GP_EXCEPTION, 0);                  exc = GP_EXCEPTION;
                   goto err;
         }          }
   
   #ifndef AS32_NOCHECK
         if (!CPU_INST_AS32)          if (!CPU_INST_AS32)
                 madr &= 0xffff;                  offset &= 0xffff;
         for (;;) {  #endif
                 if ((sd->flag & CPU_DESC_WRITABLE)          if (!(sd->flag & CPU_DESC_FLAG_WRITABLE)) {
                     || (madr <= sd->u.seg.segend - 1)) {                  cpu_memorywrite_check(sd, offset, 2,
                         addr = CPU_STAT_SREGBASE(idx) + madr;                      (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
                         if (!CPU_STAT_PM) {          } else {
                                 /* real mode */                  switch (sd->type) {
                                 cpu_memorywrite_w(addr, val);                  case 6: case 7:
                         } else {                          if (offset - 1 <= sd->u.seg.limit) {
                                 /* protected mode */                                  if (idx == CPU_SS_INDEX)
                                 cpu_lmemorywrite_w(addr, val);                                          exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                           }
                           break;
   
                   default:
                           if (offset > sd->u.seg.limit - 1) {
                                   if (idx == CPU_SS_INDEX)
                                           exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                         }                          }
                         return;                          break;
                 }                  }
                 cpu_memorywrite_check(sd, madr, 2,  
                     (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);  
         }          }
         /*NOTREACHED*/          addr = CPU_STAT_SREGBASE(idx) + offset;
           if (!CPU_STAT_PM) {
                   /* real mode */
                   cpu_memorywrite_w(addr, val);
           } else {
                   /* protected mode */
                   cpu_lmemorywrite_w(addr, val);
           }
           return;
   
   err:
           EXCEPTION(exc, 0);
 }  }
   
 void MEMCALL  void MEMCALL
 cpu_vmemorywrite_d(int idx, DWORD madr, DWORD val)  cpu_vmemorywrite_d(int idx, DWORD offset, DWORD val)
 {  {
         descriptor_t *sd;          descriptor_t *sd;
         DWORD addr;          DWORD addr;
           int exc;
   
         __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);          __ASSERT((unsigned int)idx < CPU_SEGREG_NUM);
   
         sd = &CPU_STAT_SREG(idx);          sd = &CPU_STAT_SREG(idx);
         if (!sd->valid) {          if (!sd->valid) {
                 EXCEPTION(GP_EXCEPTION, 0);                  exc = GP_EXCEPTION;
                   goto err;
         }          }
   
   #ifndef AS32_NOCHECK
         if (!CPU_INST_AS32)          if (!CPU_INST_AS32)
                 madr &= 0xffff;                  offset &= 0xffff;
         for (;;) {  #endif
                 if ((sd->flag & CPU_DESC_WRITABLE)          if (!(sd->flag & CPU_DESC_FLAG_WRITABLE)) {
                     || (madr <= sd->u.seg.segend - 3)) {                  cpu_memorywrite_check(sd, offset, 4,
                         addr = CPU_STAT_SREGBASE(idx) + madr;                      (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);
                         if (!CPU_STAT_PM) {          } else {
                                 /* real mode */                  switch (sd->type) {
                                 cpu_memorywrite_d(addr, val);                  case 6: case 7:
                         } else {                          if (offset - 3 <= sd->u.seg.limit) {
                                 /* protected mode */                                  if (idx == CPU_SS_INDEX)
                                 cpu_lmemorywrite_d(addr, val);                                          exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                         }                          }
                         return;                          break;
   
                   default:
                           if (offset > sd->u.seg.limit - 3) {
                                   if (idx == CPU_SS_INDEX)
                                           exc = SS_EXCEPTION;
                                   else
                                           exc = GP_EXCEPTION;
                                   goto err;
                           }
                           break;
                 }                  }
                 cpu_memorywrite_check(sd, madr, 4,  
                     (idx == CPU_SS_INDEX) ? SS_EXCEPTION : GP_EXCEPTION);  
         }          }
         /*NOTREACHED*/          addr = CPU_STAT_SREGBASE(idx) + offset;
           if (!CPU_STAT_PM) {
                   /* real mode */
                   cpu_memorywrite_d(addr, val);
           } else {
                   /* protected mode */
                   cpu_lmemorywrite_d(addr, val);
           }
           return;
   
   err:
           EXCEPTION(exc, 0);
 }  }
   
 /*  /*
Line 501  void MEMCALL Line 699  void MEMCALL
 cpu_memorywrite_d(DWORD address, DWORD value)  cpu_memorywrite_d(DWORD address, DWORD value)
 {  {
         DWORD adr = address & CPU_STAT_ADRSMASK;          DWORD adr = address & CPU_STAT_ADRSMASK;
           DWORD diff;
           DWORD off;
   
         if (adr < LOWMEM - 3) {          if (adr < LOWMEM - 3) {
                 __i286_memorywrite_d(adr, value);                  __i286_memorywrite_d(adr, value);
         } else if (adr < LOWMEM) {          } else if (adr < LOWMEM) {
                 cpu_memorywrite_w(adr, value & 0xffff);                  diff = LOWMEM - adr;
                 cpu_memorywrite_w(adr + 2, (value >> 16) & 0xffff);  
         } else {                  switch (diff) {
                   default:
                           ia32_panic("cpu_memorywrite_d: diff(%d)", diff);
                           break;
   
                   case 3:
                           __i286_memorywrite_w(adr, value & 0xffff);
                           value >>= 16;
                           __i286_memorywrite(adr + 2, value & 0xff);
                           value >>= 8;
                           break;
   
                   case 2:
                           __i286_memorywrite_w(adr, value & 0xffff);
                           value >>= 16;
                           break;
   
                   case 1:
                           __i286_memorywrite(adr, value & 0xff);
                           value >>= 8;
                           break;
                   }
   
                   if (extmem_size > 0) {
                           off = 0;
   
                           switch (4 - diff) {
                           case 3:
                                   cpumem[off++] = value & 0xff;
                                   value >>= 8;
                                   if (off >= extmem_size) {
                                           OVERRUN_EXCEPTION();
                                           break;
                                   }
                                   /*FALLTHROUGH*/
                           case 2:
                                   cpumem[off++] = value & 0xff;
                                   if (off >= extmem_size) {
                                           OVERRUN_EXCEPTION();
                                           break;
                                   }
                                   value >>= 8;
                                   /*FALLTHROUGH*/
                           case 1:
                                   cpumem[off] = value & 0xff;
                                   break;
                           }
                   } else {
                           OVERRUN_EXCEPTION();
                   }
           } else if (extmem_size > 0) {
                 adr -= LOWMEM;                  adr -= LOWMEM;
                 if (adr < extmem_size - 3) {                  if (adr < extmem_size - 3) {
                         STOREINTELDWORD(cpumem + adr, value);                          STOREINTELDWORD(cpumem + adr, value);
                 } else if (adr < extmem_size) {                  } else if (adr < extmem_size) {
                         cpu_memorywrite_w(adr, value & 0xffff);                          diff = extmem_size - adr;
                         cpu_memorywrite_w(adr + 2, (value >> 16) & 0xffff);                          value >>= (8 * (4 - diff));
   
                           switch (diff) {
                           default:
                                   ia32_panic("cpu_memorywrite_d: diff(%d)", diff);
                                   break;
   
                           case 3:
                                   cpumem[extmem_size - 3] = value & 0xff;
                                   value >>= 8;
                                   /*FALLTHROUGH*/
                           case 2:
                                   cpumem[extmem_size - 2] = value & 0xff;
                                   value >>= 8;
                                   /*FALLTHROUGH*/
                           case 1:
                                   cpumem[extmem_size - 1] = value & 0xff;
                                   break;
                           }
                           OVERRUN_EXCEPTION();
                   } else {
                           OVERRUN_EXCEPTION();
                 }                  }
           } else {
                   OVERRUN_EXCEPTION();
         }          }
 }  }
   
Line 528  cpu_memorywrite_w(DWORD address, WORD va Line 801  cpu_memorywrite_w(DWORD address, WORD va
         } else if (adr < LOWMEM) {          } else if (adr < LOWMEM) {
                 __i286_memorywrite(adr, value & 0xff);                  __i286_memorywrite(adr, value & 0xff);
                 cpumem[adr - (LOWMEM - 1)] = (value >> 8) & 0xff;                  cpumem[adr - (LOWMEM - 1)] = (value >> 8) & 0xff;
         } else {          } else if (extmem_size > 0) {
                 adr -= LOWMEM;                  adr -= LOWMEM;
                 if (adr < extmem_size - 1) {                  if (adr < extmem_size - 1) {
                         STOREINTELWORD(cpumem + adr, value);                          STOREINTELWORD(cpumem + adr, value);
                 } else if (adr == extmem_size - 1) {                  } else if (adr == extmem_size - 1) {
                         cpumem[adr] = value & 0xff;                          cpumem[adr] = value & 0xff;
                           OVERRUN_EXCEPTION();
                   } else {
                           OVERRUN_EXCEPTION();
                 }                  }
           } else {
                   OVERRUN_EXCEPTION();
         }          }
 }  }
   
Line 545  cpu_memorywrite(DWORD address, BYTE valu Line 823  cpu_memorywrite(DWORD address, BYTE valu
   
         if (adr < LOWMEM) {          if (adr < LOWMEM) {
                 __i286_memorywrite(adr, value);                  __i286_memorywrite(adr, value);
         } else {          } else if (extmem_size > 0) {
                 adr -= LOWMEM;                  adr -= LOWMEM;
                 if (adr < extmem_size) {                  if (adr < extmem_size) {
                         cpumem[adr] = value;                          cpumem[adr] = value;
                   } else {
                           OVERRUN_EXCEPTION();
                 }                  }
           } else {
                   OVERRUN_EXCEPTION();
         }          }
 }  }
   
Line 558  cpu_memoryread_d(DWORD address) Line 840  cpu_memoryread_d(DWORD address)
 {  {
         DWORD adr = address & CPU_STAT_ADRSMASK;          DWORD adr = address & CPU_STAT_ADRSMASK;
         DWORD val;          DWORD val;
           DWORD diff;
   
         if (adr < LOWMEM - 3) {          if (adr < LOWMEM - 3) {
                 val = __i286_memoryread_d(adr);                  val = __i286_memoryread_d(adr);
         } else if (adr < LOWMEM) {          } else if (adr < LOWMEM) {
                 val = cpu_memoryread_w(adr);                  diff = LOWMEM - adr;
                 val |= (DWORD)cpu_memoryread_w(adr + 2) << 16;  
         } else {                  switch (diff) {
                   default:
                           ia32_panic("cpu_memoryread_d: diff(%d)", diff);
                           val = 0;        /* compiler happy */
                           break;
   
                   case 3:
                           val = __i286_memoryread_w(adr);
                           val |= __i286_memoryread(adr + 2);
                           if (extmem_size > 0) {
                                   val |= cpumem[0] << 24;
                           } else {
                                   val |= 0xff000000;
                                   OVERRUN_EXCEPTION();
                           }
                           break;
   
                   case 2:
                           val = __i286_memoryread_w(adr);
                           if (extmem_size > 1) {
                                   val |= (DWORD)LOADINTELWORD(cpumem) << 16;
                           } else {
                                   val |= 0xffff0000;
                                   OVERRUN_EXCEPTION();
                           }
                           break;
   
                   case 1:
                           val = __i286_memoryread(adr);
                           if (extmem_size > 2) {
                                   val |= (DWORD)LOADINTELWORD(cpumem) << 8;
                                   val |= (DWORD)cpumem[2] << 24;
                           } else {
                                   val |= 0xffffff00;
                                   OVERRUN_EXCEPTION();
                           }
                           break;
                   }
           } else if (extmem_size > 0) {
                 adr -= LOWMEM;                  adr -= LOWMEM;
                 if (adr < extmem_size - 3) {                  if (adr < extmem_size - 3) {
                         val = LOADINTELDWORD(cpumem + adr);                          val = LOADINTELDWORD(cpumem + adr);
                   } else if (adr < extmem_size) {
                           diff = extmem_size - adr;
                           val = 0;
   
                           switch (diff) {
                           default:
                                   ia32_panic("cpu_memoryread_d: diff(%d)", diff);
                                   break;
   
                           case 3:
                                   val |= cpumem[extmem_size - 3];
                                   /*FALLTHROUGH*/
                           case 2:
                                   val |= (cpumem[extmem_size - 2] << (8 * (diff - 2)));
                                   /*FALLTHROUGH*/
                           case 1:
                                   val |= (cpumem[extmem_size - 1] << (8 * (diff - 1)));
                                   break;
                           }
                           val |= ((DWORD)-1) << (8 * diff);
                           OVERRUN_EXCEPTION();
                 } else {                  } else {
                         val = cpu_memoryread_w(adr);                          val = (DWORD)-1;
                         val |= (DWORD)cpu_memoryread_w(adr + 2) << 16;                          OVERRUN_EXCEPTION();
                 }                  }
           } else {
                   val = (DWORD)-1;
                   OVERRUN_EXCEPTION();
         }          }
         return val;          return val;
 }  }
Line 585  cpu_memoryread_w(DWORD address) Line 930  cpu_memoryread_w(DWORD address)
         if (adr < LOWMEM - 1) {          if (adr < LOWMEM - 1) {
                 val = __i286_memoryread_w(adr);                  val = __i286_memoryread_w(adr);
         } else if (adr < LOWMEM) {          } else if (adr < LOWMEM) {
                 val = cpu_memoryread(adr);                  val = __i286_memoryread(adr);
                 val |= (WORD)cpumem[adr - (LOWMEM - 1)] << 8;                  val |= (WORD)cpumem[0] << 8;
         } else {          } else if (extmem_size > 0) {
                 adr -= LOWMEM;                  adr -= LOWMEM;
                 if (adr < extmem_size - 1) {                  if (adr < extmem_size - 1) {
                         val = LOADINTELWORD(cpumem + adr);                          val = LOADINTELWORD(cpumem + adr);
                 } else if (adr == extmem_size - 1) {                  } else if (adr == extmem_size - 1) {
                         val = 0xff00 | cpumem[adr];                          val = 0xff00 | cpumem[adr];
                           OVERRUN_EXCEPTION();
                 } else {                  } else {
                         val = (WORD)-1;                          val = (WORD)-1;
                           OVERRUN_EXCEPTION();
                 }                  }
           } else {
                   val = (WORD)-1;
                   OVERRUN_EXCEPTION();
         }          }
         return val;          return val;
 }  }
Line 608  cpu_memoryread(DWORD address) Line 958  cpu_memoryread(DWORD address)
   
         if (adr < LOWMEM) {          if (adr < LOWMEM) {
                 val = __i286_memoryread(adr);                  val = __i286_memoryread(adr);
         } else {          } else if (extmem_size > 0) {
                 adr -= LOWMEM;                  adr -= LOWMEM;
                 if (adr < extmem_size) {                  if (adr < extmem_size) {
                         val = cpumem[adr];                          val = cpumem[adr];
                 } else {                  } else {
                         val = (BYTE)-1;                          val = (BYTE)-1;
                           OVERRUN_EXCEPTION();
                 }                  }
           } else {
                   val = (BYTE)-1;
                   OVERRUN_EXCEPTION();
         }          }
         return val;          return val;
 }  }

Removed from v.1.4  
changed lines
  Added in v.1.7


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