228 lines
7.7 KiB
Java
228 lines
7.7 KiB
Java
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;
|
|
}
|
|
|
|
}
|