package vue; // Java imports import java.util.*; // CPU state class CPU { // Private fields private JavaVUE vue; // Emulation state // Package fields int cycles; // Cycles until next stage int fetch; // Fetch unit index Instruction inst; // Instruction state int[] jumpFrom; // Source PCs of most recent jumps int[] jumpTo; // Destination PCs of most recent jumps int stage; // Current processing stage // Program registers int[] program; // System registers int adtre; // Address Trap Register for Execution int eipc; // Exception/interrupt PC int eipsw; // Exception/interrupt PSW int fepc; // Duplexed exception PC int fepsw; // Duplexed exception PSW int pc; // Program Counter int sr29; // System register 29 int sr31; // System register 31 // Program Status Word int psw_ae; // Address Trap Enable int psw_ep; // Exception Pending int psw_id; // Interrupt Disable int psw_cy; // Carry int psw_fiv; // Floating Reserved Operand int psw_fov; // Floating Overflow int psw_fpr; // Floating Precision int psw_fro; // Floating Reserved Operand int psw_fud; // Floating Underflow int psw_fzd; // Floating Zero Divide int psw_i; // Interrupt Level int psw_np; // NMI Pending int psw_ov; // Overflow int psw_s; // Sign int psw_z; // Zero // Cache Control Word int chcw_cec; // Clear Entry Count int chcw_cen; // Clear Entry Number int chcw_icc; // Instruction Cache Clear int chcw_icd; // Instruction Cache Dump int chcw_ice; // Instruction Cache Enable int chcw_icr; // Instruction Cache Restore int chcw_sa; // Spill-Out Base Address // Exception Cause Register int ecr_eicc; // Exception/Interrupt Cause Code int ecr_fecc; // Fatal Error Cause Code /////////////////////////////////////////////////////////////////////////// // Constants // /////////////////////////////////////////////////////////////////////////// // Stages static final int FETCH = 0; static final int EXECUTE = 1; static final int HALT = 2; static final int EXCEPTION = 3; static final int FATAL = 4; static final int CLEAR = 5; static final int DUMP = 6; static final int RESTORE = 7; /////////////////////////////////////////////////////////////////////////// // Constructors // /////////////////////////////////////////////////////////////////////////// // Default constructor CPU(JavaVUE vue) { jumpFrom = new int[3]; jumpTo = new int[3]; program = new int[32]; this.vue = vue; } /////////////////////////////////////////////////////////////////////////// // Package Methods // /////////////////////////////////////////////////////////////////////////// // Read a system register int getSystemRegister(int index) { switch (index) { case VUE.ADTRE: return adtre; case VUE.EIPC : return eipc; case VUE.EIPSW: return eipsw; case VUE.FEPC : return fepc; case VUE.FEPSW: return fepsw; case VUE.ECR : return ecr_fecc << 16 | ecr_eicc; case VUE.PIR : return 0x00005346; case VUE.TKCW : return 0x000000E0; case VUE.CHCW : return chcw_ice << 1; case 29 : return sr29; case 30 : return 0x00000004; case 31 : return sr31; case VUE.PSW : return psw_i << 16 | psw_fro << 9 | psw_fpr << 4 | psw_np << 15 | psw_fiv << 8 | psw_cy << 3 | psw_ep << 14 | psw_fzd << 7 | psw_ov << 2 | psw_ae << 13 | psw_fov << 6 | psw_s << 1 | psw_id << 12 | psw_fud << 5 | psw_z ; // Remaining cases to encourage tableswitch case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: return 0; } return 1; // Unreachable } // System reset void reset() { // Configure instance fields cycles = 0; // Duration of first fetch fetch = 0; stage = FETCH; // Clear all registers (hardware only sets ECR, PC and PSW) for (int x = 0; x < 32; x++) { program[x] = 0; setSystemRegister(x, 0, true); } // Configure jump histories Arrays.fill(jumpFrom, 0xFFFFFFF0); Arrays.fill(jumpTo , 0xFFFFFFF0); // Configure registers ecr_eicc = 0xFFF0; pc = 0xFFFFFFF0; psw_np = 1; } // Write a system register int setSystemRegister(int index, int value, boolean debug) { switch (index) { case VUE.ADTRE: return adtre = value & 0xFFFFFFFE; case VUE.EIPC : return eipc = value & 0xFFFFFFFE; case VUE.EIPSW: return eipsw = value & 0x000FF3FF; case VUE.FEPC : return fepc = value & 0xFFFFFFFE; case VUE.FEPSW: return fepsw = value & 0x000FF3FF; case 29 : return sr29 = value; case 31 : return sr31 = debug || value >= 0 ? value : -value; case VUE.ECR: if (debug) { ecr_fecc = value >> 16 & 0xFFFF; ecr_eicc = value & 0xFFFF; } return ecr_fecc << 16 | ecr_eicc; case VUE.CHCW : chcw_cen = value >> 20 & 0x00000FFF; chcw_cec = value >> 8 & 0x00000FFF; chcw_sa = value >> 8 & 0x00FFFFFF; chcw_icr = value >> 5 & 1; chcw_icd = value >> 4 & 1; chcw_ice = value >> 1 & 1; chcw_icc = value & 1; // Only one of ICC, ICD or ICR is set value &= 0x00000031; if ((value & value - 1) == 0) { // Clear // Dump // Restore } return chcw_ice << 1; case VUE.PSW : psw_i = value >> 16 & 15; psw_fov = value >> 6 & 1; psw_np = value >> 15 & 1; psw_fud = value >> 5 & 1; psw_ep = value >> 14 & 1; psw_fpr = value >> 4 & 1; psw_ae = value >> 13 & 1; psw_cy = value >> 3 & 1; psw_id = value >> 12 & 1; psw_ov = value >> 2 & 1; psw_fro = value >> 9 & 1; psw_s = value >> 1 & 1; psw_fiv = value >> 8 & 1; psw_z = value & 1; psw_fzd = value >> 7 & 1; return value & 0x000FF3FF; // Remaining cases to encourage tableswitch case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 26: case 27: case 28: case 30: return 0; } return 1; // Unreachable } // Test a condition int test(int condition) { switch (condition) { case 0: return psw_ov; case 1: return psw_cy; case 2: return psw_z; case 3: return psw_cy | psw_z; case 4: return psw_s; case 5: return 1; case 6: return psw_ov | psw_s; case 7: return psw_ov ^ psw_s | psw_z; } return test(condition & 7) ^ 1; } }