/*
JPC: An x86 PC Hardware Emulator for a pure Java Virtual Machine
Copyright (C) 2012-2013 Ian Preston
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/
End of licence header
*/
package org.jpc.emulator.execution.codeblock;
import org.jpc.emulator.execution.decoder.*;
import org.jpc.emulator.execution.*;
import org.jpc.emulator.execution.opcodes.pm.pushfd;
import org.jpc.emulator.processor.*;
import static org.jpc.emulator.execution.Executable.*;
public class InterpretedProtectedModeBlock implements ProtectedModeCodeBlock
{
private final BasicBlock b;
private boolean valid = true;
public InterpretedProtectedModeBlock(BasicBlock b)
{
this.b = b;
}
public int getX86Length() {
return b.getX86Length();
}
public int getX86Count() {
return b.getX86Count();
}
public Branch execute(Processor cpu)
{
Executable current = b.start;
Executable.Branch ret;
b.preBlock(cpu);
try
{
while ((ret = current.execute(cpu)) == Executable.Branch.None)
{
b.postInstruction(cpu, current);
if (!valid)
throw new SelfModifyingCodeException("Block modified itself!");
current = current.next;
}
b.postInstruction(cpu, current);
return ret;
} catch (ProcessorException e)
{
cpu.eip += current.delta;
if (current.isBranch()) // branches have already updated eip
cpu.eip -= getX86Length(); // so eip points at the branch that barfed
if (!e.pointsToSelf())
{
if (current.isBranch())
cpu.eip += getX86Length() - current.delta;
else
cpu.eip += current.next.delta - current.delta;
}
if (e.getType() != ProcessorException.Type.PAGE_FAULT)
{
/*System.out.println("cs selector = " + Integer.toHexString(cpu.cs.getSelector())
+ ", cs base = " + Integer.toHexString(cpu.cs.getBase()) + ", EIP = "
+ Integer.toHexString(cpu.eip));*/
}
cpu.handleProtectedModeException(e);
return Branch.Exception;
}
catch (ModeSwitchException e)
{
int count = 1;
Executable p = b.start;
while (p != current)
{
count++;
p = p.next;
}
e.setX86Count(count);
throw e;
}
catch (SelfModifyingCodeException e)
{
cpu.eip += current.next.delta;
return Branch.Exception;
}
finally
{
b.postBlock(cpu);
}
}
public String getDisplayString() {
return "Interpreted Protected Mode Block:\n"+b.getDisplayString();
}
public Instruction getInstructions() {
return b.getInstructions();
}
public boolean handleMemoryRegionChange(int startAddress, int endAddress) {
valid = b.handleMemoryRegionChange(startAddress, endAddress);
return valid;
}
}