📄 physicaladdressspace.java
字号:
/* JPC: A x86 PC Hardware Emulator for a pure Java Virtual Machine Release Version 2.0 A project from the Physics Dept, The University of Oxford Copyright (C) 2007 Isis Innovation Limited This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Details (including contact information) can be found at: www.physics.ox.ac.uk/jpc*/package org.jpc.emulator.memory;import java.util.*;import java.io.*;import org.jpc.emulator.*;import org.jpc.emulator.memory.codeblock.*;import org.jpc.emulator.processor.Processor;public final class PhysicalAddressSpace extends AddressSpace implements HardwareComponent{ private static final int GATEA20_MASK = 0xffefffff; private static final int QUICK_INDEX_SIZE = PC.SYS_RAM_SIZE >>> INDEX_SHIFT; private static final int TOP_INDEX_BITS = (32 - INDEX_SHIFT) / 2; private static final int BOTTOM_INDEX_BITS = 32 - INDEX_SHIFT - TOP_INDEX_BITS; private static final int TOP_INDEX_SHIFT = 32 - TOP_INDEX_BITS; private static final int TOP_INDEX_SIZE = 1 << TOP_INDEX_BITS; private static final int TOP_INDEX_MASK = TOP_INDEX_SIZE - 1; private static final int BOTTOM_INDEX_SHIFT = 32 - TOP_INDEX_BITS - BOTTOM_INDEX_BITS; private static final int BOTTOM_INDEX_SIZE = 1 << BOTTOM_INDEX_BITS; private static final int BOTTOM_INDEX_MASK = BOTTOM_INDEX_SIZE - 1; private boolean gateA20MaskState; private int mappedRegionCount; private Memory[] quickNonA20MaskedIndex, quickA20MaskedIndex, quickIndex; private Memory[][] nonA20MaskedIndex, a20MaskedIndex, index; public static final Memory UNCONNECTED = new UnconnectedMemoryBlock(); private LinearAddressSpace linearAddr; public PhysicalAddressSpace() { mappedRegionCount = 0; quickNonA20MaskedIndex = new Memory[QUICK_INDEX_SIZE]; clearArray(quickNonA20MaskedIndex, UNCONNECTED); quickA20MaskedIndex = new Memory[QUICK_INDEX_SIZE]; clearArray(quickA20MaskedIndex, UNCONNECTED); nonA20MaskedIndex = new Memory[TOP_INDEX_SIZE][]; a20MaskedIndex = new Memory[TOP_INDEX_SIZE][]; setGateA20State(false); } private void dumpMemory(DataOutput output, Memory[] mem) throws IOException { long len; byte[] temp = new byte[0]; for (int i = 0; i< mem.length; i++) { len = mem[i].getSize(); if (temp.length < (int) len) temp = new byte[(int) len]; if (mem[i].isAllocated()) { try { if (mem[i] instanceof MapWrapper) { len = 0; } else mem[i].copyContentsInto(0, temp, 0, (int) len); } catch (IllegalStateException e) { len = 0; } output.writeLong(len); if (len > 0 ) output.write(temp); } else { output.writeLong(0); } } } private void dumpLotsOfMemory(DataOutput output, Memory[][] mem) throws IOException { output.writeInt(mem.length); for (int i =0; i < mem.length; i++) { if (mem[i] == null) output.writeInt(0); else { dumpMemory(output, mem[i]); } } } public void dumpState(DataOutput output) throws IOException { output.writeBoolean(gateA20MaskState); output.writeInt(mappedRegionCount); output.writeInt(quickA20MaskedIndex.length); dumpMemory(output, quickA20MaskedIndex); output.writeInt(quickNonA20MaskedIndex.length); dumpMemory(output, quickNonA20MaskedIndex); if (quickIndex == quickNonA20MaskedIndex) output.writeInt(1); else output.writeInt(2); dumpLotsOfMemory(output, nonA20MaskedIndex); dumpLotsOfMemory(output, a20MaskedIndex); if (index == nonA20MaskedIndex) output.writeInt(1); else output.writeInt(2); } private void loadMemory(DataInput input, Memory[] mem, int size) throws IOException { long len; byte[] temp; for (int i = 0; i< size; i++) { len = input.readLong(); temp = new byte[(int) len]; if (len > 0) { input.readFully(temp, 0, (int) len); mem[i].copyContentsFrom(0, temp, 0, (int) len); } } } private void loadLotsOfMemory(DataInput input, Memory[][] mem) throws IOException { int width = input.readInt(); int len = 0; //mem = new Memory[width][]; for (int i = 0; i < width; i++) { loadMemory(input, mem[i], len); } } public void loadState(DataInput input) throws IOException { clearArray(quickA20MaskedIndex, UNCONNECTED); clearArray(quickNonA20MaskedIndex, UNCONNECTED); clearArray(quickIndex, UNCONNECTED); reset(); for (int i=0; i<PC.SYS_RAM_SIZE; i+= AddressSpace.BLOCK_SIZE) allocateMemory(i, new LazyMemory(AddressSpace.BLOCK_SIZE)); gateA20MaskState = input.readBoolean(); mappedRegionCount = input.readInt(); int size = input.readInt(); loadMemory(input, quickA20MaskedIndex, size); size = input.readInt(); loadMemory(input, quickNonA20MaskedIndex, size); int which = input.readInt(); if (which == 1) quickIndex = quickNonA20MaskedIndex; else quickIndex = quickA20MaskedIndex; loadLotsOfMemory(input, nonA20MaskedIndex); loadLotsOfMemory(input, a20MaskedIndex); which = input.readInt(); if (which == 1) index = nonA20MaskedIndex; else index = a20MaskedIndex; } public void setGateA20State(boolean value) { gateA20MaskState = value; if (value) { quickIndex = quickNonA20MaskedIndex; index = nonA20MaskedIndex; } else { quickIndex = quickA20MaskedIndex; index = a20MaskedIndex; } if ((linearAddr != null) && !linearAddr.pagingDisabled()) linearAddr.flush(); } public boolean getGateA20State() { return gateA20MaskState; } public int getAllocatedBufferSize() { return mappedRegionCount * BLOCK_SIZE; } public Memory getReadMemoryBlockAt(int offset) { return getMemoryBlockAt(offset); } public Memory getWriteMemoryBlockAt(int offset) { return getMemoryBlockAt(offset); } public int execute(Processor cpu, int offset) { return getReadMemoryBlockAt(offset).execute(cpu, offset & AddressSpace.BLOCK_MASK); } public CodeBlock decodeCodeBlockAt(Processor cpu, int offset) { CodeBlock block=getReadMemoryBlockAt(offset).decodeCodeBlockAt(cpu, offset & AddressSpace.BLOCK_MASK); return block; } void replaceBlocks(Memory oldBlock, Memory newBlock) { for (int i = 0; i < quickA20MaskedIndex.length; i++) if (quickA20MaskedIndex[i] == oldBlock) quickA20MaskedIndex[i] = newBlock; for (int i = 0; i < quickNonA20MaskedIndex.length; i++) if (quickNonA20MaskedIndex[i] == oldBlock) quickNonA20MaskedIndex[i] = newBlock; for (int i = 0; i < a20MaskedIndex.length; i++) { Memory[] subArray = a20MaskedIndex[i]; try { for (int j = 0; j < subArray.length; j++) if (subArray[j] == oldBlock) subArray[j] = newBlock; } catch (NullPointerException e) {} } for (int i = 0; i < nonA20MaskedIndex.length; i++) { Memory[] subArray = nonA20MaskedIndex[i]; try { for (int j = 0; j < subArray.length; j++) if (subArray[j] == oldBlock) subArray[j] = newBlock; } catch (NullPointerException e) {} } } public static class MapWrapper extends Memory { private Memory memory; private int baseAddress; MapWrapper(Memory mem, int base) { baseAddress = base; memory = mem; } public long getSize() { return BLOCK_SIZE; } public void clear() { memory.clear(baseAddress, (int)getSize()); } public void clear(int start, int length) { if (start + length > getSize()) throw new ArrayIndexOutOfBoundsException("Attempt to clear outside of memory bounds"); start = baseAddress | start; memory.clear(start, length); } public void copyContentsInto(int offset, byte[] buffer, int off, int len) { offset = baseAddress | offset; memory.copyContentsInto(offset, buffer, off, len); } public void copyContentsFrom(int offset, byte[] buffer, int off, int len) { offset = baseAddress | offset; memory.copyContentsFrom(offset, buffer, off, len); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -