⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flatmem.c

📁 realview22.rar
💻 C
📖 第 1 页 / 共 4 页
字号:
      /* top->p_ABus->bus_BusyUntil++; */
  }

  if ((address >= top->LowestPeripheralAddress) &&
      (address <= top->HighestPeripheralAddress) &&
      (rv = peripheral_access(handle,address,data,acc)) != -2)
  {
      return rv;
  }

  pageno=address>>PAGEBITS;
  page=top->mem.page[pageno];

  if (page==NULL) {
      top->mem.page[pageno]=page=NewPage(top,address);
  }
  offset = address & OFFSETBITS_WORD;
  ptr=(ARMword *)((char *)(page->memory)+offset);


  if (acc==acc_LoadInstrS) {
    *data=*ptr;
    return 1;
  } else if (acc_MREQ(acc)) {
    if (acc_READ(acc)) {
      switch (acc & WIDTH_MASK) {
      case BITS_8:              /* read byte */
        if (HostEndian!=top->read_bigend) address^=3;
        *data = ((unsigned8 *)ptr)[address & 3];
        break;
        
      case BITS_16: {           /* read half-word */
        /* extract half-word */
#ifndef HOST_HAS_NO_16BIT_TYPE
        /*
         * unsigned16 is always a 16-bit type, but if there is no native
         * 16-bit type (e.g. ARM!) then we can do something a bit more
         * cunning.
         */
        if (HostEndian!=top->read_bigend) address^=2;
        *data = *((unsigned16 *)(((char *)ptr)+(address & 2)));
#else
        unsigned32 datum;
        datum=*ptr;
        if (HostEndian!=top->read_bigend) address^=2;
        if (address & 2) datum<<=16;
        *data = (datum>>16);
#endif
      }
        break;
        
      case BITS_32:             /* read word */
        *data=*ptr;
        break;

      case BITS_64:             /* read dword */
        *data=*ptr;
        if ((offset+4) & OFFSETBITS_WORD) 
        {
            data[1]=ptr[1];
            return 2;
        }
        break;

      default:
          return_PERIP_DABORT;
      }
    } else {
      switch (acc & WIDTH_MASK) {
        /* extract byte */
      case BITS_8:              /* write_byte */
        if (HostEndian!=top->write_bigend) address^=3;
        ((unsigned8 *)ptr)[address & 3]=(unsigned8)(*data);
        break;
        
      case BITS_16:             /* write half-word */
        if (HostEndian!=top->write_bigend) address^=2;
        *((unsigned16 *)(((char *)ptr)+(address & 2))) = (unsigned16)(*data);
        break;

      case BITS_32:             /* write word */
        *ptr=*data;
        break;

      case BITS_64:             /* write dword */
        *ptr=*data;
        if ((offset+4) &OFFSETBITS_WORD) 
        {
            ptr[1]=data[1];
            return 2;
        }
        break;

      default:
          return_PERIP_DABORT;
      }
    }                           /* internal cycle */
  }

  return 1;
}



#ifdef PIPELINED
/*
 * This function gets called before every memory access with the address and
 * cycle type for the next cycle.
 */
static void NextCycle(void *handle,
                     ARMword address,
                     ARMul_acc acc)
{
  /* armflat does not make use of pipelined addresses */
  UNUSEDARG(handle); UNUSEDARG(address); UNUSEDARG(acc);
}
#endif /* PIPELINED */


#if 1
# define CHECKTOTAL
#else
      /* ... This only works if we are called for every cycle ... */
# define CHECKTOTAL \
      assert(top->p_ABus->bus_BusyUntil == \
             (top->cycles.NumNcycles + top->cycles.NumScycles +\
              top->cycles.NumIcycles+top->cycles.NumCcycles));
#endif

/*
 * This is the most basic memory access function - an ARM610/ARM710 interface.
 *
 * Optimised for word loads and idle cycles
 */
