/// <summary> /// Does an IO instruction through the DMA /// </summary> /// <param name="readOrWrite">True for read, false for write</param> /// <param name="callingCPU">The CPU that's calling the DMA</param> /// <param name="reg1">Reg1 in the instructions</param> /// <param name="secondLocation">The second location to be called, whether it be register or address</param> /// <param name="reg2ORAddress">True for reg2, false for address as second location</param> /// <returns></returns> public static async Task IOExecution(bool readOrWrite, CPU callingCPU, int reg1, int secondLocation, bool reg2ORAddress) { /* * Start the timer */ // Metrics.Stop(callingCPU.ActiveProgram); if (readOrWrite) // ==> Read { Task thread = Task.Factory.StartNew(() => { blocker().GetAwaiter().GetResult(); if (reg2ORAddress) { callingCPU.Registers[reg1] = callingCPU.Registers[secondLocation]; } else { callingCPU.Registers[reg1] = MMU.ReadWord(secondLocation, callingCPU.ActiveProgram); } unlocker().GetAwaiter().GetResult(); }); thread.Wait(); } else // ==> Write { Task thread = Task.Factory.StartNew(() => { blocker().GetAwaiter().GetResult(); if (reg2ORAddress) { callingCPU.Registers[secondLocation] = callingCPU.Registers[reg1]; } else { MMU.WriteWord(secondLocation, callingCPU.ActiveProgram, callingCPU.Registers[reg1]); } unlocker().GetAwaiter().GetResult(); }); thread.Wait(); } /* * Stop the waiting timer */ // Metrics.Stop(callingCPU.ActiveProgram); // Increment the IO count for the pcb callingCPU.ActiveProgram.IOOperationCount++; }
private void ExecuteCondi() { string second; int preAddr = addr; addr /= 4; if (dReg == 0) { second = Utilities.WordFill(Utilities.DecToHex(preAddr)); } else { second = MMU.ReadWord(addr, activeProgram).Value; } switch (OPCODE) { case 2: // 02: ST Driver._MMULock.Wait(); DMA.IOExecution(false, this, bReg, addr, false).GetAwaiter().GetResult(); Driver._MMULock.Release(); break; case 3: // 03: LW Driver._MMULock.Wait(); DMA.IOExecution(true, this, dReg, addr, false).GetAwaiter().GetResult(); Driver._MMULock.Release(); break; case 11: // 0B: MOVI registers[dReg].Value = Utilities.WordFill(second); break; case 12: // 0C: ADDI registers[dReg] = registers[dReg] + MMU.ReadWord(addr, activeProgram); break; case 13: // 0D: MULI registers[dReg] = registers[dReg] * MMU.ReadWord(addr, activeProgram); break; case 14: // 0E: DIVI registers[dReg] = registers[dReg] / MMU.ReadWord(addr, activeProgram); break; case 15: // 0F: LDI registers[dReg] = new Word(second); break; case 17: // 11: SLTI registers[dReg].Value = Utilities.DecToHexFullAddr(registers[sReg0].ValueAsInt < addr ? 1 : 0); break; case 21: // 15: BEQ PC = registers[bReg] == registers[dReg] ? preAddr : PC; break; case 22: // 16: BNE PC = registers[bReg] != registers[dReg] ? preAddr : PC; break; case 23: // 17: BEZ PC = registers[bReg].ValueAsInt == 0 ? preAddr : PC; break; case 24: // 18: BNZ PC = registers[bReg].ValueAsInt != 0 ? preAddr : PC; break; case 25: // 19: BGZ PC = registers[bReg].ValueAsInt > 0 ? preAddr : PC; break; case 26: // 1A: BLZ PC = registers[bReg].ValueAsInt < 0 ? preAddr : PC; break; default: throw new Exception("OPCode invalid, check the hex to dec conversion: " + OPCODE); } // Console.WriteLine($"CONDI: OPCODE {OPCODE} | B = {bReg} | D = {dReg} | ADDR = {addr} | SECOND = {second}"); }
string EffectiveAddress() { return(MMU.ReadWord(addr, this.activeProgram).Value); }