/// <summary> /// This method determines the next address, based on the current microinstruction, /// status word, MRTN register, etc. /// </summary> public bool GetJump(MSmicrocodeStatement mc) { // TODO This hard code neglects the MScontrolTable! if (mc.jumpCode == 0) { // No jump; increment MPC and set to MUX register MicroRegisterContent[(int)RegisterSet.MUX] = ++MicroRegisterContent[(int)RegisterSet.MPC]; return(true); } // TODO: rest of jump codes return(false); }
public bool PerformOneMicroStatement(MSmicrocodeStatement mc) { // handle the easy cases first. Note that increments do NOT affect the status if (ControlTable.aCTwrite[mc.write] == MSstate.RegSet.incPC_MAR) { PerformIncMAR(); PerformIncPC(); return(mseq.GetJump(mc)); } if (ControlTable.aCTread[mc.read] == MSstate.RegSet.incPC) { PerformIncPC(); return(mseq.GetJump(mc)); } if (ControlTable.aCTread[mc.read] == MSstate.RegSet.incMAR) { PerformIncMAR(); return(mseq.GetJump(mc)); } // determine the source and destination of this instruction // (Though they may not always be applicable) MSstate.RegSet RWdestination, RWsource; if (mc.write == 13 || mc.write == 15 || (mc.write > 0 && mc.write < 12)) { RWdestination = ControlTable.aCTwrite[mc.write]; } else { return(false); // TODO throw exception } if (mc.read == 13 || mc.read == 15 || (mc.read > 0 && mc.read < 10)) { RWsource = ControlTable.aCTwrite[mc.read]; } else { return(false); // TODO throw exception } // Handle the most frequent case (assignment), ALU "does" B if (ControlTable.aFn[mc.alu] == MScontrolTable.ALU_fn.B) { byte result = state.RegisterContent[RWsource]; PerformAssign(RWdestination, result); return(SetStatusAndJump(result, mc)); } // alu:B if (ControlTable.aFn[mc.alu] == MScontrolTable.ALU_fn.A) { byte result = state.RegisterContent[MSstate.RegSet.ALUin]; PerformAssign(RWdestination, result); return(SetStatusAndJump(result, mc)); } // alu:A if (ControlTable.aFn[mc.alu] == MScontrolTable.ALU_fn.not_A) { byte notA = (byte)~state.RegisterContent[MSstate.RegSet.ALUin]; PerformAssign(RWdestination, notA); return(SetStatusAndJump(notA, mc)); } // alu:not_A if (ControlTable.aFn[mc.alu] == MScontrolTable.ALU_fn.AandB) { byte A = state.RegisterContent[MSstate.RegSet.ALUin]; byte B = state.RegisterContent[RWsource]; // bitwise AND byte result = (byte)(A & B); PerformAssign(RWdestination, result); return(SetStatusAndJump(result, mc)); } // alu:AandB if (ControlTable.aFn[mc.alu] == MScontrolTable.ALU_fn.AtB) // A plus B TODO: test { // All registers are stored as unsigned bytes. We need to use unsigned // integers for the arithmetic operation uint A = unchecked ((uint)state.RegisterContent[MSstate.RegSet.ALUin]); uint B = unchecked ((uint)state.RegisterContent[RWsource]); uint uiResult = A + B; // adjust the result as necessary to fit into a byte bCarry = false; // assume this until proven wrong byte byteResult = 0x0; // to receive the arithmetic result if (uiResult == 0) // easy case { byteResult = unchecked ((byte)uiResult); bPos = bNeg = false; bZero = true; } else if (uiResult < 128) // positive number, no carry { byteResult = unchecked ((byte)uiResult); bNeg = bZero = false; bPos = true; } else if (uiResult < 256) // negative number, no carry { byteResult = unchecked ((byte)uiResult); bPos = bZero = false; bNeg = true; } else // positive number with carry { byteResult = unchecked ((byte)(uiResult % 256)); //truncate bNeg = bZero = false; bPos = bCarry = true; } PerformAssign(RWdestination, byteResult); return(mseq.GetJump(mc)); } // alu:AandB // TODO: more ALU selections return(false); } // PerformOneMicroStatement
// This is called after an assignment or ALU operation. // result is the assigned or calculated value. // Note that bNOT_CDAV is controlled by events other than assignments // and ALU operations. public bool SetStatusAndJump(byte result, MSmicrocodeStatement mc) { SetStatus(result); return(mseq.GetJump(mc)); }