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) { 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.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) { 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) { 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)); } }
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 value1 = (int)(((uint)cpu.GetRegister(Register.DX) << 16) | cpu.GetRegister(Register.AX)); int value2 = (short)InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement); if ((uint)value1 == 0x80000000 || value2 == 0) { cpu.Interrupt(0); return; } var quotient = value1 / value2; var remainder = value1 % value2; if ((quotient & 0xFFFF) != quotient) { cpu.Interrupt(0); return; } cpu.SetRegister(Register.AX, (ushort)quotient); cpu.SetRegister(Register.DX, (ushort)remainder); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var segment = Register.DS; if (instruction.SegmentPrefix != Register.Invalid) { segment = instruction.SegmentPrefix; } var sourceAddress = InstructionHelper.SegmentToAddress(cpu.GetRegister(segment), cpu.GetRegister(Register.SI)); var destAddress = InstructionHelper.SegmentToAddress(cpu.GetRegister(Register.ES), cpu.GetRegister(Register.DI)); byte size; if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { var value = cpu.ReadU8(sourceAddress); cpu.WriteU8(destAddress, value); size = 1; } else { var value = cpu.ReadU16(sourceAddress); cpu.WriteU16(destAddress, value); size = 2; } if (!cpu.GetFlags().Has(FlagsRegister.Direction)) { cpu.IncRegister(Register.DI, size); cpu.IncRegister(Register.SI, size); } else { cpu.DecRegister(Register.DI, size); cpu.DecRegister(Register.SI, size); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { byte size; if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { cpu.WriteU8(InstructionHelper.SegmentToAddress(cpu.GetRegister(Register.ES), cpu.GetRegister(Register.DI)), (byte)(cpu.GetRegister(Register.AX) & 0xFF)); size = 1; } else { cpu.WriteU16(InstructionHelper.SegmentToAddress(cpu.GetRegister(Register.ES), cpu.GetRegister(Register.DI)), cpu.GetRegister(Register.AX)); size = 2; } 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) { var segment = Register.DS; if (instruction.SegmentPrefix != Register.Invalid) { segment = instruction.SegmentPrefix; } ushort value1; ushort value2; byte size; if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8)) { value1 = cpu.ReadU8(InstructionHelper.SegmentToAddress(cpu.GetRegister(segment), cpu.GetRegister(Register.SI))); value2 = cpu.ReadU8(InstructionHelper.SegmentToAddress(cpu.GetRegister(Register.ES), cpu.GetRegister(Register.DI))); size = 1; } else { value1 = cpu.ReadU16(InstructionHelper.SegmentToAddress(cpu.GetRegister(segment), cpu.GetRegister(Register.SI))); 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.SetRegister(Register.DI, (ushort)(cpu.GetRegister(Register.DI) + size)); cpu.SetRegister(Register.SI, (ushort)(cpu.GetRegister(Register.SI) + size)); } else { cpu.SetRegister(Register.DI, (ushort)(cpu.GetRegister(Register.DI) - size)); cpu.SetRegister(Register.SI, (ushort)(cpu.GetRegister(Register.SI) - size)); } }
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); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { uint value1 = cpu.GetRegister(Register.AX); uint value2 = (byte)InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement); if (value2 == 0) { cpu.Interrupt(0); return; } var quotient = value1 / value2; if (quotient > 0xFF) { cpu.Interrupt(0); return; } var remainder = value1 % value2; cpu.SetRegisterU8(Register.AL, (byte)quotient); cpu.SetRegisterU8(Register.AH, (byte)remainder); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { cpu.SetRegister(Register.DX, (cpu.GetRegister(Register.AX) & 0x8000) != 0 ? (ushort)0xFFFF : (ushort)0); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { ushort counter; switch (instruction.OpcodePrefix) { case 0: new OneStringOperation().Dispatch(cpu, instruction); break; case 0xF2: counter = cpu.GetRegister(Register.CX); if (instruction.Type == OpCodeManager.InstructionType.Cmps || instruction.Type == OpCodeManager.InstructionType.Scas) { while (counter != 0) { new OneStringOperation().Dispatch(cpu, instruction); counter--; if (cpu.GetFlags().Has(FlagsRegister.Zero)) { break; } } } else { while (counter != 0) { new OneStringOperation().Dispatch(cpu, instruction); counter--; } } cpu.SetRegister(Register.CX, counter); break; case 0xF3: counter = cpu.GetRegister(Register.CX); if (instruction.Type == OpCodeManager.InstructionType.Cmps || instruction.Type == OpCodeManager.InstructionType.Scas) { while (counter != 0) { new OneStringOperation().Dispatch(cpu, instruction); counter--; if (!cpu.GetFlags().Has(FlagsRegister.Zero)) { break; } } } else { while (counter != 0) { new OneStringOperation().Dispatch(cpu, instruction); counter--; } } cpu.SetRegister(Register.CX, counter); break; default: throw new NotImplementedException(); } }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { Debug.Assert(instruction.Argument1 == OpCodeManager.ARG_CONSTANT); cpu.Push(cpu.GetRegister(Register.IP)); cpu.SetRegister(Register.IP, (ushort)(cpu.GetRegister(Register.IP) + instruction.Argument1Value)); }
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) { cpu.Push(cpu.GetRegister(Register.CS)); cpu.Push(cpu.GetRegister(Register.IP)); new FarJump().Dispatch(cpu, instruction); }
public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) { var address = InstructionHelper.SegmentToAddress(cpu.GetRegister(Register.DS), (ushort)(cpu.GetRegister(Register.BX) + cpu.GetRegisterU8(Register.AL))); cpu.SetRegisterU8(Register.AL, cpu.ReadU8(address)); }
public int GetCurrentAddress() { return(_cpu.GetRegister(Register.CS) * 0x10 + _cpu.GetRegister(Register.IP)); }