/* JPC: An x86 PC Hardware Emulator for a pure Java Virtual Machine Release Version 2.4 A project from the Physics Dept, The University of Oxford Copyright (C) 2007-2010 The University of Oxford 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: jpc.sourceforge.net or the developer website sourceforge.net/projects/jpc/ Conceived and Developed by: Rhys Newman, Ian Preston, Chris Dennis End of licence header */ package org.jpc.emulator.processor; import org.jpc.emulator.memory.*; import java.io.*; import static org.jpc.emulator.processor.ProtectedModeSegment.*; /** * * @author Chris Dennis */ public class SegmentFactory { private static final long DESCRIPTOR_TYPE = 0x100000000000L; private static final long SEGMENT_TYPE = 0xf0000000000L; public static final Segment NULL_SEGMENT = new NullSegment(); private SegmentFactory() { } public static Segment createRealModeSegment(AddressSpace memory, int selector) { if (memory == null) throw new NullPointerException("Null reference to memory"); return new RealModeSegment(memory, selector); } public static Segment createRealModeSegment(AddressSpace memory, Segment ancestor) { if (memory == null) throw new NullPointerException("Null reference to memory"); return new RealModeSegment(memory, ancestor); } public static Segment createVirtual8086ModeSegment(AddressSpace memory, int selector, boolean isCode) { if (memory == null) throw new NullPointerException("Null reference to memory"); return new Virtual8086ModeSegment(memory, selector, isCode); } public static Segment createDescriptorTableSegment(AddressSpace memory, int base, int limit) { if (memory == null) throw new NullPointerException("Null reference to memory"); return new DescriptorTableSegment(memory, base, limit); } public static Segment createProtectedModeSegment(AddressSpace memory, int selector, long descriptor) { return createProtectedModeSegment(memory, selector, descriptor, false); } public static Segment createProtectedModeSegment(AddressSpace memory, int selector, long descriptor, boolean isStack) { switch ((int) ((descriptor & (DESCRIPTOR_TYPE | SEGMENT_TYPE)) >>> 40)) { // System Segments default: case 0x00: //Reserved case 0x08: //Reserved case 0x0a: //Reserved case 0x0d: //Reserved throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0; case 0x01: //System Segment: 16-bit TSS (Available) return new ProtectedModeSegment.Available16BitTSS(memory, selector, descriptor); case 0x02: //System Segment: LDT return new ProtectedModeSegment.LDT(memory, selector, descriptor); case 0x03: //System Segment: 16-bit TSS (Busy) return new ProtectedModeSegment.Busy16BitTSS(memory, selector, descriptor); case 0x04: //System Segment: 16-bit Call Gate return new ProtectedModeSegment.CallGate16Bit(memory, selector, descriptor); case 0x05: //System Segment: Task Gate return new ProtectedModeSegment.TaskGate(memory, selector, descriptor); case 0x06: //System Segment: 16-bit Interrupt Gate return new ProtectedModeSegment.InterruptGate16Bit(memory, selector, descriptor); case 0x07: //System Segment: 16-bit Trap Gate return new ProtectedModeSegment.TrapGate16Bit(memory, selector, descriptor); case TYPE_AVAILABLE_32_TSS: //System Segment: 32-bit TSS (Available) return new ProtectedModeSegment.Available32BitTSS(memory, selector, descriptor); case TYPE_BUSY_32_TSS: //System Segment: 32-bit TSS (Busy) return new ProtectedModeSegment.Busy32BitTSS(memory, selector, descriptor); case 0x0c: //System Segment: 32-bit Call Gate return new ProtectedModeSegment.CallGate32Bit(memory, selector, descriptor); case 0x0e: //System Segment: 32-bit Interrupt Gate return new ProtectedModeSegment.InterruptGate32Bit(memory, selector, descriptor); case 0x0f: //System Segment: 32-bit Trap Gate return new ProtectedModeSegment.TrapGate32Bit(memory, selector, descriptor); // Data Segments case 0x10: //Data Segment: Read-Only if (isStack) return new ProtectedModeSegment.ReadOnlyDataStackSegment(memory, selector, descriptor); else return new ProtectedModeSegment.ReadOnlyDataSegment(memory, selector, descriptor); case 0x11: //Data Segment: Read-Only, Accessed if (isStack) return new ProtectedModeSegment.ReadOnlyAccessedStackSegment(memory, selector, descriptor); else return new ProtectedModeSegment.ReadOnlyAccessedDataSegment(memory, selector, descriptor); case 0x12: //Data Segment: Read/Write if (isStack) return new ProtectedModeSegment.ReadWriteStackSegment(memory, selector, descriptor); else return new ProtectedModeSegment.ReadWriteDataSegment(memory, selector, descriptor); case 0x13: //Data Segment: Read/Write, Accessed if (isStack) return new ProtectedModeSegment.ReadWriteAccessedStackSegment(memory, selector, descriptor); else return new ProtectedModeSegment.ReadWriteAccessedDataSegment(memory, selector, descriptor); case 0x14: //Data Segment: Read-Only, Expand-Down throw new IllegalStateException("Unimplemented Data Segment: Read-Only, Expand-Down"); case 0x15: //Data Segment: Read-Only, Expand-Down, Accessed throw new IllegalStateException("Unimplemented Data Segment: Read-Only, Expand-Down, Accessed"); case 0x16: //Data Segment: Read/Write, Expand-Down return new ProtectedModeExpandDownSegment.ReadWriteDataSegment(memory, selector, descriptor); case 0x17: //Data Segment: Read/Write, Expand-Down, Accessed throw new IllegalStateException("Unimplemented Data Segment: Read/Write, Expand-Down, Accessed"); // Code Segments case 0x18: //Code, Execute-Only return new ProtectedModeSegment.ExecuteOnlyCodeSegment(memory, selector, descriptor); case 0x19: //Code, Execute-Only, Accessed throw new IllegalStateException("Unimplemented Code Segment: Execute-Only, Accessed"); case 0x1a: //Code, Execute/Read return new ProtectedModeSegment.ExecuteReadCodeSegment(memory, selector, descriptor); case 0x1b: //Code, Execute/Read, Accessed return new ProtectedModeSegment.ExecuteReadAccessedCodeSegment(memory, selector, descriptor); case 0x1c: //Code: Execute-Only, Conforming throw new IllegalStateException("Unimplemented Code Segment: Execute-Only, Conforming"); case 0x1d: //Code: Execute-Only, Conforming, Accessed return new ProtectedModeSegment.ExecuteOnlyConformingAccessedCodeSegment(memory, selector, descriptor); case 0x1e: //Code: Execute/Read, Conforming return new ProtectedModeSegment.ExecuteReadConformingCodeSegment(memory, selector, descriptor); case 0x1f: //Code: Execute/Read, Conforming, Accessed return new ProtectedModeSegment.ExecuteReadConformingAccessedCodeSegment(memory, selector, descriptor); } } public static final class NullSegment extends Segment { public NullSegment() { super(null); } public void printState() { System.out.println("Null Segment"); } public void saveState(DataOutput output) throws IOException { output.writeInt(4); } public int getType() { throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0; } public int getSelector() { return 0; } public void checkAddress(int offset) { throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0; } public int translateAddressRead(int offset) { throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0; } public int translateAddressWrite(int offset) { throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0; } public void invalidateAddress(int offset) { throw new ProcessorException(ProcessorException.Type.GENERAL_PROTECTION, 0, true);//ProcessorException.GENERAL_PROTECTION_0; } public int getBase() { throw new IllegalStateException(getClass().toString()); } public int getLimit() { throw new IllegalStateException(getClass().toString()); } public int getRawLimit() { throw new IllegalStateException(getClass().toString()); } public boolean setSelector(int selector) { throw new IllegalStateException(getClass().toString()); } public int getDPL() { throw new IllegalStateException(getClass().toString()); } public int getRPL() { throw new IllegalStateException(getClass().toString()); } public void setRPL(int cpl) { throw new IllegalStateException(getClass().toString()); } public boolean getDefaultSizeFlag() { throw new IllegalStateException(getClass().toString()); } public boolean isPresent() { return true; } public boolean isSystem() { return false; } } }