Beispiel #1
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            void @out(byte portNumber, ByteRegister dataRegister, bool bc)
            {
                Port port   = cpu.Ports[portNumber];
                byte output = 0;

                if (dataRegister != ByteRegister.None)
                {
                    output = r[dataRegister];
                }
                port.SignalWrite();
                port.WriteByte(output, bc);
            }

            if (instruction.Prefix == 0x00)
            {
                // OUT (n),A
                r.WZ = (ushort)((r.A << 8) + data.Argument1 + 1);
                @out(data.Argument1, ByteRegister.A, false);
            }
            else
            {
                // OUT (C),r
                @out(r.C, instruction.Source.AsByteRegister(), true);
                r.WZ = (ushort)(r.BC + 1);
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #2
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            Port port = cpu.Ports[r.C];

            port.SignalRead();
            byte input = port.ReadByte(true);

            cpu.Memory.Timed.WriteByteAt(r.HL, input);
            cpu.Timing.InternalOperationCycle(5);
            r.HL--;
            r.WZ = r.BC;
            r.B--;

            flags.Zero     = true;
            flags.Subtract = true;
            flags.X        = (input & 0x08) > 0; // copy bit 3
            flags.Y        = (input & 0x20) > 0; // copy bit 5

            if (r.B != 0)
            {
                r.PC = package.InstructionAddress;
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #3
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;

            switch (instruction.Opcode)
            {
            case 0x46:
            case 0x4E:
            case 0x66:     // IM 0
                cpu.SetInterruptMode(InterruptMode.IM0);
                break;

            case 0x56:
            case 0x76:     // IM 1
                cpu.SetInterruptMode(InterruptMode.IM1);
                break;

            case 0x5E:
            case 0x7E:     // IM 2
                cpu.SetInterruptMode(InterruptMode.IM2);
                break;
            }

            return(new ExecutionResult(package, null));
        }
Beispiel #4
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            byte value = cpu.Memory.Timed.ReadByteAt(r.HL);

            cpu.Memory.Timed.WriteByteAt(r.DE, value);
            r.HL++;
            r.DE++;
            r.BC--;

            flags.HalfCarry      = false;
            flags.ParityOverflow = (r.BC != 0);;
            flags.Subtract       = false;
            flags.X = (((byte)(value + cpu.Registers.A)) & 0x08) > 0; // copy bit 3
            flags.Y = (((byte)(value + cpu.Registers.A)) & 0x02) > 0; // copy bit 1 (note: non-standard behaviour)

            bool conditionTrue = (r.BC == 0);

            if (conditionTrue)
            {
                cpu.Timing.InternalOperationCycle(5);
                r.WZ = (ushort)(r.PC + 1);
            }
            else
            {
                r.PC = package.InstructionAddress;
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #5
0
 public ExecutionResult Execute(Processor cpu, InstructionPackage package)
 {
     cpu.Pop(WordRegister.PC);
     cpu.Registers.WZ = cpu.Registers.PC;
     cpu.RestoreInterruptsFromNMI(); // will re-enable maskable interrupts if they were enabled before entering the NMI handler
     return(new ExecutionResult(package, null));
 }
Beispiel #6
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Registers       r           = cpu.Registers;

            if (instruction.Opcode == 0x08)
            {
                // EX AF,AF'
                r.ExchangeAF();
            }
            else
            {
                if (instruction.Target == InstructionElement.AddressFromSP)
                {
                    // EX (SP),HL/IX/IY
                    ushort value     = instruction.MarshalSourceWord(data, cpu, out ushort address);
                    ushort valueAtSP = cpu.Memory.Untimed.ReadWordAt(r.SP);

                    r[instruction.Source.AsWordRegister()] = valueAtSP;
                    cpu.Memory.Timed.WriteWordAt(r.SP, value);

                    r.WZ = valueAtSP;
                }
                else
                {
                    // EX DE,HL
                    ushort de = r.DE;
                    r.DE = r.HL;
                    r.HL = de;
                }
            }

            return(new ExecutionResult(package, null));
        }
Beispiel #7
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            if (instruction.TargetsWordRegister)
            {
                ushort left = r.HL;
                cpu.Timing.InternalOperationCycle(4);
                cpu.Timing.InternalOperationCycle(3);
                ushort right = instruction.MarshalSourceWord(data, cpu, out ushort address);

                var addition = ALUOperations.Add(left, right, flags.Carry, true, flags);
                r.HL  = addition.Result;
                flags = addition.Flags;
                r.WZ  = (ushort)(left + 1);
            }
            else
            {
                byte left = r.A;
                if (instruction.IsIndexed)
                {
                    cpu.Timing.InternalOperationCycle(5);
                }
                byte right = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source);

                var addition = ALUOperations.Add(left, right, flags.Carry);
                r.A   = addition.Result;
                flags = addition.Flags;
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #8
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            Port port   = cpu.Ports[r.C];
            byte output = cpu.Memory.Timed.ReadByteAt(r.HL);

            r.WZ = r.BC;
            r.B--;
            port.SignalWrite();
            port.WriteByte(output, true);
            r.HL++;

            flags.Zero     = true;
            flags.Subtract = true;
            flags.X        = (output & 0x08) > 0; // copy bit 3
            flags.Y        = (output & 0x20) > 0; // copy bit 5

            if (r.B != 0)
            {
                r.PC = package.InstructionAddress;
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #9
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;

            bool carry = flags.Carry;
            byte a     = cpu.Registers.A;
            byte b     = cpu.Memory.Timed.ReadByteAt(cpu.Registers.HL);

            var compare = ALUOperations.Subtract(a, b, false);

            flags = compare.Flags;

            cpu.Registers.BC--;
            flags.ParityOverflow = (cpu.Registers.BC != 0);

            cpu.Registers.HL--;

            flags.Subtract = true;
            flags.Carry    = carry;

            byte valueXY = (byte)(a - b - (flags.HalfCarry ? 1 : 0));

            flags.X = (valueXY & 0x08) > 0; // copy bit 3
            flags.Y = (valueXY & 0x02) > 0; // copy bit 1 (note: non-standard behaviour)

            cpu.Registers.WZ++;

            return(new ExecutionResult(package, flags));
        }
Beispiel #10
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;

            if (instruction.Condition == Condition.None || cpu.Flags.SatisfyCondition(instruction.Condition))
            {
                cpu.Timing.InternalOperationCycle(5);
                ushort address = (ushort)(cpu.Registers.PC - 2); // wind back to the address of the JR instruction as PC has already moved on

                // the jump is relative to the address of the JR instruction but the jump *displacement* is calculated from the start of the *next* instruction.
                // This means the actual jump range is -126 to +129 bytes, *not* 127 bytes each way. Z80 assemblers compensate for this by
                // adjusting the jump value, so for example 'JR 0' would actually end up being 'JR 2' and would set PC to the start of the next
                // instruction - hence we must add two bytes here to resolve the correct target address
                address = (ushort)(address + (sbyte)data.Argument1 + 2);

                cpu.Registers.PC = address;
                cpu.Flags.X      = (address & 0x08) > 0; // copy bit 3
                cpu.Flags.Y      = (address & 0x20) > 0; // copy bit 5

                cpu.Registers.WZ = address;
            }

            return(new ExecutionResult(package, cpu.Flags));
        }
Beispiel #11
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;

            cpu.Halt(HaltReason.HaltInstruction);

            return(new ExecutionResult(package, null));
        }
Beispiel #12
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction instruction = package.Instruction;

            WordRegister register = instruction.Target.AsWordRegister();

            cpu.Pop(register);

            return(new ExecutionResult(package, null));
        }
Beispiel #13
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            sbyte        offset        = (sbyte)(data.Argument1);
            ByteRegister register      = instruction.Target.AsByteRegister();
            bool         previousCarry = flags.Carry;

            byte original, shifted;

            if (register != ByteRegister.None)
            {
                original = r[register];
                shifted  = (byte)(original >> 1);
                shifted  = shifted.SetBit(7, previousCarry);
                setFlags(original, shifted, original.GetBit(0));
                r[register] = shifted;
            }
            else
            {
                ushort address = instruction.Prefix switch
                {
                    0xCB => r.HL,
                    0xDDCB => (ushort)(r.IX + offset),
                    0xFDCB => (ushort)(r.IY + offset),
                    _ => (ushort)0xFFFF
                };
                original = cpu.Memory.Timed.ReadByteAt(address);
                shifted  = (byte)(original >> 1);
                shifted  = shifted.SetBit(7, previousCarry);
                setFlags(original, shifted, original.GetBit(0));
                if (instruction.IsIndexed)
                {
                    cpu.Timing.InternalOperationCycle(4);
                }
                cpu.Memory.Timed.WriteByteAt(address, shifted);
                if (instruction.CopyResultTo != ByteRegister.None)
                {
                    r[instruction.CopyResultTo.Value] = shifted;
                }
            }

            void setFlags(byte original, byte shifted, bool overflowBit)
            {
                flags           = FlagLookup.BitwiseFlags(original, BitwiseOperation.RotateRightThroughCarry, previousCarry);
                flags.Carry     = overflowBit;
                flags.HalfCarry = false;
                flags.Subtract  = false;
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #14
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;
            byte            A           = r.A;
            int             mode        = 0;

            if ((A & 0x0F) > 0x09 || flags.HalfCarry)
            {
                mode++;
            }

            if (A > 0x99 || flags.Carry)
            {
                mode       += 2;
                flags.Carry = true;
            }

            if (flags.Subtract && !flags.HalfCarry)
            {
                flags.HalfCarry = false;
            }
            else
            {
                if (flags.Subtract && flags.HalfCarry)
                {
                    flags.HalfCarry = (A & 0x0F) < 0x06;
                }
                else
                {
                    flags.HalfCarry = (A & 0x0F) >= 0x0A;
                }
            }

            A = mode switch
            {
                1 => (byte)(A + (byte)(flags.Subtract ? 0xFA : 0x06)),
                2 => (byte)(A + (byte)(flags.Subtract ? 0xA0 : 0x60)),
                3 => (byte)(A + (byte)(flags.Subtract ? 0x9A : 0x66)),
                _ => A
            };

            flags.Sign           = (A & 0x80) > 0;
            flags.Zero           = (A == 0);
            flags.ParityOverflow = A.EvenParity();
            flags.X = (A & 0x08) > 0; // copy bit 3
            flags.Y = (A & 0x20) > 0; // copy bit 5

            r.A = A;

            return(new ExecutionResult(package, flags));
        }
