/* 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; } }