private void HandleINT() { // TODO: Check if INT is supposed to be able to fire during this push and other memory operations var opcode = AcknowledgeInterrupt(); if (Registers.InterruptMode == Z80InterruptMode.External) { var instr = InstructionDecoder.DecodeNextInstruction(this, opcode); instr.Execute(this, instr.InstructionBytes); } else if (Registers.InterruptMode == Z80InterruptMode.FixedAddress) { PushWord(Registers.PC); Registers.PC = 0x38; } else if (Registers.InterruptMode == Z80InterruptMode.Vectorized) { var upper = Registers.I; var lower = opcode; var addr = Utilities.LETo16Bit(lower, upper); PushWord(Registers.PC); var jumpAddr = ReadWord(addr); Registers.PC = jumpAddr; } }
public List <DisassembledInstruction> Disassemble(ushort address) { Registers.PC = address; var instructions = new List <DisassembledInstruction>(); DisassembledInstruction instruction; do { instruction = InstructionDecoder.DecodeNextInstruction(this); instructions.Add(instruction); } while (!instruction.ControlInstruction); return(instructions); }
public void ExecuteNextInstruction() { if (Registers.PC == 0) { throw new InvalidOperationException("Hit address 0"); } if (Registers.PC == 5) { // Handle CP/M syscalls switch (Registers.C) { case 2: { var inputByte = Registers.E; var outputChar = Encoding.ASCII.GetString(new[] { inputByte })[0]; Console.Write(outputChar); break; } case 9: { var strAddress = Registers.DE; var inputBytes = new List <byte>(); byte inputByte; _cycleCount += 3; while ((inputByte = ReadMemory(strAddress)) != '$') { _cycleCount += 3; inputBytes.Add(inputByte); strAddress++; } var outputChar = Encoding.ASCII.GetString(inputBytes.ToArray()); Console.Write(outputChar); break; } default: // throw new NotImplementedException($"Unimplemented syscall {Registers.C}"); break; } FetchOpcode(); _cycleCount += Z80Instructions.RET(this, null); } var instruction = InstructionDecoder.DecodeNextInstruction(this); var beforeCount = _cycleCount; _cycleCount += instruction.Execute(this, instruction.InstructionBytes); if (_cycleCount != ControlLines.SystemClock.Ticks) { throw new InvalidOperationException($"Cycle mismatch when executing instruction {instruction.Mnemonic} - expected {_cycleCount - beforeCount} but got {ControlLines.SystemClock.Ticks - beforeCount} cycles"); } if (Registers.IFF1 && ControlLines.INT.Value == TristateWireState.LogicLow) { HandleINT(); } }