Beispiel #15
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Flags flags = cpu.Flags;

            flags.Carry     = true;
            flags.HalfCarry = false;
            flags.Subtract  = false;
            flags.X         = (cpu.Registers.A & 0x08) > 0; // copy bit 3
            flags.Y         = (cpu.Registers.A & 0x20) > 0; // copy bit 5
            return(new ExecutionResult(package, flags));
        }
Beispiel #16
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;

            if (instruction.Condition == Condition.None || flags.SatisfyCondition(instruction.Condition))
            {
                cpu.Pop(WordRegister.PC);
                cpu.Registers.WZ = cpu.Registers.PC;
            }
            return(new ExecutionResult(package, flags));
        }
Beispiel #17
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;

            byte   t_index = instruction.Opcode.GetByteFromBits(3, 3);
            ushort address = (ushort)(t_index * 8);

            cpu.Push(WordRegister.PC);
            cpu.Registers.PC = (address);
            cpu.Registers.WZ = cpu.Registers.PC;

            return(new ExecutionResult(package, null));
        }
Beispiel #18
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Registers       r           = cpu.Registers;
            Flags           flags       = cpu.Flags;

            int result = 0x00 - r.A;

            flags = FlagLookup.ByteArithmeticFlags(0x00, r.A, false, true);
            flags.ParityOverflow = r.A == 0x80;
            flags.Carry          = r.A != 0x00;
            r.A = (byte)result;

            return(new ExecutionResult(package, flags));
        }
