diff --git a/src/core/cpu.c b/src/core/cpu.c index f1e7e5e..33169b3 100644 --- a/src/core/cpu.c +++ b/src/core/cpu.c @@ -27,13 +27,13 @@ static const int8_t LOOKUP_OPCODE[] = { VUE_SHL_REG, 1, VUE_SHR_REG, 1, VUE_JMP , 1, VUE_SAR_REG, 1, VUE_MUL , 1, VUE_DIV , 1, VUE_MULU , 1, VUE_DIVU , 1, VUE_OR , 1, VUE_AND , 1, VUE_XOR , 1, VUE_NOT , 1, - VUE_MOV_IMM,-2, VUE_ADD_IMM,-2, VUE_SETF , 2, VUE_CMP_IMM,-2, + -VUE_MOV_IMM, 2,-VUE_ADD_IMM, 2, VUE_SETF , 2,-VUE_CMP_IMM, 2, VUE_SHL_IMM, 2, VUE_SHR_IMM, 2, VUE_CLI , 2, VUE_SAR_IMM, 2, VUE_TRAP , 2, VUE_RETI , 2, VUE_HALT , 2, VUE_ILLEGAL, 0, VUE_LDSR , 2, VUE_STSR , 2, VUE_SEI , 2, BITSTRING , 2, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, VUE_BCOND , 3, - VUE_MOVEA ,-5, VUE_ADDI ,-5, VUE_JR , 4, VUE_JAL , 4, + -VUE_MOVEA , 5,-VUE_ADDI , 5, VUE_JR , 4, VUE_JAL , 4, VUE_ORI , 5, VUE_ANDI , 5, VUE_XORI , 5, VUE_MOVHI , 5, VUE_LD_B , 6, VUE_LD_H , 6, VUE_ILLEGAL, 0, VUE_LD_W , 6, VUE_ST_B , 6, VUE_ST_H , 6, VUE_ILLEGAL, 0, VUE_ST_W , 6, @@ -60,106 +60,70 @@ static const int8_t LOOKUP_FLOATENDO[] = { /***************************************************************************** - * Instruction Functions * + * Module Functions * *****************************************************************************/ -/* Decoder for Format I */ -static void cpuFormatI(VUE_INST *inst) { - inst->reg2 = inst->bits >> 21 & 31; - inst->reg1 = inst->bits >> 16 & 31; -} - -/* Decoder for Format II */ -static void cpuFormatII(VUE_INST *inst, int extend) { - int32_t imm = inst->bits >> 16 & 31; - inst->reg2 = inst->bits >> 21 & 31; - inst->imm = extend ? SIGN_EXTEND(5, imm) : imm; -} - -/* Decoder for Format III */ -static void cpuFormatIII(VUE_INST *inst) { - int32_t disp = inst->bits >> 16 & 0x1FF; - inst->opcode = 0x20; - inst->cond = inst->bits >> 25 & 15; - inst->disp = SIGN_EXTEND(9, disp); -} - -/* Decoder for Format IV */ -static void cpuFormatIV(VUE_INST *inst) { - int32_t disp = inst->bits & 0x3FFFFFF; - inst->disp = SIGN_EXTEND(26, disp); -} - -/* Decoder for Format V */ -static void cpuFormatV(VUE_INST *inst, int extend) { - int32_t imm = inst->bits & 0xFFFF; - inst->reg2 = inst->bits >> 21 & 31; - inst->reg1 = inst->bits >> 16 & 31; - inst->imm = extend ? SIGN_EXTEND(16, imm) : imm; -} - -/* Decoder for Format VI */ -static void cpuFormatVI(VUE_INST *inst) { - int32_t disp = inst->bits & 0xFFFF; - inst->reg2 = inst->bits >> 21 & 31; - inst->reg1 = inst->bits >> 16 & 31; - inst->disp = SIGN_EXTEND(16, disp); -} - -/* Decoder for Format VII */ -static void cpuFormatVII(VUE_INST *inst) { - inst->reg2 = inst->bits >> 21 & 31; - inst->reg1 = inst->bits >> 16 & 31; - inst->subopcode = inst->bits >> 10 & 63; -} - /* Decode an instruction from its binary encoding */ static void cpuDecode(VUE_INST *inst, int32_t bits) { - int extend; + int8_t extend; /* Sign-extend the immediate operand */ + int32_t x; /* Working variable */ /* Configure instance fields */ inst->bits = bits; inst->opcode = bits >> 26 & 63; - inst->id = inst->opcode << 1 | 1; - inst->format = LOOKUP_OPCODE[inst->id + 1]; - inst->id = LOOKUP_OPCODE[inst->id]; - - /* Determine whether to sign-extend the immediate operand */ - if ((extend = inst->format < 0)) - inst->format = -inst->format; - - /* Determine the size in bytes of the instruction */ - inst->size = inst->format < 4 ? 2 : 4; - if (inst->size == 2) - inst->bits &= 0xFFFF0000; + x = inst->opcode << 1 | 1; + extend = LOOKUP_OPCODE[x]; + inst->format = LOOKUP_OPCODE[x + 1]; + inst->id = extend < 0 ? -extend : extend; + inst->size = inst->format < 4 ? 2 : 4; /* Decode by format */ switch (inst->format) { - case 0: return; /* Nothing to do */ - case 1: cpuFormatI (inst ); break; - case 2: cpuFormatII (inst, extend); break; - case 3: cpuFormatIII(inst ); break; - case 4: cpuFormatIV (inst ); break; - case 5: cpuFormatV (inst, extend); break; - case 6: cpuFormatVI (inst ); break; - case 7: cpuFormatVII(inst ); break; + case 0: return; /* Illegal opcode */ + case 1: + inst->reg2 = bits >> 21 & 31; + inst->reg1 = bits >> 16 & 31; + break; + case 2: + x = bits >> 16 & 31; + inst->reg2 = bits >> 21 & 31; + inst->imm = extend < 0 ? SIGN_EXTEND(5, x) : x; + if (inst->id == BITSTRING) + inst->id = x >= 16 ? VUE_ILLEGAL : LOOKUP_BITSTRING[x]; + break; + case 3: + x = bits >> 16 & 0x1FF; + inst->opcode = 0x20; + inst->cond = bits >> 25 & 15; + inst->disp = SIGN_EXTEND(9, x); + break; + case 4: + x = bits & 0x3FFFFFF; + inst->disp = SIGN_EXTEND(26, x); + break; + case 5: + x = bits & 0xFFFF; + inst->reg2 = bits >> 21 & 31; + inst->reg1 = bits >> 16 & 31; + inst->imm = extend < 0 ? SIGN_EXTEND(16, x) : x; + break; + case 6: + x = bits & 0xFFFF; + inst->reg2 = bits >> 21 & 31; + inst->reg1 = bits >> 16 & 31; + inst->disp = SIGN_EXTEND(16, x); + break; + case 7: + inst->reg2 = bits >> 21 & 31; + inst->reg1 = bits >> 16 & 31; + inst->subopcode = bits >> 10 & 63; + inst->id = inst->subopcode >= 16 ? VUE_ILLEGAL : + LOOKUP_FLOATENDO[inst->subopcode]; + break; } - /* Resolve final instruction ID by subopcode */ - if (inst->id == FLOATENDO) - inst->id = inst->subopcode >= 16 ? VUE_ILLEGAL : - LOOKUP_FLOATENDO[inst->subopcode]; - else if (inst->id == BITSTRING) - inst->id = inst->imm >= 16 ? VUE_ILLEGAL : - LOOKUP_BITSTRING[inst->imm ]; } - - -/***************************************************************************** - * Module Functions * - *****************************************************************************/ - /* Read a system register */ static int32_t cpuGetSystemRegister(VUE *vue, int index) { switch (index) { @@ -267,7 +231,7 @@ static void cpuReset(VUE *vue) { int x; /* Configure instance fields */ - vue->cpu.cycles = 0; + vue->cpu.cycles = 0; /* Duration of first fetch */ vue->cpu.fetch = 0; vue->cpu.stage = CPU_FETCH; @@ -277,10 +241,12 @@ static void cpuReset(VUE *vue) { cpuSetSystemRegister(vue, x, 0, VUE_TRUE); } + /* Configure jump history */ + for (x = 0; x < 3; x++) + vue->cpu.jumpFrom[x] = vue->cpu.jumpTo[x] = 0xFFFFFFF0; + /* Configure registers */ vue->cpu.ecr_eicc = 0xFFF0; - vue->cpu.jumpFrom = 0xFFFFFFF0; - vue->cpu.jumpTo = 0xFFFFFFF0; vue->cpu.pc = 0xFFFFFFF0; vue->cpu.psw_np = 1; } diff --git a/src/core/include/vue.h b/src/core/include/vue.h index 0c79a42..aa0f864 100644 --- a/src/core/include/vue.h +++ b/src/core/include/vue.h @@ -171,11 +171,11 @@ typedef struct { /* CPU state */ struct { - uint32_t cycles; /* Cycles until next stage */ - int fetch; /* Fetch unit index */ - int32_t jumpFrom; /* Source PC of most recent jump */ - int32_t jumpTo; /* Destination PC of most recent jump */ - int stage; /* Current processing stage */ + uint32_t cycles; /* Cycles until next stage */ + int32_t jumpFrom[3]; /* Source PCs of most recent jumps */ + int32_t jumpTo [3]; /* Destination PCs of most recent jumps */ + int fetch; /* Fetch unit index */ + int stage; /* Current processing stage */ /* Program registers */ int32_t program[32]; diff --git a/src/core/vue.c b/src/core/vue.c index 99b6643..c63365b 100644 --- a/src/core/vue.c +++ b/src/core/vue.c @@ -43,10 +43,12 @@ int32_t vueGetRegister(VUE *vue, int index, vbool system) { return 0; /* Non-indexed registers */ - if (system) switch (index) { + if (system && index < 0) switch (index) { + case VUE_JUMP_FROM: + return vue->cpu.jumpFrom[vue->cpu.psw_np ? 2 : vue->cpu.psw_ep]; + case VUE_JUMP_TO : + return vue->cpu.jumpTo [vue->cpu.psw_np ? 2 : vue->cpu.psw_ep]; case VUE_PC : return vue->cpu.pc; - case VUE_JUMP_FROM: return vue->cpu.jumpFrom; - case VUE_JUMP_TO : return vue->cpu.jumpTo; } /* Indexed registers */ diff --git a/src/desktop/vue/CPU.java b/src/desktop/vue/CPU.java index 5ec8bd9..9786b7f 100644 --- a/src/desktop/vue/CPU.java +++ b/src/desktop/vue/CPU.java @@ -1,5 +1,8 @@ package vue; +// Java imports +import java.util.*; + // CPU state class CPU { @@ -7,11 +10,11 @@ class CPU { private JavaVUE vue; // Emulation state // Package fields - int cycles; // Cycles until next stage - int fetch; // Fetch unit index - int jumpFrom; // Source PC of most recent jump - int jumpTo; // Destination PC of most recent jump - int stage; // Current processing stage + int cycles; // Cycles until next stage + int fetch; // Fetch unit index + 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; @@ -80,6 +83,8 @@ class CPU { // Default constructor CPU(JavaVUE vue) { + jumpFrom = new int[3]; + jumpTo = new int[3]; program = new int[32]; this.vue = vue; } @@ -115,20 +120,7 @@ class CPU { // 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: // Configure instance fields - cycles = 0; - fetch = 0; - stage = FETCH; - - // Reset program counter - pc = 0xFFFFFFF0; - - // Clear all registers (hardware only sets ECR, PC and PSW) - for (int x = 0; x < 32; x++) { - program[x] = 0; - setSystemRegister(x, 0, true); - } - case 22: case 23: case 26: case 27: case 28: + case 15: case 16: case 17: case 18: case 19: case 20: case 21: return 0; } return 1; // Unreachable @@ -138,7 +130,7 @@ class CPU { void reset() { // Configure instance fields - cycles = 0; + cycles = 0; // Duration of first fetch fetch = 0; stage = FETCH; @@ -148,10 +140,12 @@ class CPU { setSystemRegister(x, 0, true); } + // Configure jump histories + Arrays.fill(jumpFrom, 0xFFFFFFF0); + Arrays.fill(jumpTo , 0xFFFFFFF0); + // Configure registers ecr_eicc = 0xFFF0; - jumpFrom = 0xFFFFFFF0; - jumpTo = 0xFFFFFFF0; pc = 0xFFFFFFF0; psw_np = 1; } diff --git a/src/desktop/vue/Instruction.java b/src/desktop/vue/Instruction.java index a224f7a..b1461dd 100644 --- a/src/desktop/vue/Instruction.java +++ b/src/desktop/vue/Instruction.java @@ -32,13 +32,13 @@ public class Instruction { VUE.SHL_REG, 1, VUE.SHR_REG, 1, VUE.JMP , 1, VUE.SAR_REG, 1, VUE.MUL , 1, VUE.DIV , 1, VUE.MULU , 1, VUE.DIVU , 1, VUE.OR , 1, VUE.AND , 1, VUE.XOR , 1, VUE.NOT , 1, - VUE.MOV_IMM,-2, VUE.ADD_IMM,-2, VUE.SETF , 2, VUE.CMP_IMM,-2, + -VUE.MOV_IMM, 2,-VUE.ADD_IMM, 2, VUE.SETF , 2,-VUE.CMP_IMM, 2, VUE.SHL_IMM, 2, VUE.SHR_IMM, 2, VUE.CLI , 2, VUE.SAR_IMM, 2, VUE.TRAP , 2, VUE.RETI , 2, VUE.HALT , 2, VUE.ILLEGAL, 0, VUE.LDSR , 2, VUE.STSR , 2, VUE.SEI , 2, BITSTRING , 2, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, - VUE.MOVEA ,-5, VUE.ADDI ,-5, VUE.JR , 4, VUE.JAL , 4, + -VUE.MOVEA , 5,-VUE.ADDI , 5, VUE.JR , 4, VUE.JAL , 4, VUE.ORI , 5, VUE.ANDI , 5, VUE.XORI , 5, VUE.MOVHI , 5, VUE.LD_B , 6, VUE.LD_H , 6, VUE.ILLEGAL, 0, VUE.LD_W , 6, VUE.ST_B , 6, VUE.ST_H , 6, VUE.ILLEGAL, 0, VUE.ST_W , 6, @@ -90,92 +90,58 @@ public class Instruction { // Decode an instruction from its binary encoding public void decode(int bits) { + byte extend; // Sign-extend the immediate operand + int x; // Working variable // Configure instance fields this.bits = bits; - opcode = bits >> 26 & 63; - id = opcode << 1 | 1; - format = LOOKUP_OPCODE[id + 1]; - id = LOOKUP_OPCODE[id]; - - // Determine whether to sign-extend the immediate operand - boolean extend = format < 0; - if (extend) - format = -format; - - // Determine the size in bytes of the instruction - size = format < 4 ? 2 : 4; - if (size == 2) - this.bits &= 0xFFFF0000; + opcode = bits >> 26 & 63; + x = opcode << 1 | 1; + extend = LOOKUP_OPCODE[x]; + format = LOOKUP_OPCODE[x + 1]; + id = extend < 0 ? -extend : extend; + size = format < 4 ? 2 : 4; // Decode by format switch (format) { - case 0: return; // Nothing to do - case 1: formatI ( ); break; - case 2: formatII (extend); break; - case 3: formatIII( ); break; - case 4: formatIV ( ); break; - case 5: formatV (extend); break; - case 6: formatVI ( ); break; - case 7: formatVII( ); break; + case 0: return; // Illegal opcode + case 1: + reg2 = bits >> 21 & 31; + reg1 = bits >> 16 & 31; + break; + case 2: + reg2 = bits >> 21 & 31; + imm = extend < 0 ? bits << 11 >> 27 : bits >> 16 & 31; + if (id == BITSTRING) + id = imm >= 16 ? VUE.ILLEGAL : LOOKUP_BITSTRING[imm]; + break; + case 3: + opcode = 0x20; + cond = bits >> 25 & 15; + disp = bits << 7 >> 23; + break; + case 4: + disp = bits << 6 >> 6; + break; + case 5: + reg2 = bits >> 21 & 31; + reg1 = bits >> 16 & 31; + imm = extend < 0 ? bits << 16 >> 16 : bits & 0xFFFF; + break; + case 6: + reg2 = bits >> 21 & 31; + reg1 = bits >> 16 & 31; + disp = bits << 16 >> 16; + break; + case 7: + reg2 = bits >> 21 & 31; + reg1 = bits >> 16 & 31; + subopcode = bits >> 10 & 63; + id = subopcode >= 16 ? VUE.ILLEGAL : + LOOKUP_FLOATENDO[subopcode]; + break; } - // Resolve final instruction ID by subopcode - if (id == FLOATENDO) - id = subopcode >= 16 ? VUE.ILLEGAL : LOOKUP_FLOATENDO[subopcode]; - else if (id == BITSTRING) - id = imm >= 16 ? VUE.ILLEGAL : LOOKUP_BITSTRING[imm ]; - } - - - - /////////////////////////////////////////////////////////////////////////// - // Private Methods // - /////////////////////////////////////////////////////////////////////////// - - // Decoder for Format I - private void formatI() { - reg2 = bits >> 21 & 31; - reg1 = bits >> 16 & 31; - } - - // Decoder for Format II - private void formatII(boolean extend) { - reg2 = bits >> 21 & 31; - imm = extend ? bits << 11 >> 27 : bits >> 16 & 31; - } - - // Decoder for Format III - private void formatIII() { - opcode = 0x20; - cond = bits >> 25 & 15; - disp = bits << 7 >> 25; - } - - // Decoder for Format IV - private void formatIV() { - disp = bits << 6 >> 6; - } - - // Decoder for Format V - private void formatV(boolean extend) { - reg2 = bits >> 21 & 31; - reg1 = bits >> 16 & 31; - imm = extend ? bits << 16 >> 16 : bits & 0x0000FFFF; - } - - // Decoder for Format VI - private void formatVI() { - reg2 = bits >> 21 & 31; - reg1 = bits >> 16 & 31; - disp = bits << 16 >> 16; - } - - // Decoder for Format VII - private void formatVII() { - reg2 = bits >> 21 & 31; - reg1 = bits >> 16 & 31; - subopcode = bits >> 10 & 63; } } diff --git a/src/desktop/vue/JavaVUE.java b/src/desktop/vue/JavaVUE.java index 903eb2a..995f41b 100644 --- a/src/desktop/vue/JavaVUE.java +++ b/src/desktop/vue/JavaVUE.java @@ -43,9 +43,11 @@ class JavaVUE extends VUE { // Non-indexed registers if (system) switch (index) { + case VUE.JUMP_FROM: return + cpu.jumpFrom[cpu.psw_np != 0 ? 2 : cpu.psw_ep]; + case VUE.JUMP_TO : return + cpu.jumpTo [cpu.psw_np != 0 ? 2 : cpu.psw_ep]; case VUE.PC : return cpu.pc; - case VUE.JUMP_FROM: return cpu.jumpFrom; - case VUE.JUMP_TO : return cpu.jumpTo; } // Indexed registers