/* This file is included through vue.c and cannot be built directly. */ #ifdef VUEAPI /***************************************************************************** * Constants * *****************************************************************************/ /* Stages */ #define CPU_FETCH 0 #define CPU_EXECUTE 1 #define CPU_HALT 2 #define CPU_EXCEPTION 3 #define CPU_FATAL 4 #define CPU_CLEAR 5 #define CPU_DUMP 6 #define CPU_RESTORE 7 /***************************************************************************** * Module Functions * *****************************************************************************/ /* Read a system register */ static int32_t cpuGetSystemRegister(VUE *vue, int index) { switch (index) { case VUE_ADTRE: return vue->cpu.adtre; case VUE_EIPC : return vue->cpu.eipc; case VUE_EIPSW: return vue->cpu.eipsw; case VUE_FEPC : return vue->cpu.fepc; case VUE_FEPSW: return vue->cpu.fepsw; case VUE_ECR : return vue->cpu.ecr_fecc << 16 | vue->cpu.ecr_eicc; case VUE_PIR : return 0x00005346; case VUE_TKCW : return 0x000000E0; case VUE_CHCW : return vue->cpu.chcw_ice << 1; case 29 : return vue->cpu.sr29; case 30 : return 0x00000004; case 31 : return vue->cpu.sr31; case VUE_PSW : return vue->cpu.psw_i << 16 | vue->cpu.psw_fov << 6 | vue->cpu.psw_np << 15 | vue->cpu.psw_fud << 5 | vue->cpu.psw_ep << 14 | vue->cpu.psw_fpr << 4 | vue->cpu.psw_ae << 13 | vue->cpu.psw_cy << 3 | vue->cpu.psw_id << 12 | vue->cpu.psw_ov << 2 | vue->cpu.psw_fro << 9 | vue->cpu.psw_s << 1 | vue->cpu.psw_fiv << 8 | vue->cpu.psw_z | vue->cpu.psw_fzd << 7 ; /* 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: case 22: case 23: case 26: case 27: case 28: return 0; } return 1; /* Unreachable */ } /* Write a system register */ static int32_t cpuSetSystemRegister(VUE *vue, int index, int32_t value, vbool debug) { switch (index) { case VUE_ADTRE: return vue->cpu.adtre = value & 0xFFFFFFFE; case VUE_EIPC : return vue->cpu.eipc = value & 0xFFFFFFFE; case VUE_EIPSW: return vue->cpu.eipsw = value & 0x000FF3FF; case VUE_FEPC : return vue->cpu.fepc = value & 0xFFFFFFFE; case VUE_FEPSW: return vue->cpu.fepsw = value & 0x000FF3FF; case 29 : return vue->cpu.sr29 = value; case 31 : return vue->cpu.sr31 = debug || value >= 0 ? value : -value; case VUE_CHCW : vue->cpu.chcw_cen = value >> 20 & 0x00000FFF; vue->cpu.chcw_cec = value >> 8 & 0x00000FFF; vue->cpu.chcw_sa = value >> 8 & 0x00FFFFFF; vue->cpu.chcw_icr = value >> 5 & 1; vue->cpu.chcw_icd = value >> 4 & 1; vue->cpu.chcw_ice = value >> 1 & 1; vue->cpu.chcw_icc = value & 1; /* Only one of ICC, ICD or ICR is set */ value &= 0x00000031; if ((value & (value - 1)) == 0) { /* Clear */ /* Dump */ /* Restore */ } return vue->cpu.chcw_ice << 1; case VUE_ECR: if (debug) { vue->cpu.ecr_fecc = value >> 16 & 0xFFFF; vue->cpu.ecr_eicc = value & 0xFFFF; } return vue->cpu.ecr_fecc << 16 | vue->cpu.ecr_eicc; case VUE_PSW : vue->cpu.psw_i = value >> 16 & 15; vue->cpu.psw_np = value >> 15 & 1; vue->cpu.psw_ep = value >> 14 & 1; vue->cpu.psw_ae = value >> 13 & 1; vue->cpu.psw_id = value >> 12 & 1; vue->cpu.psw_fro = value >> 9 & 1; vue->cpu.psw_fiv = value >> 8 & 1; vue->cpu.psw_fzd = value >> 7 & 1; vue->cpu.psw_fov = value >> 6 & 1; vue->cpu.psw_fud = value >> 5 & 1; vue->cpu.psw_fpr = value >> 4 & 1; vue->cpu.psw_cy = value >> 3 & 1; vue->cpu.psw_ov = value >> 2 & 1; vue->cpu.psw_s = value >> 1 & 1; vue->cpu.psw_z = value & 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 */ } /* Perform a system reset */ static void cpuReset(VUE *vue) { int x; /* Configure instance fields */ vue->cpu.cycles = 0; vue->cpu.fetch = 0; vue->cpu.stage = CPU_FETCH; /* Clear all registers (hardware only sets ECR, PC and PSW) */ for (x = 0; x < 32; x++) { vue->cpu.program[x] = 0; cpuSetSystemRegister(vue, x, 0, VUE_TRUE); } /* Configure registers */ vue->cpu.ecr_eicc = 0xFFF0; vue->cpu.jumpFrom = 0xFFFFFFF0; vue->cpu.jumpTo = 0xFFFFFFF0; vue->cpu.pc = 0xFFFFFFF0; vue->cpu.psw_np = 1; } /* Test a condition */ static int8_t cpuTest(VUE *vue, int condition) { switch (condition) { case 0: return vue->cpu.psw_ov; case 1: return vue->cpu.psw_cy; case 2: return vue->cpu.psw_z; case 3: return vue->cpu.psw_cy | vue->cpu.psw_z; case 4: return vue->cpu.psw_s; case 5: return 1; case 6: return vue->cpu.psw_ov | vue->cpu.psw_s; case 7: return (vue->cpu.psw_ov ^ vue->cpu.psw_s) | vue->cpu.psw_z; } return cpuTest(vue, condition & 7) ^ 1; } #endif