Beispiel #19
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction instruction = package.Instruction;
            InstructionData data = package.Data;
            Flags flags = cpu.Flags;
            Registers r = cpu.Registers;
            sbyte offset = (sbyte)(data.Argument1);
            ByteRegister register = instruction.Target.AsByteRegister();

            void setFlags(byte original)
            {
                flags = FlagLookup.BitwiseFlags(original, BitwiseOperation.ShiftLeftSetBit0, flags.Carry);
                flags.Carry = original.GetBit(7);
                flags.HalfCarry = false;
                flags.Subtract = false;
            }

            byte original, shifted;
            if (register != ByteRegister.None)
            {
                original = r[register];
                shifted = (byte)((original << 1) + 1); // bit 0 is always set, adding 1 does this quicker than calling SetBit
                setFlags(original);
                r[register] = shifted;
            }
            else
            {
                ushort address = instruction.Prefix switch
                {
                    0xCB => r.HL,
                    0xDDCB => (ushort)(r.IX + offset),
                    0xFDCB => (ushort)(r.IY + offset),
                    _ => (ushort)0xFFFF
                };
                original = cpu.Memory.Timed.ReadByteAt(address);
                shifted = (byte)((original << 1) + 1);
                setFlags(original);
                cpu.Memory.Timed.WriteByteAt(address, shifted);
                if (instruction.CopyResultTo != ByteRegister.None)
                {
                    r[instruction.CopyResultTo.Value] = shifted;
                }
            }

            return new ExecutionResult(package, flags);
        }
Beispiel #20
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Registers       r           = cpu.Registers;
            byte            offset      = data.Argument1;
            Flags           flags       = cpu.Flags;

            if (instruction.TargetsWordRegister)
            {
                // inc 16-bit
                WordRegister register = instruction.Target.AsWordRegister();
                ushort       value    = r[register];
                r[register] = (ushort)(value + 1);
            }
            else
            {
                byte value = 0;
                if (instruction.TargetsByteInMemory)
                {
                    // inc byte in memory
                    if (instruction.IsIndexed)
                    {
                        cpu.Timing.InternalOperationCycle(5);
                    }
                    value = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source);
                    cpu.Memory.Timed.WriteByteAt(address, (byte)(value + 1));
                }
                else
                {
                    // it's an 8-bit inc
                    ByteRegister register = instruction.Target.AsByteRegister();
                    value       = r[register];
                    r[register] = (byte)(value + 1);
                }

                bool carry = flags.Carry;
                flags = FlagLookup.ByteArithmeticFlags(value, 1, false, false);
                flags.ParityOverflow = (value == 0x7F);
                flags.Carry          = carry; // always unaffected
                flags.Subtract       = false;
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #21
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Registers       r           = cpu.Registers;
            Flags           flags       = cpu.Flags;

            byte         bitIndex = instruction.GetBitIndex();
            byte         value;
            ByteRegister register = instruction.Source.AsByteRegister();

            if (register != ByteRegister.None)
            {
                value = r[register]; // BIT b, r
            }
            else
            {
                if (instruction.IsIndexed)
                {
                    cpu.Timing.InternalOperationCycle(5);
                }
                value = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source);
                byte valueXY = instruction.IsIndexed ? address.HighByte() : r.WZ.HighByte(); // this is literally the only place the WZ value is *ever* actually used
                flags.X = (valueXY & 0x08) > 0;                                              // copy bit 3
                flags.Y = (valueXY & 0x20) > 0;                                              // copy bit 5
            }

            bool set = value.GetBit(bitIndex);

            flags.Sign = bitIndex == 7 && set;

            if (register == ByteRegister.None)
            {
                flags.Y = bitIndex == 5 && set;
                flags.X = bitIndex == 3 && set;
            }

            flags.Zero           = !set;
            flags.ParityOverflow = flags.Zero;
            flags.HalfCarry      = true;
            flags.Subtract       = false;

            return(new ExecutionResult(package, flags));
        }
Beispiel #22
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;

            if (instruction.Source != InstructionElement.WordValue)
            {
                // JP HL / IX / IY
                cpu.Registers.PC = instruction.MarshalSourceWord(data, cpu, out ushort address);
            }
            else if (instruction.Condition == Condition.None || flags.SatisfyCondition(instruction.Condition))
            {
                cpu.Registers.PC = data.ArgumentsAsWord;
                cpu.Registers.WZ = data.ArgumentsAsWord;
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #23
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            if (instruction.IsIndexed)
            {
                cpu.Timing.InternalOperationCycle(5);
            }
            byte operand = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source);
            int  result  = (r.A | operand);

            flags = FlagLookup.LogicalFlags(r.A, operand, LogicalOperation.Or);
            r.A   = (byte)result;

            return(new ExecutionResult(package, flags));
        }
Beispiel #24
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            byte @in(byte portNumber, ByteRegister toRegister, bool bc)
            {
                Port port = cpu.Ports[portNumber];

                port.SignalRead();
                byte input = port.ReadByte(bc);

                if (toRegister != ByteRegister.F)
                {
                    r[toRegister] = input;
                }
                return(input);
            }

            if (instruction.Prefix == 0x00)
            {
                // IN A,(n)
                r.WZ = (ushort)((r.A << 8) + data.Argument1 + 1);
                @in(data.Argument1, ByteRegister.A, false);
            }
            else
            {
                // IN r,(C)
                byte input = @in(r.C, instruction.Target.AsByteRegister(), true);
                flags.Sign           = ((sbyte)input < 0);
                flags.Zero           = (input == 0);
                flags.ParityOverflow = input.EvenParity();
                flags.HalfCarry      = false;
                flags.Subtract       = false;
                flags.X = (input & 0x08) > 0; // copy bit 3
                flags.Y = (input & 0x20) > 0; // copy bit 5
                r.WZ    = (ushort)(r.BC + 1);
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #25
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;

            bool carry = flags.Carry;
            byte a     = cpu.Registers.A;
            byte b     = cpu.Memory.Timed.ReadByteAt(cpu.Registers.HL);

            var compare = ALUOperations.Subtract(a, b, false);

            flags = compare.Flags;

            cpu.Registers.BC--;
            flags.ParityOverflow = (cpu.Registers.BC != 0);

            cpu.Registers.HL++;

            flags.Subtract = true;
            flags.Carry    = carry;

            byte valueXY = (byte)(a - b - (flags.HalfCarry ? 1 : 0));

            flags.X = (valueXY & 0x08) > 0; // copy bit 3
            flags.Y = (valueXY & 0x02) > 0; // copy bit 1 (note: non-standard behaviour)

            bool conditionTrue = (compare.Result == 0 || cpu.Registers.BC == 0);

            if (conditionTrue)
            {
                cpu.Timing.InternalOperationCycle(5);
                cpu.Registers.WZ++;
            }
            else
            {
                cpu.Registers.PC = package.InstructionAddress;
                cpu.Registers.WZ = (ushort)(cpu.Registers.PC + 1);
            }

            return(new ExecutionResult(package, flags));
        }
Beispiel #26
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            byte value = r.A;

            flags.Carry     = value.GetBit(0);
            value           = (byte)(value >> 1);
            value           = value.SetBit(7, flags.Carry);
            flags.HalfCarry = false;
            flags.Subtract  = false;
            flags.X         = (value & 0x08) > 0; // copy bit 3
            flags.Y         = (value & 0x20) > 0; // copy bit 5

            r.A = value;

            return(new ExecutionResult(package, flags));
        }
Beispiel #27
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            byte left  = r.A;
            byte right = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source);

            if (instruction.IsIndexed)
            {
                cpu.Timing.InternalOperationCycle(5);
            }
            var sub = ALUOperations.Subtract(left, right, false);

            r.A   = sub.Result;
            flags = sub.Flags;

            return(new ExecutionResult(package, flags));
        }
Beispiel #28
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Registers       r           = cpu.Registers;
            byte            bitIndex    = instruction.GetBitIndex();
            sbyte           offset      = (sbyte)(data.Argument1);

            ByteRegister register = instruction.Source.AsByteRegister();

            if (register != ByteRegister.None)
            {
                byte value = r[register].SetBit(bitIndex, true);
                r[register] = value;
            }
            else
            {
                ushort address = instruction.Prefix switch
                {
                    0xCB => r.HL,
                    0xDDCB => (ushort)(r.IX + offset),
                    0xFDCB => (ushort)(r.IY + offset),
                    _ => (ushort)0xFFFF
                };
                if (instruction.IsIndexed)
                {
                    cpu.Timing.InternalOperationCycle(5);
                }

                byte value = cpu.Memory.Timed.ReadByteAt(address);
                value = value.SetBit(bitIndex, true);
                cpu.Memory.Timed.WriteByteAt(address, value);
                if (instruction.CopyResultTo != ByteRegister.None)
                {
                    r[instruction.CopyResultTo.Value] = value;
                }
            }

            return(new ExecutionResult(package, null));
        }
Beispiel #29
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            byte value = cpu.Memory.Timed.ReadByteAt(r.HL);

            cpu.Memory.Timed.WriteByteAt(r.DE, value);
            r.HL++;
            r.DE++;
            r.BC--;

            flags.HalfCarry      = false;
            flags.ParityOverflow = (r.BC != 0);
            flags.Subtract       = false;
            flags.X = (((byte)(value + cpu.Registers.A)) & 0x08) > 0; // copy bit 3
            flags.Y = (((byte)(value + cpu.Registers.A)) & 0x02) > 0; // copy bit 1 (note: non-standard behaviour)

            return(new ExecutionResult(package, flags));
        }
Beispiel #30
0
        public ExecutionResult Execute(Processor cpu, InstructionPackage package)
        {
            Instruction     instruction = package.Instruction;
            InstructionData data        = package.Data;
            Flags           flags       = cpu.Flags;
            Registers       r           = cpu.Registers;

            if (instruction.TargetsWordRegister)
            {
                // it's one of the 16-bit adds (HL,DE etc)
                WordRegister destination = instruction.Target.AsWordRegister();
                ushort       left        = r[destination];
                ushort       right       = instruction.MarshalSourceWord(data, cpu, out ushort address);

                cpu.Timing.InternalOperationCycle(4);
                cpu.Timing.InternalOperationCycle(3);
                var sum = ALUOperations.Add(left, right, false, false, flags);
                r[destination] = sum.Result;
                flags          = sum.Flags;
                r.WZ           = (ushort)(left + 1);
            }
            else
            {
                // it's an 8-bit add to A
                byte left = r.A;
                if (instruction.IsIndexed)
                {
                    cpu.Timing.InternalOperationCycle(5);
                }
                byte right = instruction.MarshalSourceByte(data, cpu, out ushort address, out ByteRegister source);

                var sum = ALUOperations.Add(left, right, false);
                r.A   = sum.Result;
                flags = sum.Flags;
            }

            return(new ExecutionResult(package, flags));
        }