static int MemAccessCached(void *handle,
                           ARMword address,
                           ARMword *data,
                           ARMul_acc acc)
{
  toplevel *top=(toplevel *)handle;
  unsigned int pageno;
  mempage *page;
  ARMword *ptr;
  ARMword offset;
  int rv;

  if (acc_ACCOUNT(acc)) {
      COUNTCYCLES(top->cycles,acc);
      /* top->p_ABus->bus_BusyUntil++; */
      CHECKTOTAL
  }

  if ((address >= top->LowestPeripheralAddress) &&
      (address <= top->HighestPeripheralAddress) &&
      (rv = peripheral_access(handle,address,data,acc)) != -2)
  {
      return rv;
  }


  if (ACCESS_IS_IDLE(acc))
      return 1;

  pageno=address>>PAGEBITS;
  page=top->mem.page[pageno];

  /* !TODO: if (page==dummyPage && ACCESS_IS_WRITE)... */
  if (page==NULL) 
  {
    top->mem.page[pageno]=page=NewPage(top,address);
  }
  offset = address & OFFSETBITS_WORD;
  ptr=(ARMword *)((char *)(page->memory)+offset);

  if (acc==acc_LoadWordS) {
    *data=*ptr;
    return 1;
  } else if (acc_MREQ(acc)) {
    if (acc_READ(acc)) {
      switch (acc & WIDTH_MASK) {
      case BITS_8:              /* read byte */
        if (HostEndian!=top->read_bigend) address^=3;
        *data = ((unsigned8 *)ptr)[address & 3];
        break;
        
      case BITS_16: {           /* read half-word */
        /* extract half-word */
#ifndef HOST_HAS_NO_16BIT_TYPE
        /*
         * unsigned16 is always a 16-bit type, but if there is no native
         * 16-bit type (e.g. ARM!) then we can do something a bit more
         * cunning.
         */
        if (HostEndian!=top->read_bigend) address^=2;
        *data = *((unsigned16 *)(((char *)ptr)+(address & 2)));
#else
        unsigned32 datum;
        datum=*ptr;
        if (HostEndian!=top->read_bigend) address^=2;
        if (address & 2) datum<<=16;
        *data = (datum>>16);
#endif
      }
        break;
        
      case BITS_32:             /* read word */
        *data=*ptr;
        break;

      case BITS_64:             /* read dword */
        *data=*ptr;
        if ((offset+4) & OFFSETBITS_WORD) 
        {
            data[1]=ptr[1];
            return 2;
        }
        break;

      default:
          return_PERIP_DABORT;
      }
    } else {
      switch (acc & WIDTH_MASK) {
        /* extract byte */
      case BITS_8:              /* write_byte */
        if (HostEndian!=top->write_bigend) address^=3;
        ((unsigned8 *)ptr)[address & 3]=(unsigned8)(*data);
        break;
        
      case BITS_16:             /* write half-word */
        if (HostEndian!=top->write_bigend) address^=2;
        *((unsigned16 *)(((char *)ptr)+(address & 2))) = (unsigned16)(*data);
        break;

      case BITS_32:             /* write word */
        *ptr=*data;
        break;


      case BITS_64:             /* write dword */
        *ptr=*data;
        if ((offset+4) &OFFSETBITS_WORD) 
        {
            ptr[1]=data[1];
            return 2;
        }
        break;

      default:
          return_PERIP_DABORT;
      }
    }                           /* internal cycle */
  }

  return 1;
}

/*
 * Same function, but optimised for Thumb accesses
 */
static int MemAccessThumb(void *handle,
                          ARMword address,
                          ARMword *data,
                          ARMul_acc acc)
{
  toplevel *top=(toplevel *)handle;
  unsigned int pageno;
  mempage *page;
  ARMword *ptr;
  ARMword offset;
  int rv;


  if (acc_ACCOUNT(acc)) {
      COUNTCYCLES(top->cycles,acc);
      /* top->p_ABus->bus_BusyUntil++; */
      CHECKTOTAL
  }

  if ((address >= top->LowestPeripheralAddress) &&
      (address <= top->HighestPeripheralAddress) &&
      (rv = peripheral_access(handle,address,data,acc)) != -2)
  {
      return rv;
  }

  pageno=address>>PAGEBITS;
  page=top->mem.page[pageno];

  if (page==NULL) {
    top->mem.page[pageno]=page=NewPage(top,address);
  }
  offset = address & OFFSETBITS_WORD;
  ptr=(ARMword *)((char *)(page->memory)+offset);
  switch (acc & (ACCESS_SIZE_MASK | ACCESS_IDLE | ACCESS_WRITE) ) 
    {
      case BITS_8:              /* read byte */
        *data = ((unsigned8 *)ptr)[(address ^ top->byteAddrXor) & 3];
        break;
        
      case BITS_16:           /* read half-word */
        *data = *((unsigned16 *)(((char *)ptr)+
                                 ((address ^ top->hwordAddrXor) & 2)));
        return 1;

      case BITS_32:             /* read word */
        *data=*ptr;
        return 1;

        /* This case should not be needed for MemAccessThumb,
        * but I intend to merge that with MemAccessCached. */
      case BITS_64:             /* read dword */
        *data=*ptr;
        if ((offset+4) & OFFSETBITS_WORD) 
        {
            data[1]=ptr[1];
            return 2;
        }
        break;


      case BITS_8 | ACCESS_WRITE:              /* write_byte */
        if (HostEndian!=top->write_bigend) address^=3;
        ((unsigned8 *)ptr)[address & 3]=(unsigned8)(*data);
        break;
        
      case BITS_16 | ACCESS_WRITE:             /* write half-word */
        if (HostEndian!=top->write_bigend) address^=2;
        *((unsigned16 *)(((char *)ptr)+(address & 2))) = (unsigned16)(*data);
        break;

      case BITS_32 | ACCESS_WRITE:             /* write word */
        *ptr=*data;
        break;

      case BITS_64  | ACCESS_WRITE:             /* write dword */
        *ptr=*data;
        if ((offset+4) &OFFSETBITS_WORD) 
        {
            ptr[1]=data[1];
            return 2; /* PERIP_OK2 */
        }
        break;

      case BITS_8 | ACCESS_IDLE:
      case BITS_16 | ACCESS_IDLE:
      case BITS_32 | ACCESS_IDLE:
      case BITS_64 | ACCESS_IDLE:
      case ACCESS_IDLE:
        return 1;
        
      default:
          return_PERIP_DABORT;
    }
  return 1;
}

