/*
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.decoder;
import org.jpc.emulator.PC;
import org.jpc.emulator.execution.*;
import org.jpc.emulator.execution.codeblock.CodeBlock;
import org.jpc.emulator.processor.*;
import org.jpc.j2se.Option;
import static org.jpc.emulator.execution.Executable.*;
public class BasicBlock implements CodeBlock
{
public static final boolean LOG_BLOCKENTRY = Option.log_blockentry.value();
public static final boolean LOG_STATE = Option.log_state.value();
public static final boolean SINGLE_STEP_TIME = Option.singlesteptime.value();
public static final int MIN_ADDR_WATCH = Option.min_addr_watch.intValue(0);
public static final int MAX_ADDR_WATCH = Option.max_addr_watch.intValue(0xffffffff);
public static int lastExitEip;
public Executable start;
public BasicBlock link1, link2;
public final int x86Length, x86Count;
public BasicBlock(Executable start, int x86Length, int x86Count)
{
this.start = start;
this.x86Length = x86Length;
this.x86Count = x86Count;
if (x86Count == 0)
throw new IllegalStateException("Block with zero x86Count!");
}
public void preBlock(Processor cpu)
{
if (LOG_BLOCKENTRY)
System.out.printf("***** %08x:%08x\n", cpu.cs.getBase(), cpu.eip);
if (PC.HISTORY)
PC.logBlock(cpu.getInstructionPointer(), this);
}
public void postBlock(Processor cpu)
{
if (PC.HISTORY)
lastExitEip = cpu.getInstructionPointer();
}
private boolean watchedAddress(int addr)
{
if (addr < MIN_ADDR_WATCH)
return false;
if ((addr & 0xFFFFFFFFL) > (MAX_ADDR_WATCH & 0xFFFFFFFFL))
return false;
return true;
}
public void postInstruction(Processor cpu, Executable last)
{
if ((LOG_STATE) && watchedAddress(cpu.getInstructionPointer()))
{
System.out.println("\t"+last);
State.print(cpu);
}
if ((SINGLE_STEP_TIME) && !last.toString().contains("eip"))
cpu.vmClock.update(1);
cpu.rf(false);
}
public Branch execute(Processor cpu)
{
Executable current = start;
Executable.Branch ret;
preBlock(cpu);
while ((ret = current.execute(cpu)) == Executable.Branch.None)
{
postInstruction(cpu, current);
current = current.next;
}
postInstruction(cpu, current);
postBlock(cpu);
return ret;
}
public int getX86Length()
{
return x86Length;
}
public int getX86Count()
{
return x86Count;
}
public boolean handleMemoryRegionChange(int startAddress, int endAddress)
{
return false;
}
public String getDisplayString()
{
return toString();
}
public Instruction getInstructions()
{
return null;
}
}