Exemple #1
0
 public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
 {
     if (cpu.GetRegister(Register.CX) == 0)
     {
         new JumpRelative().Dispatch(cpu, instruction);
     }
 }
Exemple #2
0
        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));
            }
        }
Exemple #3
0
        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();
            }
        }
Exemple #4
0
        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);
            }
        }
Exemple #5
0
        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));
            }
        }
Exemple #6
0
 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);
     }
 }
Exemple #7
0
        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);
        }
Exemple #8
0
        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);
            }
        }
Exemple #9
0
        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);
            }
        }
Exemple #10
0
        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));
            }
        }
Exemple #11
0
        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);
        }
Exemple #12
0
        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);
        }
Exemple #13
0
 public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
 {
     cpu.SetRegister(Register.DX, (cpu.GetRegister(Register.AX) & 0x8000) != 0 ? (ushort)0xFFFF : (ushort)0);
 }
Exemple #14
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();
            }
        }
Exemple #15
0
 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));
 }
Exemple #16
0
        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();
            }
        }
Exemple #17
0
 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);
 }
Exemple #18
0
        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));
        }
Exemple #19
0
 public int GetCurrentAddress()
 {
     return(_cpu.GetRegister(Register.CS) * 0x10 + _cpu.GetRegister(Register.IP));
 }