/*
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.execution.codeblock;
import java.util.logging.*;
import org.jpc.emulator.memory.Memory;
/**
* Provides the outer skin for the codeblock construction system.
* <p>
* If blocks are not found in memory, then they are requested from this class.
* @author Chris Dennis
*/
public class CodeBlockManager {
private static final Logger LOGGING = Logger.getLogger(CodeBlockManager.class.getName());
public static volatile int BLOCK_LIMIT = 1000;
private CodeBlockFactory realModeChain, protectedModeChain, virtual8086ModeChain;
private CodeBlockFactory compilingRealModeChain, compilingProtectedModeChain, compilingVirtual8086ModeChain;
private PeekableMemoryStream byteSourceStream;
private BackgroundCompiler bgc;
public CodeBlockManager()
{
byteSourceStream = new PeekableMemoryStream();
realModeChain = new DefaultCodeBlockFactory(new OptimisedCompiler(), BLOCK_LIMIT);
protectedModeChain = new DefaultCodeBlockFactory(new OptimisedCompiler(), BLOCK_LIMIT);
virtual8086ModeChain = new DefaultCodeBlockFactory(new OptimisedCompiler(), BLOCK_LIMIT);
bgc = new BackgroundCompiler(new OptimisedCompiler(), null);
compilingRealModeChain = new DefaultCodeBlockFactory(bgc, BLOCK_LIMIT);//realModeChain;
compilingProtectedModeChain = new DefaultCodeBlockFactory(bgc, BLOCK_LIMIT);//protectedModeChain;
compilingVirtual8086ModeChain = virtual8086ModeChain;
}
private RealModeCodeBlock tryRealModeFactory(CodeBlockFactory ff, Memory memory, int offset)
{
try {
byteSourceStream.set(memory, offset);
return ff.getRealModeCodeBlock(byteSourceStream);
} catch (ArrayIndexOutOfBoundsException e) {
throw new SpanningDecodeException(new SpanningRealModeCodeBlock(new CodeBlockFactory[]{realModeChain}));
}
}
private ProtectedModeCodeBlock tryProtectedModeFactory(CodeBlockFactory ff, Memory memory, int offset, boolean operandSizeFlag)
{
try {
byteSourceStream.set(memory, offset);
return ff.getProtectedModeCodeBlock(byteSourceStream, operandSizeFlag);
} catch (ArrayIndexOutOfBoundsException e) {
throw new SpanningDecodeException(new SpanningProtectedModeCodeBlock(new CodeBlockFactory[]{protectedModeChain}));
}
}
private Virtual8086ModeCodeBlock tryVirtual8086ModeFactory(CodeBlockFactory ff, Memory memory, int offset)
{
try {
byteSourceStream.set(memory, offset);
return ff.getVirtual8086ModeCodeBlock(byteSourceStream);
} catch (ArrayIndexOutOfBoundsException e) {
throw new SpanningDecodeException(new SpanningVirtual8086ModeCodeBlock(new CodeBlockFactory[]{virtual8086ModeChain}));
}
}
/**
* Get a real mode codeblock instance for the given memory area.
* @param memory source for the x86 bytes
* @param offset address in the given memory object
* @return real mode codeblock instance
*/
public RealModeCodeBlock getRealModeCodeBlockAt(Memory memory, int offset) {
RealModeCodeBlock block;
if ((block = tryRealModeFactory(compilingRealModeChain, memory, offset)) == null) {
if ((block = tryRealModeFactory(realModeChain, memory, offset)) == null) {
throw new IllegalStateException("Couldn't find capable block");
}
}
return block;
}
/**
* Get a protected mode codeblock instance for the given memory area.
* @param memory source for the x86 bytes
* @param offset address in the given memory object
* @param operandSize <code>true</code> for 32-bit, <code>false</code> for 16-bit
* @return protected mode codeblock instance
*/
public ProtectedModeCodeBlock getProtectedModeCodeBlockAt(Memory memory, int offset, boolean operandSize) {
ProtectedModeCodeBlock block;
if ((block = tryProtectedModeFactory(compilingProtectedModeChain, memory, offset, operandSize)) == null) {
if ((block = tryProtectedModeFactory(protectedModeChain, memory, offset, operandSize)) == null) {
throw new IllegalStateException("Couldn't find capable block");
}
}
return block;
}
/**
* Get a Virtual8086 mode codeblock instance for the given memory area.
* @param memory source for the x86 bytes
* @param offset address in the given memory object
* @return Virtual8086 mode codeblock instance
*/
public Virtual8086ModeCodeBlock getVirtual8086ModeCodeBlockAt(Memory memory, int offset) {
Virtual8086ModeCodeBlock block;
if ((block = tryVirtual8086ModeFactory(compilingVirtual8086ModeChain, memory, offset)) == null) {
if ((block = tryVirtual8086ModeFactory(virtual8086ModeChain, memory, offset)) == null) {
throw new IllegalStateException("Couldn't find capable block");
}
}
return block;
}
}