Beispiel #1
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();
            }
        }
Beispiel #2
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:
                //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();
            }
        }
Beispiel #3
0
        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();
            }
        }
Beispiel #4
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));
            }
        }
Beispiel #5
0
        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));
            }
        }
Beispiel #6
0
 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();
 }
Beispiel #7
0
        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));
        }
Beispiel #8
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);
     }
 }
Beispiel #9
0
        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();
            }
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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();
            }
        }
Beispiel #12
0
        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));
            }
        }
Beispiel #13
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));
            }
        }
Beispiel #14
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);
        }
Beispiel #15
0
        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);
        }
Beispiel #16
0
        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();
            }
        }
Beispiel #17
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);
        }
Beispiel #18
0
 public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
 {
     cpu.SetRegister(Register.AX, (ushort)(sbyte)cpu.GetRegisterU8(Register.AL));
 }
Beispiel #19
0
 public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
 {
     cpu.SetRegister(Register.DX, (cpu.GetRegister(Register.AX) & 0x8000) != 0 ? (ushort)0xFFFF : (ushort)0);
 }
Beispiel #20
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            var value1 = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement);
            var value2 = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument2, instruction.Argument2Value, instruction.Argument2Displacement);

            if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
            {
                value1 &= 0xFF;
                value2 &= 0xFF;
            }

            int  result;
            bool carry;

            switch (instruction.Type)
            {
            case OpCodeManager.InstructionType.Adc:
                result = value1 + value2 + (cpu.GetFlags().Has(FlagsRegister.Carry) ? 1 : 0);
                InstructionHelper.CalculateAddFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.Add:
                result = value1 + value2;
                InstructionHelper.CalculateAddFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.And:
            case OpCodeManager.InstructionType.Test:
                result = value1 & value2;
                InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.Compare:
            case OpCodeManager.InstructionType.Subtract:
                result = value1 - value2;
                InstructionHelper.CalculateSubFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.Or:
                result = value1 | value2;
                InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.Rcl:
                if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
                {
                    const int mask  = 0x1FF;
                    var       shift = (value2 & 0x1F) % 9;

                    result = (byte)value1;
                    if (cpu.Flags.Has(FlagsRegister.Carry))
                    {
                        result |= 0x100;
                    }
                    result = (byte)(result << shift) | (byte)(result >> (-shift & mask));
                    if ((result & 0x100) != 0)
                    {
                        cpu.Flags |= FlagsRegister.Carry;
                    }
                    else
                    {
                        cpu.Flags &= ~FlagsRegister.Carry;
                    }

                    if (value2 == 1)
                    {
                        if (((result & 0x100) != 0) ^ ((result & 0x80) != 0))
                        {
                            cpu.Flags |= FlagsRegister.Overflow;
                        }
                        else
                        {
                            cpu.Flags &= ~FlagsRegister.Overflow;
                        }
                    }
                }
                else
                {
                    const int mask  = 0x1FFFF;
                    var       shift = (value2 & 0x1F) % 17;

                    result = value1;
                    if (cpu.Flags.Has(FlagsRegister.Carry))
                    {
                        result |= 0x10000;
                    }
                    result = (ushort)(result << shift) | (ushort)(result >> (-shift & mask));
                    if ((result & 0x10000) != 0)
                    {
                        cpu.Flags |= FlagsRegister.Carry;
                    }
                    else
                    {
                        cpu.Flags &= ~FlagsRegister.Carry;
                    }

                    if (value2 == 1)
                    {
                        if (((result & 0x10000) != 0) ^ ((result & 0x8000) != 0))
                        {
                            cpu.Flags |= FlagsRegister.Overflow;
                        }
                        else
                        {
                            cpu.Flags &= ~FlagsRegister.Overflow;
                        }
                    }
                }
                InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.Rcr:
                if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
                {
                    const int mask  = 0x1FF;
                    var       shift = (value2 & 0x1F) % 9;

                    result = (byte)value1;
                    if (cpu.Flags.Has(FlagsRegister.Carry))
                    {
                        result |= 0x100;
                    }

                    if ((result & 0x1) != 0)
                    {
                        cpu.Flags |= FlagsRegister.Carry;
                    }
                    else
                    {
                        cpu.Flags &= ~FlagsRegister.Carry;
                    }

                    result = (byte)(result >> shift) | (byte)(result << (-shift & mask));

                    if (value2 == 1)
                    {
                        if (((result & 0x80) != 0) ^ ((result & 0x40) != 0))
                        {
                            cpu.Flags |= FlagsRegister.Overflow;
                        }
                        else
                        {
                            cpu.Flags &= ~FlagsRegister.Overflow;
                        }
                    }
                }
                else
                {
                    const int mask  = 0x1FFFF;
                    var       shift = (value2 & 0x1F) % 17;

                    result = value1;
                    if (cpu.Flags.Has(FlagsRegister.Carry))
                    {
                        result |= 0x10000;
                    }

                    if ((result & 0x1) != 0)
                    {
                        cpu.Flags |= FlagsRegister.Carry;
                    }
                    else
                    {
                        cpu.Flags &= ~FlagsRegister.Carry;
                    }

                    result = (ushort)(result >> shift) | (ushort)(result << (-shift & mask));

                    if (value2 == 1)
                    {
                        if (((result & 0x8000) != 0) ^ ((result & 0x4000) != 0))
                        {
                            cpu.Flags |= FlagsRegister.Overflow;
                        }
                        else
                        {
                            cpu.Flags &= ~FlagsRegister.Overflow;
                        }
                    }
                }
                //cpu.CalculateBitwiseFlags(instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.Rol:
                if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
                {
                    const int mask  = 0xFF;
                    var       shift = value2 & mask;
                    result = (byte)(value1 << shift) | (byte)(value1 >> (-shift & mask));
                }
                else
                {
                    const int mask  = 0xFFFF;
                    var       shift = value2 & mask;
                    result = (ushort)(value1 << shift) | (ushort)(value1 >> (-shift & mask));
                }
                InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.Ror:
                if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
                {
                    const int mask  = 0xFF;
                    var       shift = value2 & mask;
                    result = (byte)(value1 >> shift) | (byte)(value1 << (-shift & mask));
                }
                else
                {
                    const int mask  = 0xFFFF;
                    var       shift = value2 & mask;
                    result = (ushort)(value1 >> shift) | (ushort)(value1 << (-shift & mask));
                }
                InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.Sbb:
                result = value1 - (value2 + (cpu.GetFlags().Has(FlagsRegister.Carry) ? 1 : 0));
                InstructionHelper.CalculateSubFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            case OpCodeManager.InstructionType.Shl:
                bool overflow;
                result = value1 << (value2 & 0x1F);
                InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, value1, (ushort)(value2 & 0x1F), result);
                if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
                {
                    carry    = (result & 0x100) != 0;
                    overflow = (result & 0x80) != 0;
                }
                else
                {
                    carry    = (result & 0x10000) != 0;
                    overflow = (result & 0x8000) != 0;
                }
                if (carry)
                {
                    cpu.Flags |= FlagsRegister.Carry;
                }
                if ((value2 & 0x1F) == 1 && overflow ^ carry)
                {
                    cpu.Flags |= FlagsRegister.Overflow;
                }
                break;

            case OpCodeManager.InstructionType.Sar:
                if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
                {
                    carry  = (((sbyte)value1 >> ((value2 & 0x1F) - 1)) & 1) != 0;
                    result = (sbyte)value1 >> (value2 & 0x1F);
                }
                else
                {
                    carry  = (((short)value1 >> ((value2 & 0x1F) - 1)) & 1) != 0;
                    result = (short)value1 >> (value2 & 0x1F);
                }
                InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, value1, (ushort)(value2 & 0x1F), result);
                if (carry)
                {
                    cpu.Flags |= FlagsRegister.Carry;
                }
                break;

            case OpCodeManager.InstructionType.Shr:
                carry  = ((value1 >> ((value2 & 0x1F) - 1)) & 1) != 0;
                result = value1 >> (value2 & 0x1F);
                InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, value1, (ushort)(value2 & 0x1F), result);
                if (carry)
                {
                    cpu.Flags |= FlagsRegister.Carry;
                }
                if ((value2 & 0x1F) == 1)
                {
                    if (instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8))
                    {
                        if ((value1 & 0x80) != 0)
                        {
                            cpu.Flags |= FlagsRegister.Overflow;
                        }
                    }
                    else
                    {
                        if ((value1 & 0x8000) != 0)
                        {
                            cpu.Flags |= FlagsRegister.Overflow;
                        }
                    }
                }
                break;

            case OpCodeManager.InstructionType.Xor:
                result = value1 ^ value2;
                InstructionHelper.CalculateBitwiseFlags(cpu, instruction.Flag, value1, value2, result);
                break;

            default:
                throw new NotImplementedException();
            }

            var truncResult = instruction.Flag.Has(OpCodeManager.OpCodeFlag.Size8) ? (byte)result : (ushort)result;

            if (instruction.Type != OpCodeManager.InstructionType.Compare && instruction.Type != OpCodeManager.InstructionType.Test)
            {
                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, truncResult);
                    break;

                case OpCodeManager.ARG_BYTE_REGISTER:
                    cpu.SetRegisterU8((Register)instruction.Argument1Value, (byte)truncResult);
                    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)truncResult);
                    }
                    else
                    {
                        cpu.WriteU16(address, truncResult);
                    }
                    break;

                default:
                    throw new NotImplementedException();
                }
            }
        }
