/*
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 java.util.*;
/**
*
* @author Chris Dennis
*/
public final class ProcessorException extends RuntimeException
{
public static final ProcessorException DIVIDE_ERROR = new ProcessorException(Type.DIVIDE_ERROR, true);
public static final ProcessorException BOUND_RANGE = new ProcessorException(Type.BOUND_RANGE, true);
public static final ProcessorException UNDEFINED = new ProcessorException(Type.UNDEFINED, true);
public static final ProcessorException DOUBLE_FAULT_0 = new ProcessorException(Type.DOUBLE_FAULT, 0, true);
public static final ProcessorException STACK_SEGMENT_0 = new ProcessorException(Type.STACK_SEGMENT, 0, true);
public static final ProcessorException GENERAL_PROTECTION_0 = new ProcessorException(Type.GENERAL_PROTECTION, 0, true);
public static final ProcessorException FLOATING_POINT = new ProcessorException(Type.FLOATING_POINT, true);
public static final ProcessorException ALIGNMENT_CHECK_0 = new ProcessorException(Type.ALIGNMENT_CHECK, 0, true);
public static final ProcessorException NO_FPU = new ProcessorException(Type.NO_FPU, 0, true);
public static enum Type {
DIVIDE_ERROR(0x00),
DEBUG(0x01),
NMI(0x02),
BREAKPOINT(0x03),
OVERFLOW(0x04),
BOUND_RANGE(0x05),
UNDEFINED(0x06),
NO_FPU(0x07),
DOUBLE_FAULT(0x08),
FPU_SEGMENT_OVERRUN(0x09),
TASK_SWITCH(0x0a),
NOT_PRESENT(0x0b),
STACK_SEGMENT(0x0c),
GENERAL_PROTECTION(0x0d),
PAGE_FAULT(0x0e),
RESERVED(0x0f),
FLOATING_POINT(0x10),
ALIGNMENT_CHECK(0x11),
MACHINE_CHECK(0x12),
SIMD_FLOATING_POINT(0x13);
//Traps: BREAKPOINT, OVERFLOW
static Set<Type> traps = new HashSet();
static {
traps.add(BREAKPOINT);
traps.add(OVERFLOW);
traps.add(MACHINE_CHECK);
}
private final int vector;
Type(int vector)
{
this.vector = vector;
}
public boolean isTrap()
{
return traps.contains(this);
}
public int vector()
{
return vector;
}
}
public static boolean isFault(int vector)
{
if (vector >= Type.values().length)
return false;
return !Type.values()[vector].isTrap();
}
private final Type type;
private final int errorCode;
private final boolean pointsToSelf;
private final boolean hasErrorCode;
public ProcessorException(Type type, int errorCode, boolean pointsToSelf)
{
this.type = type;
this.hasErrorCode = true;
this.errorCode = errorCode;
this.pointsToSelf = pointsToSelf;
}
private ProcessorException(Type type, boolean pointsToSelf)
{
this.type = type;
this.hasErrorCode = false;
this.errorCode = 0;
this.pointsToSelf = pointsToSelf;
}
public Type getType()
{
return type;
}
public boolean isFault()
{
return !type.isTrap();
}
public boolean hasErrorCode()
{
return hasErrorCode;
}
public int getErrorCode()
{
return errorCode;
}
public boolean pointsToSelf()
{
return pointsToSelf;
}
public boolean combinesToDoubleFault(ProcessorException original)
{
switch (getType()) {
case DIVIDE_ERROR:
case TASK_SWITCH:
case NOT_PRESENT:
case STACK_SEGMENT:
case GENERAL_PROTECTION:
switch (original.getType()) {
case DIVIDE_ERROR:
case TASK_SWITCH:
case NOT_PRESENT:
case STACK_SEGMENT:
case GENERAL_PROTECTION:
case PAGE_FAULT:
return true;
default:
return false;
}
case PAGE_FAULT:
return (original.getType() == Type.PAGE_FAULT);
default:
return false;
}
}
public String toString()
{
if (hasErrorCode())
return "Processor Exception: " + type + " [errorcode:0x" + Integer.toHexString(getErrorCode()) + "]";
else
return "Processor Exception: " + type;
}
}