#ifdef MEM_ACCESS2_DISTINCT /* F */
/*
 * This function is used by ARM8. Effectively we model a memory
 * system which can return two words per cycle.
 * The differences between this an a normal 64-bit bus (ARM10, XScale)
 * are
 * (1) 64-bit fetches need not be DWORD aligned.
 * (2) A non-aligned fetch just below a 64k-boundary may return just one word!
 */

static int MemAccess2(void *handle,
                      ARMword address,
                      ARMword *data,ARMword *data2,
                      ARMul_acc acc)
{
  toplevel *top=(toplevel *)handle;
  unsigned int pageno;
  mempage *page;
  ARMword *ptr;
  ARMword offset;
  int words=1;
  int rv;

  if (acc_ACCOUNT(acc)) {
      COUNTCYCLES(top->cycles,acc);
      /* top->p_ABus->bus_BusyUntil++; */
      CHECKTOTAL
  }

  if ((address >= top->LowestPeripheralAddress) &&
      (address <= top->HighestPeripheralAddress) &&
      (rv = peripheral_access(handle,address,data,acc)) != -2)
  {
      return rv;
  }

  pageno=address>>PAGEBITS;
  page=top->mem.page[pageno];

  if (page==NULL) {
      top->mem.page[pageno]=page=NewPage(top,address);
  }
  offset = address & OFFSETBITS_WORD;
  ptr=(ARMword *)((char *)(page->memory)+offset);

  if (acc_MREQ(acc)) {
    if (acc_READ(acc)) {
      switch (acc & WIDTH_MASK) {
      case BITS_8:              /* read byte */
        if (HostEndian!=top->read_bigend) address^=3;
        *data = ((unsigned8 *)ptr)[address & 3];
        break;
        
      case BITS_16: {           /* read half-word */
        /* extract half-word */
        if (HostEndian!=top->read_bigend) address^=2;
        *data = *((unsigned16 *)(((char *)ptr)+(address & 2)));
      }
        break;
        
      case BITS_32:             /* read word */
        *data=*ptr;
        break;

      case BITS_64:             /* read two words */
        *data=*ptr;
        if ((offset+4) & OFFSETBITS_WORD) { *data2=ptr[1]; words=2; }
        break;

      default:
          return_PERIP_DABORT;
      }
    } else {
      switch (acc & WIDTH_MASK) {
        /* extract byte */
      case BITS_8:              /* write_byte */
        if (HostEndian!=top->write_bigend) address^=3;
        ((unsigned8 *)ptr)[address & 3]=(unsigned8)(*data);
        break;
        
      case BITS_16:             /* write half-word */
        if (HostEndian!=top->write_bigend) address^=2;
        *((unsigned16 *)(((char *)ptr)+(address & 2)))=(unsigned16)(*data);
        break;

      case BITS_32:             /* write word */
        *ptr=*data;
        break;

      default:
          return_PERIP_DABORT;
      }
    }                           /* internal cycle */
  }

  return words;
}
#endif


/*
 * A memory model used by StrongARM. This only accounts
 * for cycles on opcode boundaries - i.e. we allow both a data
 * and an instruction fetch on one cycle.
 */

static int MemAccessSA(void *handle,
                       ARMword address,
                       ARMword *data,
                       ARMul_acc acc)
{
  toplevel *top=(toplevel *)handle;
  unsigned int pageno;
  mempage *page;
  ARMword *ptr;
  ARMword offset;
  int rv;

  /*
   * On StrongARM there are four types of cycle - we'll reuse
   * the four cycle counters for these:
   *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -