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; }