Пример #1
0
  static private int translate(int virtAddr, int size, boolean writing) 
       throws MachineException {
    int i = 0;
    long vpn, offset;
    TranslationEntry entry;
    long pageFrame;
    int physAddr;

    if (Debug.isEnabled('a')) {
      if (writing) 
	Debug.printf('a', "\tTranslate 0x%x, %s: ", new Integer(virtAddr), 
		     "write");
      else
	Debug.printf('a', "\tTranslate 0x%x, %s: ", new Integer(virtAddr), 
		     "read");
    }

    // check for alignment errors
    if (((size == 4) && (virtAddr & 0x3) != 0) || 
	((size == 2) && (virtAddr & 0x1) != 0)) {
      Debug.println('a', "alignment problem at " + virtAddr + ", size " + size);
      throw new MachineException(exceptionNames[AddressErrorException], 
				 AddressErrorException);
    }
    
    // we must have either a TLB or a page table, but not both!
    Debug.ASSERT(tlb == null || pageTable == null);	
    Debug.ASSERT(tlb != null || pageTable != null);	

    // calculate the virtual page number, and offset within the page,
    // from the virtual address
    vpn = ((long) virtAddr & LOW32BITS) / PageSize;
    offset = ((long) virtAddr & LOW32BITS) % PageSize;
    
    if (tlb == null) {		// => page table => vpn is index into table
      if (vpn >= pageTableSize) {
	Debug.println('a', "virtual page # " + virtAddr + 
		    " too large for page table size " + pageTableSize);
	throw new MachineException(exceptionNames[AddressErrorException], 
				   AddressErrorException);
      } else if (!pageTable[(int)vpn].valid) {
	Debug.println('a', "virtual page # " + virtAddr + 
		    " too large for page table size " + pageTableSize);
	throw new MachineException(exceptionNames[PageFaultException], 
				   PageFaultException);
      }
      entry = pageTable[(int)vpn];
    } else {
      for (entry = null, i = 0; i < TLBSize; i++)
	if (tlb[i].valid && (tlb[i].virtualPage == vpn)) {
	  entry = tlb[i];			// FOUND!
	  break;
	}
      if (entry == null) {				// not found
	Debug.println('a', "** no valid TLB entry found for this virtual page!");

	// really, this is a TLB fault,
	// the page may be in memory,
	// but not in the TLB
	throw new MachineException(exceptionNames[PageFaultException], 
				   PageFaultException);
      }
    }

    if (entry.readOnly && writing) {	// trying to write to a read-only page
      Debug.println('a', virtAddr + " mapped read-only at " + i + " in TLB!");
      throw new MachineException(exceptionNames[ReadOnlyException], 
				 ReadOnlyException);
    }
    pageFrame = entry.physicalPage;

    // if the pageFrame is too big, there is something really wrong! 
    // An invalid translation was loaded into the page table or TLB. 
    if (pageFrame >= NumPhysPages) { 
      Debug.println('a', "*** frame " + pageFrame + " > " + NumPhysPages);
      throw new MachineException(exceptionNames[BusErrorException], 
				 BusErrorException);
    }
    entry.use = true;		// set the use, dirty bits
    if (writing)
	entry.dirty = true;
    physAddr = (int) (pageFrame * PageSize + offset);

    Debug.ASSERT((physAddr >= 0) && ((physAddr + size) <= MemorySize));
    if (Debug.isEnabled('a')) {
      Debug.printf('a', "phys addr = 0x%x\n", new Integer(physAddr));
    }

    return physAddr;
  }