Beispiel #21
0
 public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction) =>
 cpu.SetRegister(Register.AH, (byte)cpu.GetFlags());
Beispiel #22
0
        public void Dispatch(Cpu8086 cpu, OpCodeManager.Instruction instruction)
        {
            var value = InstructionHelper.GetInstructionValue(cpu, instruction.Flag, instruction.SegmentPrefix, instruction.Argument1, instruction.Argument1Value, instruction.Argument1Displacement);
            int result;

            switch (instruction.Type)
            {
            case OpCodeManager.InstructionType.Decrement:
                result = value - 1;
                InstructionHelper.CalculateDecFlags(cpu, instruction.Flag, value, 1, result);
                break;

            case OpCodeManager.InstructionType.Increment:
                result = value + 1;
                InstructionHelper.CalculateIncFlags(cpu, instruction.Flag, value, 1, result);
                break;

            case OpCodeManager.InstructionType.Negate:
                result = ~value + 1;
                InstructionHelper.CalculateSubFlags(cpu, instruction.Flag, 0, value, result);
                break;

            case OpCodeManager.InstructionType.Not:
                result = ~value;
                break;

            default:
                throw new OutOfMemoryException();
            }

            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, (ushort)result);
                break;

            case OpCodeManager.ARG_BYTE_REGISTER:
                cpu.SetRegisterU8((Register)instruction.Argument1Value, (byte)result);
                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)result);
                }
                else
                {
                    cpu.WriteU16(address, (ushort)result);
                }
                break;

            default:
                throw new NotImplementedException();
            }
        }
Beispiel #23
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));
 }
Beispiel #24
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();
            }
        }