public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { if (!cpu.GetFlags().Has(FlagsRegister.Overflow)) { new JumpRelative().Dispatch(cpu, instruction); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { switch (instruction.Argument1) { case (int)Register.SP: // 8086 has a bug where it pushes SP after it has been modified // cpu.registers[(int)Register.SP] -= 2; // cpu.WriteU16(SegmentToAddress(cpu.GetRegister(Register.SS), cpu.GetRegister(Register.SP)), cpu.GetRegister(Register.SP)); // break; case (int)Register.AX: case (int)Register.CX: case (int)Register.DX: case (int)Register.BX: case (int)Register.BP: case (int)Register.SI: case (int)Register.DI: case (int)Register.IP: case (int)Register.CS: case (int)Register.DS: case (int)Register.ES: case (int)Register.SS: case unchecked ((int)Register.FLAGS): cpu.Push(cpu.GetRegister((Register)instruction.Argument1)); break; case OpCodeManager.ARG_DEREFERENCE: case OpCodeManager.ARG_MEMORY: var address = InstructionHelper.GetInstructionRealAddress(cpu, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement); cpu.Push(cpu.ReadU16(address)); break; default: throw new ArgumentOutOfRangeException(); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { ushort value1; ushort value2; byte size; if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { value1 = cpu.GetRegisterU8(Register.AL); value2 = cpu.ReadU8(InstructionHelper.SegmentToAddress(cpu.GetRegister(Register.ES), cpu.GetRegister(Register.DI))); size = 1; } else { value1 = cpu.GetRegister(Register.AX); value2 = cpu.ReadU16(InstructionHelper.SegmentToAddress(cpu.GetRegister(Register.ES), cpu.GetRegister(Register.DI))); size = 2; } var result = value1 - value2; InstructionHelper.CalculateSubFlags(cpu, instruction.Flag, value1, value2, result); if (!cpu.GetFlags().Has(FlagsRegister.Direction)) { cpu.IncRegister(Register.DI, size); } else { cpu.DecRegister(Register.DI, size); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { switch (instruction.Type) { case OpCodeManager.InstructionType.Cmps: new CompareString().Dispatch(cpu, instruction); break; case OpCodeManager.InstructionType.Lods: new LoadString().Dispatch(cpu, instruction); break; case OpCodeManager.InstructionType.Movs: new MoveString().Dispatch(cpu, instruction); break; case OpCodeManager.InstructionType.Stos: new StoreString().Dispatch(cpu, instruction); break; case OpCodeManager.InstructionType.Scas: new ScanString().Dispatch(cpu, instruction); break; default: throw new NotImplementedException(); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { if (cpu.GetRegister(Register.CX) == 0) { new JumpRelative().Dispatch(cpu, instruction); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { switch (instruction.Argument1) { case (int)Register.AX: case (int)Register.CX: case (int)Register.DX: case (int)Register.BX: case (int)Register.SP: case (int)Register.BP: case (int)Register.SI: case (int)Register.DI: case (int)Register.IP: case (int)Register.CS: case (int)Register.DS: case (int)Register.ES: case (int)Register.SS: cpu.SetRegister((Register)instruction.Argument1, ProcessExchangeSecond(cpu, instruction, cpu.GetRegister((Register)instruction.Argument1))); break; case OpCodeManager.ARG_BYTE_REGISTER: cpu.SetRegister((Register)instruction.Argument1Value, (byte)ProcessExchangeSecond(cpu, instruction, cpu.GetRegisterU8((Register)instruction.Argument1Value))); break; default: throw new NotImplementedException(); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var value1 = cpu.GetRegister(Register.AX); var value2 = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement); if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { value1 &= 0xFF; value2 &= 0xFF; } uint result; switch (instruction.Type) { case OpCodeManager.InstructionType.Multiply: result = (uint)value1 * value2; break; case OpCodeManager.InstructionType.SignedMultiply: result = (uint)(value1 * value2); break; default: throw new ArgumentOutOfRangeException(); } InstructionHelper.CalculateAddFlags(cpu, instruction.Flag, value1, value2, (int)result); cpu.SetRegister(Register.AX, (ushort)result); if (!instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { cpu.SetRegister(Register.DX, (ushort)(result >> 16)); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { switch (instruction.Argument1) { case (int)Register.AX: case (int)Register.CX: case (int)Register.DX: case (int)Register.BX: case (int)Register.SP: case (int)Register.BP: case (int)Register.SI: case (int)Register.DI: case (int)Register.IP: case (int)Register.CS: case (int)Register.DS: case (int)Register.ES: case (int)Register.SS: //case unchecked((int)Register.FLAGS): cpu.SetRegister((Register)instruction.Argument1, cpu.Pop()); break; case unchecked ((int)Register.FLAGS): cpu.SetRegister((Register)instruction.Argument1, cpu.Pop()); break; case OpCodeManager.ARG_DEREFERENCE: case OpCodeManager.ARG_MEMORY: var address = InstructionHelper.GetInstructionRealAddress(cpu, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement); cpu.WriteU16(address, cpu.Pop()); break; default: throw new ArgumentOutOfRangeException(); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var address = InstructionHelper.GetInstructionRealAddress(cpu, instruction.SegmentPrefix, instruction.Argument2, instruction.Argument2Value, instruction.Argument2Displacement); var memory = cpu.ReadU16(address); var segment = cpu.ReadU16(address + 2); cpu.SetRegister(_register, segment); switch ((Register)instruction.Argument1) { case Register.AX: case Register.CX: case Register.DX: case Register.BX: case Register.SP: case Register.BP: case Register.SI: case Register.DI: case Register.IP: case Register.CS: case Register.DS: case Register.ES: case Register.SS: cpu.SetRegister((Register)instruction.Argument1, memory); break; default: throw new NotImplementedException(); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { const FlagsRegister flagsAffected = FlagsRegister.Sign | FlagsRegister.Zero | FlagsRegister.Auxiliary | FlagsRegister.Parity | FlagsRegister.Carry; cpu.Flags &= ~flagsAffected; cpu.Flags |= (FlagsRegister)(cpu.GetRegister(Register.AH) & (ushort)flagsAffected); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var address = InstructionHelper.GetInstructionAddress(cpu, instruction.Argument2, instruction.Argument2Value, instruction.Argument2Displacement); switch ((Register)instruction.Argument1) { case Register.AX: case Register.CX: case Register.DX: case Register.BX: case Register.SP: case Register.BP: case Register.SI: case Register.DI: case Register.IP: case Register.CS: case Register.DS: case Register.ES: case Register.SS: cpu.SetRegister((Register)instruction.Argument1, address); break; default: throw new NotImplementedException(); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { cpu.SetRegister(Register.IP, cpu.Pop()); cpu.SetRegister(Register.CS, cpu.Pop()); cpu.SetRegister(Register.FLAGS, cpu.Pop()); //cpu._interruptStack.Pop(); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var prefix = instruction.SegmentPrefix; if (prefix == Register.Invalid) { prefix = Register.DS; } var sourceAddress = InstructionHelper.SegmentToAddress(cpu.GetRegister(prefix), cpu.GetRegister(Register.SI)); byte size; if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { cpu.SetRegisterU8(Register.AL, cpu.ReadU8(sourceAddress)); size = 1; } else { cpu.SetRegister(Register.AX, cpu.ReadU16(sourceAddress)); size = 2; } if (!cpu.GetFlags().Has(FlagsRegister.Direction)) { cpu.SetRegister(Register.SI, (ushort)(cpu.GetRegister(Register.SI) + size)); } else { cpu.SetRegister(Register.SI, (ushort)(cpu.GetRegister(Register.SI) - size)); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var address = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement); cpu.Push(cpu.GetRegister(Register.IP)); cpu.SetRegister(Register.IP, address); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var al = cpu.GetRegisterU8(Register.AL); var flags = cpu.GetFlags(); if ((al & 0xF) > 9 || flags.Has(FlagsRegister.Auxiliary)) { var ah = cpu.GetRegisterU8(Register.AH); al = (byte)((al + 6) & 0x0F); ah++; cpu.SetRegisterU8(Register.AH, ah); flags |= FlagsRegister.Carry | FlagsRegister.Auxiliary; } else { al &= 0x0F; flags &= ~(FlagsRegister.Carry | FlagsRegister.Auxiliary); } flags &= ~(FlagsRegister.Parity | FlagsRegister.Zero | FlagsRegister.Sign); flags |= (InstructionHelper.ParityLookup[al] ? FlagsRegister.Parity : 0) | (al == 0 ? FlagsRegister.Zero : 0) | ((al & 0x80) != 0 ? FlagsRegister.Sign : 0); cpu.SetFlags(flags); cpu.SetRegisterU8(Register.AL, al); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { if (cpu.GetFlags().Has(FlagsRegister.Overflow)) { cpu.Interrupt(4); } }
private static void RunTest([NotNull] string testFile) { ICpu cpu; using (var file = File.OpenRead("CpuBinaries/" + testFile)) cpu = new Cpu8086(file, 1024 * 1024); cpu.WriteBytes(0, new byte[0x100]); if (cpu.ProcessInstructions(1000)) { throw new InvalidOperationException("Test case did not complete in the required amount of time."); } using (var file = File.OpenRead($"CpuBinaries/{testFile}Result")) { var goodData = new byte[file.Length]; if (file.Read(goodData, 0, goodData.Length) != goodData.Length) { throw new InvalidDataException(); } var testData = cpu.ReadBytes(0, (uint)goodData.Length); var result = CompareArrays(goodData, testData); if (result.Count > 0) { var comparison = result.Select(i => new Tuple <int, byte, byte>(i, goodData[i], testData[i])).ToList(); throw new InvalidOperationException("Test case did not produce valid output."); } } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var al = cpu.GetRegister(Register.AL); cpu.SetRegister(Register.AH, (byte)(al / 10)); cpu.SetRegister(Register.AL, (byte)(al % 10)); InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, al, 0, cpu.GetRegister(Register.AX)); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var flags = cpu.GetFlags(); if (!flags.Has(FlagsRegister.Carry) && !flags.Has(FlagsRegister.Zero)) { new JumpRelative().Dispatch(cpu, instruction); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var flags = cpu.GetFlags(); if (flags.Has(FlagsRegister.Zero) || flags.Has(FlagsRegister.Sign) != flags.Has(FlagsRegister.Overflow)) { new JumpRelative().Dispatch(cpu, instruction); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { cpu.DecRegister(Register.CX); var counter = cpu.GetRegister(Register.CX); if (counter != 0) { new JumpRelative().Dispatch(cpu, instruction); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { new Divide8().Dispatch(cpu, instruction); } else { new Divide16().Dispatch(cpu, instruction); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { cpu.SetRegister(Register.IP, cpu.Pop()); if (instruction.Argument1 == OpCodeManager.ARG_CONSTANT) { cpu.SetRegister(Register.SP, (ushort)(cpu.GetRegister(Register.SP) + instruction.Argument1Value)); } else { Debug.Assert(instruction.Argument1 == OpCodeManager.ARG_NONE); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var al = cpu.GetRegisterU8(Register.AL); var oldAl = al; var flags = cpu.GetFlags(); var oldCarry = flags.Has(FlagsRegister.Carry); flags &= ~FlagsRegister.Carry; if ((al & 0xF) > 9 || flags.Has(FlagsRegister.Auxiliary)) { al -= 6; if (oldCarry || (al > oldAl)) { flags |= FlagsRegister.Carry; } else { flags &= ~FlagsRegister.Carry; } flags |= FlagsRegister.Auxiliary; } else { flags &= ~FlagsRegister.Auxiliary; } if (oldAl > 0x99 || oldCarry) { al -= 0x60; flags |= FlagsRegister.Carry; } else { flags &= ~FlagsRegister.Carry; } flags &= ~(FlagsRegister.Parity | FlagsRegister.Zero | FlagsRegister.Sign); flags |= (InstructionHelper.ParityLookup[al] ? FlagsRegister.Parity : 0) | (al == 0 ? FlagsRegister.Zero : 0) | ((al & 0x80) != 0 ? FlagsRegister.Sign : 0); cpu.SetFlags(flags); cpu.SetRegister(Register.AL, al); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var value = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument2, instruction.Argument2Value, instruction.Argument2Displacement); switch (instruction.Argument1) { case (int)Register.AX: case (int)Register.CX: case (int)Register.DX: case (int)Register.BX: case (int)Register.SP: case (int)Register.BP: case (int)Register.SI: case (int)Register.DI: case (int)Register.IP: case (int)Register.CS: case (int)Register.DS: case (int)Register.ES: case (int)Register.SS: cpu.SetRegister((Register)instruction.Argument1, value); break; case OpCodeManager.ARG_BYTE_REGISTER: cpu.SetRegisterU8((Register)instruction.Argument1Value, (byte)value); break; case OpCodeManager.ARG_DEREFERENCE: case OpCodeManager.ARG_MEMORY: var address = InstructionHelper.GetInstructionRealAddress(cpu, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement); if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { cpu.WriteU8(address, (byte)value); } else { cpu.WriteU16(address, value); } break; default: throw new NotImplementedException(); } }
public Mini8086Emulator() { var components = new List <BaseComponent>(); _memMapper = new MemoryMapper(512); _portMapper = new PortMapper(); _cpu = new Cpu8086(_memMapper, _portMapper); _disassembler = new Disassembler(_cpu, _memMapper); components.Add(_bios = new Rom(Config.BiosMemAddress)); _memMapper.Register(Config.BiosMemAddress, Config.BiosMemAddress + Config.BiosMemSize - 1, _bios); components.Add(_pic = new InterruptController(Config.PicBasePort)); _portMapper.Register(Config.PicBasePort, Config.PicBasePort + 0x07, _pic); components.Add(_timer = new Timer(Config.TimerBasePort, _pic)); _portMapper.Register(Config.TimerBasePort, Config.TimerBasePort + 0x07, _timer); components.Add(_graphicsAdapter = new GraphicsAdapter(Config.VgaBasePort, Config.VgaMemAddress, _pic, @"..\..\..\ROMs\charrom.bin")); _portMapper.Register(Config.VgaBasePort, Config.VgaBasePort + 0x07, _graphicsAdapter); _memMapper.Register(Config.VgaMemAddress, Config.VgaMemAddress + Config.VgaMemSize - 1, _graphicsAdapter); components.Add(_lcd = new Lcd44780(Config.LcdBasePort)); _portMapper.Register(Config.LcdBasePort, Config.LcdBasePort + 0x07, _lcd); //components.Add(_ppi = new Ppi(Config.PpiBasePort)); //_portMapper.Register(Config.PpiBasePort, Config.PpiBasePort + 0x07, _ppi); components.Add(_keybController = new KeybController(Config.KeybControllerBasePort, _pic)); _portMapper.Register(Config.KeybControllerBasePort, Config.KeybControllerBasePort + 0x07, _keybController); components.Add(_sdController = new SdController(Config.SdControllerBasePort, Config.SdImagePath)); _portMapper.Register(Config.SdControllerBasePort, Config.SdControllerBasePort + 0x07, _sdController); _memMapper.FinishRegistration(); components.ForEach(_ => { _.EventTimer = _cpu; _.DoCpuInterrupt = _cpu.DoInterrupt; }); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { switch (instruction.Argument1) { case OpCodeManager.ARG_FAR_MEMORY: cpu.SetRegister(Register.CS, (ushort)((uint)instruction.Argument1Value >> 16)); cpu.SetRegister(Register.IP, (ushort)(instruction.Argument1Value & 0xFFFF)); break; case OpCodeManager.ARG_DEREFERENCE: case OpCodeManager.ARG_MEMORY: var address = InstructionHelper.GetInstructionRealAddress(cpu, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement); cpu.SetRegister(Register.CS, cpu.ReadU16(address + 2)); cpu.SetRegister(Register.IP, cpu.ReadU16(address)); break; default: throw new InvalidOperationException(); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var port = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument2, instruction.Argument2Value, instruction.Argument2Displacement); var device = cpu.GetPortDevice(port); if (device == null) { throw new InvalidOperationException($"Tried to read from port 0x{port.ToString("X")}"); } if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { cpu.SetRegister(Register.AL, device.Read(port)); //Console.WriteLine($"IN {port.ToString("X")}:{cpu.GetRegister(Register.AL).ToString("X")}"); } else { cpu.SetRegister(Register.AX, device.Read16(port)); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var port = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement); var device = cpu.GetPortDevice(port); if (device == null) { throw new InvalidOperationException($"Tried to write to port 0x{port.ToString("X")}"); } if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { //Console.WriteLine($"OUT {port.ToString("X")}:{cpu.GetRegister(Register.AL).ToString("X")}"); device.Write(port, (byte)cpu.GetRegister(Register.AL)); } else { device.Write16(port, cpu.GetRegister(Register.AX)); } }
private ushort ProcessExchangeSecond(Cpu8086 cpu, OpCodeManager.Instruction instruction, ushort value) { ushort tmp; switch (instruction.Argument2) { case (int)Register.AX: case (int)Register.CX: case (int)Register.DX: case (int)Register.BX: case (int)Register.SP: case (int)Register.BP: case (int)Register.SI: case (int)Register.DI: case (int)Register.IP: case (int)Register.CS: case (int)Register.DS: case (int)Register.ES: case (int)Register.SS: tmp = cpu.GetRegister((Register)instruction.Argument2); cpu.SetRegister((Register)instruction.Argument2, (byte)value); break; case OpCodeManager.ARG_BYTE_REGISTER: tmp = cpu.GetRegisterU8((Register)instruction.Argument2Value); cpu.SetRegisterU8((Register)instruction.Argument2Value, (byte)value); break; case OpCodeManager.ARG_DEREFERENCE: case OpCodeManager.ARG_MEMORY: var address = InstructionHelper.GetInstructionRealAddress(cpu, instruction.SegmentPrefix, instruction.Argument2, instruction.Argument2Value, instruction.Argument2Displacement); tmp = cpu.ReadU16(address); cpu.WriteU16(address, value); break; default: throw new NotImplementedException(); } return(tmp); }