예제 #1
0
 public CPU(MMU mmu, Clock clock)
 {
     this.clock       = clock;
     this.mmu         = mmu;
     this.Registers   = new Registers(mmu);
     this.ControlUnit = new ControlUnit(mmu, this.Registers);
 }
예제 #2
0
파일: Cpu.cs 프로젝트: FredrikL/DCPU16
 public Cpu(IRegisters registers, IRam ram)
 {
     this.registers = registers;
     this.ram = ram;
     this.destinationProvider = new DestinationProvider(registers, ram);
     this.sourceProvider = new SourceProvider(registers, ram);
 }
예제 #3
0
 /// <summary>
 /// Constructor for injecting an observed set of registers for unit testing.
 /// </summary>
 /// <param name="mmu">
 /// Memory subsystem of the Game Boy
 /// </param>
 /// <param name="reg">
 /// A Set of registers that the CPU needs. Here the registers are being injected,
 /// so that they can be observed by unit tests.
 /// </param>
 public CPU(MMU mmu, IRegisters reg)
 {
     Registers   = reg;
     clock       = new Clock();
     this.mmu    = mmu;
     ControlUnit = new ControlUnit(mmu, reg);
 }
예제 #4
0
        void IPipeline.DecodeAndExecute(
            byte instruction, IRegisters registers, IMemory memory)
        {
            mLog.Info(
                "Decoding and executing: {0:D8}",
                Convert.ToString(instruction, 2));

            switch (instruction)
            {
            case 0x00:
                NopInstr.ExecuteNop(registers);
                return;

            //case 0xAF:
            //    LoadInstr.Execute_Ld_r_r(instruction, registers);
            //    return;

            case 0xC3:
                JumpInstr.Execute_Jp_nn(registers, memory);
                return;

            default:
                mLog.Error("Instruction not implemented.");
                throw new NotImplementedException();
            }
        }
예제 #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="InterpreterHelper"/> class.
 /// </summary>
 /// <param name="operation">The operation.</param>
 /// <param name="registers">The registers.</param>
 /// <param name="mmu">The mmu.</param>
 /// <param name="alu">The alu.</param>
 /// <param name="peripheralManager">The peripheral manager.</param>
 public InterpreterHelper(IRegisters registers, IMmu mmu, IAlu alu, IPeripheralManager peripheralManager)
 {
     _registers         = registers;
     _mmu               = mmu;
     _alu               = alu;
     _peripheralManager = peripheralManager;
 }
예제 #6
0
        public ushort LoadRegistersFromMemory(IRegisters registers, ushort startAddress)
        {
            ushort address = startAddress;

            registers.AF    = GetSWordAtAddress(address);
            address        += 2;
            registers.BC    = GetSWordAtAddress(address);
            address        += 2;
            registers.DE    = GetSWordAtAddress(address);
            address        += 2;
            registers.HL    = GetSWordAtAddress(address);
            address        += 2;
            registers.IX    = GetSWordAtAddress(address);
            address        += 2;
            registers.IY    = GetSWordAtAddress(address);
            address        += 2;
            registers.SP    = GetSWordAtAddress(address);
            address        += 2;
            registers.PC    = GetWordAtAddress(address);
            address        += 2;
            registers.AltAF = GetSWordAtAddress(address);
            address        += 2;
            registers.AltBC = GetSWordAtAddress(address);
            address        += 2;
            registers.AltDE = GetSWordAtAddress(address);
            address        += 2;
            registers.AltHL = GetSWordAtAddress(address);
            return(address);
        }
예제 #7
0
        public ushort SaveRegistersToMemory(IRegisters registers, ushort startAddress)
        {
            ushort address = startAddress;

            SetSWordAtAddress(address, registers.AF);
            address += 2;
            SetSWordAtAddress(address, registers.BC);
            address += 2;
            SetSWordAtAddress(address, registers.DE);
            address += 2;
            SetSWordAtAddress(address, registers.HL);
            address += 2;
            SetSWordAtAddress(address, registers.IX);
            address += 2;
            SetSWordAtAddress(address, registers.IY);
            address += 2;
            SetSWordAtAddress(address, registers.SP);
            address += 2;
            SetWordAtAddress(address, registers.PC);
            address += 2;
            SetSWordAtAddress(address, registers.AltAF);
            address += 2;
            SetSWordAtAddress(address, registers.AltBC);
            address += 2;
            SetSWordAtAddress(address, registers.AltDE);
            address += 2;
            SetSWordAtAddress(address, registers.AltHL);
            return(address);
        }
예제 #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="CpuCoreBase" /> class.
        /// </summary>
        /// <param name="registers">The registers.</param>
        /// <param name="interruptManager">The interrupt manager.</param>
        /// <param name="peripheralManager">The peripheral manager.</param>
        /// <param name="mmu">The mmu.</param>
        /// <param name="instructionTimer">The instruction timer.</param>
        /// <param name="alu">The alu.</param>
        /// <param name="opCodeDecoder">The opcode decoder.</param>
        /// <param name="instructionBlockFactory">The instruction block decoder.</param>
        /// <param name="dmaController">The dma controller.</param>
        /// <param name="messageBus">The message bus.</param>
        /// <param name="requireInstructionBlockCaching">if set to <c>true</c> [require instruction block caching].</param>
        /// <exception cref="ArgumentException">Instruction block decoder must support caching</exception>
        protected CpuCoreBase(IRegisters registers,
                              IInterruptManager interruptManager,
                              IPeripheralManager peripheralManager,
                              IMmu mmu,
                              IInstructionTimer instructionTimer,
                              IAlu alu,
                              IOpCodeDecoder opCodeDecoder,
                              IInstructionBlockFactory instructionBlockFactory,
                              IDmaController dmaController,
                              IMessageBus messageBus,
                              bool requireInstructionBlockCaching)
        {
            CoreId             = Guid.NewGuid();
            _registers         = registers;
            _interruptManager  = interruptManager;
            _peripheralManager = peripheralManager;
            _mmu = mmu;
            _instructionTimer = instructionTimer;
            _alu                     = alu;
            _opCodeDecoder           = opCodeDecoder;
            _instructionBlockFactory = instructionBlockFactory;
            _dmaController           = dmaController;
            _messageBus              = messageBus;
            messageBus.RegisterHandler(Message.PauseCpu, Pause);
            messageBus.RegisterHandler(Message.ResumeCpu, Resume);

            if (requireInstructionBlockCaching && !_instructionBlockFactory.SupportsInstructionBlockCaching)
            {
                throw new ArgumentException("Instruction block decoder must support caching");
            }
        }
예제 #9
0
 public void SetUp()
 {
     mmu  = new MMU();
     regs = new Registers(mmu);
     cpu  = new CPU(mmu, regs);
     regs.SP--;
 }
예제 #10
0
 public Processor(IRegisters registers, IIntreruptQueue intreruptQueue, IMemory memory, IDiagnosticsService diagnosticsService)
 {
     _registers          = registers;
     _intreruptQueue     = intreruptQueue;
     _memory             = memory;
     _diagnosticsService = diagnosticsService;
 }
예제 #11
0
        private string GetFlags(IRegisters registers)
        {
            var flags = Convert.ToString(registers.F, 2).PadLeft(8, '0');

            flags = flags.Substring(0, 2) + "X" + flags.Substring(3, 1) + "X" + flags.Substring(5, 3);
            return(flags);
        }
예제 #12
0
 public Cpu(IRandomAccessMemory memory, IRegisters registers, IFlags flags,
            IEmulatorInstructionFactory instructionFactory)
 {
     Memory    = memory ?? throw new ArgumentNullException(nameof(memory));
     Registers = registers;
     this.instructionFactory = instructionFactory;
     Flags = flags;
 }
예제 #13
0
 public void TestBitByte(IRegisters registers, int bit, byte value)
 {
     if ((value & (1 << bit)) > 0)
     {
         registers.ZeroFlag = true;
     }
     registers.NegativeFlag  = false;
     registers.HalfCarryFlag = true;
 }
예제 #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="InterruptManager"/> class.
 /// </summary>
 /// <param name="registers">The registers.</param>
 /// <param name="instructionTimer">The instruction timer.</param>
 public InterruptManager(IRegisters registers, IInstructionTimer instructionTimer)
 {
     _registers           = registers;
     _instructionTimer    = instructionTimer;
     _haltTaskSource      = new TaskCompletionSource <bool>();
     _nextInterruptSource = new TaskCompletionSource <ushort>();
     _cancellationSource  = new CancellationTokenSource();
     Task.Factory.StartNew(InterruptTask, TaskCreationOptions.LongRunning);
 }
예제 #15
0
        public static void Execute_Ld_r_r(byte instruction, IRegisters registers)
        {
            mLog.Info("LD r,r'");

            byte destination = (byte)(instruction & 0x38);
            byte source      = (byte)(instruction & 0x07);

            throw new NotImplementedException();
        }
예제 #16
0
        static void PrintProcessorState(IMemory memory, IRegisters registers)
        {
            var registerPointingColors = new Dictionary <RegisterType, ConsoleColor>()
            {
                [RegisterType.Ip]  = ConsoleColor.Blue,
                [RegisterType.Pip] = ConsoleColor.DarkYellow
            };

            var regDict = new Dictionary <RegisterType, int>();

            ConsoleColor GetConsoleColor(RegisterType registerType)
            {
                if (registerPointingColors.ContainsKey(registerType))
                {
                    return(registerPointingColors[registerType]);
                }
                return(ConsoleColor.Black);
            }

            // print registers
            foreach (var regType in Enum.GetValues(typeof(RegisterType)))
            {
                var typedRegisterType = (RegisterType)regType;

                var regValue = registers.Read(typedRegisterType);

                regDict[typedRegisterType] = regValue;

                PrintInColor(GetConsoleColor(typedRegisterType), $"{typedRegisterType} = {regValue}\n");
            }

            Console.Write("\n");

            for (int i = 0; i < 256; i++)
            {
                if (i % 16 == 0)
                {
                    Console.Write($"\n|");
                }

                var regMatching = regDict.Where(x => x.Value == i && registerPointingColors.ContainsKey(x.Key)).ToList();

                var color = regMatching.Any() ? GetConsoleColor(regMatching.First().Key) : ConsoleColor.Black;

                Console.Write(" ");

                PrintInColor(color, $"{memory.Read(i): 000}");

                Console.Write(" |");
            }
            Console.WriteLine();



            // print memory
        }
예제 #17
0
 private void WriteTrace(IRegisters registers, object instruction, string flags)
 {
     Console.WriteLine("{0:X4} : {1} FLG: {2} A:{3:X2} BC:{4:X4} DE:{5:X4} HL:{6:X4} IX:{7:X4} IY:{8:X4}",
                       registers.PC,
                       instruction,
                       flags,
                       registers.A, registers.BC,
                       registers.DE, registers.HL,
                       registers.IX, registers.IY);
 }
예제 #18
0
파일: Cpu.cs 프로젝트: SergioLuis/dotBoy
 public Cpu(
     IClock clock,
     IMemory memory,
     IRegisters registers,
     IPipeline pipeline)
 {
     mClock     = clock;
     mMemory    = memory;
     mRegisters = registers;
     mPipeline  = pipeline;
 }
예제 #19
0
        public Mmu(IMemoryMap memoryMap, IRegisters registers)
        {
            this.MemoryMap = memoryMap;
            this.Registers = registers;

            // TODO: Initialize IO memory

            this.Stack = new Stack(this.MemoryMap, this.Registers.Sp);

            this.Reset();
        }
예제 #20
0
        public static void Execute_Jp_nn(IRegisters registers, IMemory memory)
        {
            mLog.Info("JP nn");

            registers.PC++;
            byte l = memory[registers.PC];

            registers.PC++;
            byte h = memory[registers.PC];

            registers.PC = BitConverter.ToUInt16(new byte[] { l, h }, 0);
        }
예제 #21
0
    public static void ToConsole(this IRegisters registers)
    {
        WriteRegister("PC", registers.ProgramCounter);
        WriteRegister("SP", registers.StackPointer);
        Console.WriteLine();

        for (byte index = 0; index < 8; index++)
        {
            WriteRegister($"R{index}", registers[index]);
        }

        Console.WriteLine();
    }
예제 #22
0
        private InstructionTimings Interpret(IRegisters registers, IMmu mmu, IAlu alu, IPeripheralManager peripherals, DecodedBlock block)
        {
            var helper = new InterpreterHelper(registers, mmu, alu, peripherals);
            var result = block.Operations.Select(o => Interpret(registers, mmu, alu, peripherals, helper, o, block)).Aggregate((t0, t1) => t0 + t1);

            if (_cpuMode == CpuMode.Z80)
            {
                // Add the block length to the 7 lsb of memory refresh register.
                registers.R = (byte)((registers.R + block.Length) & 0x7f);
            }

            return(result);
        }
예제 #23
0
파일: CpuCore.cs 프로젝트: jrp7/Alizarin
 /// <summary>
 /// Initializes a new instance of the <see cref="CpuCore" /> class.
 /// </summary>
 /// <param name="registers">The registers.</param>
 /// <param name="interruptManager">The interrupt manager.</param>
 /// <param name="peripheralManager">The peripheral manager.</param>
 /// <param name="mmu">The mmu.</param>
 /// <param name="instructionTimer">The instruction timer.</param>
 /// <param name="alu">The alu.</param>
 /// <param name="opCodeDecoder">The opcode decoder.</param>
 /// <param name="instructionBlockFactory">The instruction block decoder.</param>
 /// <param name="dmaController">The dma controller.</param>
 /// <param name="messageBus">The message bus.</param>
 public CpuCore(IRegisters registers,
                IInterruptManager interruptManager,
                IPeripheralManager peripheralManager,
                IMmu mmu,
                IInstructionTimer instructionTimer,
                IAlu alu,
                IOpCodeDecoder opCodeDecoder,
                IInstructionBlockFactory instructionBlockFactory,
                IDmaController dmaController,
                IMessageBus messageBus)
     : base(registers, interruptManager, peripheralManager, mmu, instructionTimer, alu, opCodeDecoder, instructionBlockFactory, dmaController, messageBus, false)
 {
 }
        public InterpreterEngine()
        {
            Registers     = new Registers();
            _instructions = new Dictionary <string, IExecutableInstruction>();

            _instructions.Add("LD", new LoadInstruction());
            _instructions.Add("ADD", new AddInstruction());
            _instructions.Add("MOV", new MovInstruction());
            _instructions.Add("SUB", new SubInstruction());
            _instructions.Add("BR", new BrInstruction());
            _instructions.Add("BRGZ", new BrGzInstruction());
            _instructions.Add("CLEAR", new ClearInstruction());
            _instructions.Add("SYSCALL", new SyscallInstruction());

            _ip = 0;
        }
 private void RefreshRegisters()
 {
     _registers = businessLogic.GetRegisters();
     afRegisterLabel.Content = $"0x{_registers.AF.ToString("X4")}";
     bcRegisterLabel.Content = $"0x{_registers.BC.ToString("X4")}";
     deRegisterLabel.Content = $"0x{_registers.DE.ToString("X4")}";
     hlRegisterLabel.Content = $"0x{_registers.HL.ToString("X4")}";
     spRegisterLabel.Content = $"0x{_registers.SP.ToString("X4")}";
     pcRegisterLabel.Content = $"0x{_registers.PC.ToString("X4")}";
     zFlagCheckbox.IsChecked = _registers.ZFlag == 1;
     nFlagCheckbox.IsChecked = _registers.NFlag == 1;
     hFlagCheckbox.IsChecked = _registers.HFlag == 1;
     cFlagCheckbox.IsChecked = _registers.CFlag == 1;
     imeCheckbox.IsChecked   = _registers.IME;
     cycleCountLabel.Content = _registers.CycleCount;
 }
예제 #26
0
        public void DecrementMemory(IRegisters registers, IMemory memory, ushort address)
        {
            int result        = memory.ReadByte(address);
            int originalValue = result;

            result -= 1;

            registers.NegativeFlag = false;
            if ((result & 0xFF) == 0)
            {
                registers.ZeroFlag = true;
            }
            if (!(((originalValue & 0x0F) - (1 & 0x0F)) < 0))
            {
                registers.HalfCarryFlag = true;
            }
            //ignore carry flag

            memory.WriteByte(address, (byte)result);
        }
예제 #27
0
        public Processor(IMemory memory, IRegisters registers, ITeleprinter teleprinter)
        {
            Memory      = memory ?? throw new ArgumentNullException(nameof(memory));
            Teleprinter = teleprinter ?? throw new ArgumentNullException(nameof(teleprinter));
            Registers   = registers ?? throw new ArgumentNullException(nameof(registers));

            Interrupts = new Interrupts(registers, memory, teleprinter);

            group1Instructions          = new Group1Instructions(this);
            group3Instructions          = new Group3Instructions(this);
            memoryReferenceInstructions = new MemoryReferenceInstructions(this);
            noOperationInstruction      = new NoOperationInstruction(this);

            group2ANDInstructions            = new Group2ANDInstructions(this);
            group2ORInstructions             = new Group2ORInstructions(this);
            memoryManagementInstructions     = new MemoryManagementInstructions(this);
            keyboardInstructions             = new KeyboardInstructions(this);
            teleprinterInstructions          = new TeleprinterInstructions(this);
            interruptInstructions            = new InterruptInstructions(this);
            privilegedNoOperationInstruction = new PrivilegedNoOperationInstruction(this);
        }
예제 #28
0
        static void PrintMemory(IMemory memory, IRegisters registers)
        {
            for (int i = 0; i < 256; i++)
            {
                if (registers.Read(RegisterType.Ip) == i)
                {
                    Console.BackgroundColor = ConsoleColor.Blue;
                }
                if (registers.Read(RegisterType.Pip) == i)
                {
                    Console.BackgroundColor = ConsoleColor.DarkBlue;
                }

                if (i % 16 == 0)
                {
                    Console.Write($"\n|");
                }

                Console.Write($" {memory.Read(i) : 000} |");

                Console.BackgroundColor = ConsoleColor.Black;
            }
            Console.WriteLine();
        }
예제 #29
0
 public Interrupts(IRegisters registers, IMemory memory, ITeleprinter teleprinter)
 {
     this.registers   = registers;
     this.memory      = memory;
     this.teleprinter = teleprinter;
 }
예제 #30
0
        private InstructionTimings Interpret(IRegisters registers, IMmu mmu, IAlu alu, IPeripheralManager peripherals, InterpreterHelper helper, Operation operation, DecodedBlock block)
        {
            helper.Operation = operation;
            var timer = new InstructionTimingsBuilder();

            switch (operation.OpCode)
            {
            case OpCode.NoOperation:
                break;

            case OpCode.Stop:
            case OpCode.Halt:
                SyncProgramCounter(registers, block);
                break;

            case OpCode.Load:
                if (operation.Operand1 == operation.Operand2)
                {
                    break;
                }

                helper.Operand1 = helper.Operand2;
                if (operation.Operand2 == Operand.I || operation.Operand2 == Operand.R)
                {
                    // LD A, R & LD A, I also reset H & N and copy IFF2 to P/V
                    registers.AccumulatorAndFlagsRegisters.Flags.SetResultFlags(registers.AccumulatorAndFlagsRegisters.A);
                    registers.AccumulatorAndFlagsRegisters.Flags.HalfCarry      = false;
                    registers.AccumulatorAndFlagsRegisters.Flags.Subtract       = false;
                    registers.AccumulatorAndFlagsRegisters.Flags.ParityOverflow = registers.InterruptFlipFlop2;
                }
                break;

            case OpCode.Load16:
                helper.WordOperand1 = helper.WordOperand2;
                break;

            case OpCode.Push:
                helper.PushStackPointer();
                mmu.WriteWord(registers.StackPointer, helper.WordOperand1);
                break;

            case OpCode.Pop:
                helper.WordOperand1 = mmu.ReadWord(registers.StackPointer);
                helper.PopStackPointer();
                break;

            case OpCode.Add:
                helper.Alu8BitOperation(alu.Add);
                break;

            case OpCode.AddWithCarry:
                helper.Alu8BitOperation(alu.AddWithCarry);
                break;

            case OpCode.Subtract:
                helper.Alu8BitOperation(alu.Subtract);
                break;

            case OpCode.SubtractWithCarry:
                helper.Alu8BitOperation(alu.SubtractWithCarry);
                break;

            case OpCode.And:
                helper.Alu8BitOperation(alu.And);
                break;

            case OpCode.Or:
                helper.Alu8BitOperation(alu.Or);
                break;

            case OpCode.Xor:
                helper.Alu8BitOperation(alu.Xor);
                break;

            case OpCode.Compare:
                alu.Compare(registers.AccumulatorAndFlagsRegisters.A, helper.Operand1);
                break;

            case OpCode.Increment:
                helper.Operand1 = alu.Increment(helper.Operand1);
                break;

            case OpCode.Decrement:
                helper.Operand1 = alu.Decrement(helper.Operand1);
                break;

            case OpCode.Add16:
                helper.Alu16BitOperation(alu.Add);
                break;

            case OpCode.AddWithCarry16:
                helper.Alu16BitOperation(alu.AddWithCarry);
                break;

            case OpCode.SubtractWithCarry16:
                helper.Alu16BitOperation(alu.SubtractWithCarry);
                break;

            case OpCode.Increment16:
                // INC ss (no flags changes so implemented directly)
                helper.WordOperand1 = (ushort)(helper.WordOperand1 + 1);
                break;

            case OpCode.Decrement16:
                // DEC ss (no flags changes so implemented directly)
                helper.WordOperand1 = (ushort)(helper.WordOperand1 - 1);
                break;

            case OpCode.Exchange:
            {
                var w = helper.WordOperand2;
                helper.WordOperand2 = helper.WordOperand1;
                helper.WordOperand1 = w;
            }
            break;

            case OpCode.ExchangeAccumulatorAndFlags:
                registers.SwitchToAlternativeAccumulatorAndFlagsRegisters();
                break;

            case OpCode.ExchangeGeneralPurpose:
                registers.SwitchToAlternativeGeneralPurposeRegisters();
                break;

            case OpCode.Jump:
                if (operation.FlagTest == FlagTest.None || helper.DoFlagTest())
                {
                    registers.ProgramCounter = helper.WordOperand1;
                }
                else
                {
                    SyncProgramCounter(registers, block);
                }
                break;

            case OpCode.JumpRelative:
                if (operation.FlagTest == FlagTest.None || helper.DoFlagTest())
                {
                    helper.JumpToDisplacement();

                    if (operation.FlagTest != FlagTest.None)
                    {
                        timer.Add(1, 5);
                    }
                }
                SyncProgramCounter(registers, block);
                break;

            case OpCode.DecrementJumpRelativeIfNonZero:
                registers.GeneralPurposeRegisters.B--;
                if (registers.GeneralPurposeRegisters.B != 0)
                {
                    helper.JumpToDisplacement();
                    timer.Add(1, 5);
                }
                SyncProgramCounter(registers, block);
                break;

            case OpCode.Call:
                SyncProgramCounter(registers, block);

                if (operation.FlagTest == FlagTest.None || helper.DoFlagTest())
                {
                    helper.PushStackPointer();
                    mmu.WriteWord(registers.StackPointer, registers.ProgramCounter);
                    registers.ProgramCounter = helper.WordOperand1;

                    if (operation.FlagTest != FlagTest.None)
                    {
                        timer.Add(2, 7);
                    }
                }
                break;

            case OpCode.Return:
                if (operation.FlagTest == FlagTest.None || helper.DoFlagTest())
                {
                    registers.ProgramCounter = mmu.ReadWord(registers.StackPointer);
                    helper.PopStackPointer();

                    if (operation.FlagTest != FlagTest.None)
                    {
                        timer.Add(2, 6);
                    }
                }
                else
                {
                    SyncProgramCounter(registers, block);
                }
                break;

            case OpCode.ReturnFromInterrupt:
                registers.ProgramCounter = mmu.ReadWord(registers.StackPointer);
                helper.PopStackPointer();
                registers.InterruptFlipFlop1 = true;
                break;

            case OpCode.ReturnFromNonmaskableInterrupt:
                registers.ProgramCounter = mmu.ReadWord(registers.StackPointer);
                helper.PopStackPointer();
                registers.InterruptFlipFlop1 = registers.InterruptFlipFlop2;
                break;

            case OpCode.Reset:
                SyncProgramCounter(registers, block);
                helper.PushStackPointer();
                mmu.WriteWord(registers.StackPointer, registers.ProgramCounter);
                registers.ProgramCounter = helper.WordOperand1;
                break;

            case OpCode.Input:
                helper.Operand1 = peripherals.ReadByteFromPort(helper.Operand2,
                                                               operation.Operand2 == Operand.n
                                                                       ? registers.AccumulatorAndFlagsRegisters.A
                                                                       : registers.GeneralPurposeRegisters.B);
                break;

            case OpCode.Output:
                peripherals.WriteByteToPort(helper.Operand2,
                                            operation.Operand2 == Operand.n
                                                    ? registers.AccumulatorAndFlagsRegisters.A
                                                    : registers.GeneralPurposeRegisters.B,
                                            helper.Operand1);
                break;

            case OpCode.RotateLeftWithCarry:
                helper.Operand1 = alu.RotateLeftWithCarry(helper.Operand1);
                if (operation.OpCodeMeta == OpCodeMeta.UseAlternativeFlagAffection)
                {
                    registers.AccumulatorAndFlagsRegisters.Flags.Zero = false;
                    registers.AccumulatorAndFlagsRegisters.Flags.Sign = false;
                }
                break;

            case OpCode.RotateLeft:
                helper.Operand1 = alu.RotateLeft(helper.Operand1);
                if (operation.OpCodeMeta == OpCodeMeta.UseAlternativeFlagAffection)
                {
                    registers.AccumulatorAndFlagsRegisters.Flags.Zero = false;
                    registers.AccumulatorAndFlagsRegisters.Flags.Sign = false;
                }
                break;

            case OpCode.RotateRightWithCarry:
                helper.Operand1 = alu.RotateRightWithCarry(helper.Operand1);
                if (operation.OpCodeMeta == OpCodeMeta.UseAlternativeFlagAffection)
                {
                    registers.AccumulatorAndFlagsRegisters.Flags.Zero = false;
                    registers.AccumulatorAndFlagsRegisters.Flags.Sign = false;
                }
                break;

            case OpCode.RotateRight:
                helper.Operand1 = alu.RotateRight(helper.Operand1);
                if (operation.OpCodeMeta == OpCodeMeta.UseAlternativeFlagAffection)
                {
                    registers.AccumulatorAndFlagsRegisters.Flags.Zero = false;
                    registers.AccumulatorAndFlagsRegisters.Flags.Sign = false;
                }
                break;

            case OpCode.RotateLeftDigit:
            {
                var result = alu.RotateLeftDigit(registers.AccumulatorAndFlagsRegisters.A,
                                                 mmu.ReadByte(registers.GeneralPurposeRegisters.HL));
                registers.AccumulatorAndFlagsRegisters.A = result.Accumulator;
                mmu.WriteByte(registers.GeneralPurposeRegisters.HL, result.Result);
            }
            break;

            case OpCode.RotateRightDigit:
            {
                var result = alu.RotateRightDigit(registers.AccumulatorAndFlagsRegisters.A,
                                                  mmu.ReadByte(registers.GeneralPurposeRegisters.HL));
                registers.AccumulatorAndFlagsRegisters.A = result.Accumulator;
                mmu.WriteByte(registers.GeneralPurposeRegisters.HL, result.Result);
            }
            break;

            case OpCode.ShiftLeft:
                helper.Operand1 = alu.ShiftLeft(helper.Operand1);
                break;

            case OpCode.ShiftLeftSet:
                helper.Operand1 = alu.ShiftLeftSet(helper.Operand1);
                break;

            case OpCode.ShiftRight:
                helper.Operand1 = alu.ShiftRight(helper.Operand1);
                break;

            case OpCode.ShiftRightLogical:
                helper.Operand1 = alu.ShiftRightLogical(helper.Operand1);
                break;

            case OpCode.BitTest:
                alu.BitTest(helper.Operand1, operation.ByteLiteral);
                break;

            case OpCode.BitSet:
                helper.Operand1 = alu.BitSet(helper.Operand1, operation.ByteLiteral);
                break;

            case OpCode.BitReset:
                helper.Operand1 = alu.BitReset(helper.Operand1, operation.ByteLiteral);
                break;

            case OpCode.TransferIncrement:
                helper.BlockTransfer();
                break;

            case OpCode.TransferIncrementRepeat:
                helper.BlockTransferRepeat(timer);
                break;

            case OpCode.TransferDecrement:
                helper.BlockTransfer(true);
                break;

            case OpCode.TransferDecrementRepeat:
                helper.BlockTransferRepeat(timer, true);
                break;

            case OpCode.SearchIncrement:
                helper.BlockSearch();
                break;

            case OpCode.SearchIncrementRepeat:
                helper.BlockSearchRepeat(timer);
                break;

            case OpCode.SearchDecrement:
                helper.BlockSearch(true);
                break;

            case OpCode.SearchDecrementRepeat:
                helper.BlockSearchRepeat(timer, true);
                break;

            case OpCode.InputTransferIncrement:
                helper.InputTransfer();
                break;

            case OpCode.InputTransferIncrementRepeat:
                helper.InputTransferRepeat(timer);
                break;

            case OpCode.InputTransferDecrement:
                helper.InputTransfer(true);
                break;

            case OpCode.InputTransferDecrementRepeat:
                helper.InputTransferRepeat(timer, true);
                break;

            case OpCode.OutputTransferIncrement:
                helper.OutputTransfer();
                break;

            case OpCode.OutputTransferIncrementRepeat:
                helper.OutputTransferRepeat(timer);
                break;

            case OpCode.OutputTransferDecrement:
                helper.OutputTransfer(true);
                break;

            case OpCode.OutputTransferDecrementRepeat:
                helper.OutputTransferRepeat(timer, true);
                break;

            case OpCode.DecimalArithmeticAdjust:
                registers.AccumulatorAndFlagsRegisters.A = alu.DecimalAdjust(registers.AccumulatorAndFlagsRegisters.A,
                                                                             _cpuMode == CpuMode.Z80);
                break;

            case OpCode.NegateOnesComplement:
                registers.AccumulatorAndFlagsRegisters.A = (byte)~registers.AccumulatorAndFlagsRegisters.A;
                registers.AccumulatorAndFlagsRegisters.Flags.SetUndocumentedFlags(registers.AccumulatorAndFlagsRegisters.A);
                registers.AccumulatorAndFlagsRegisters.Flags.HalfCarry = true;
                registers.AccumulatorAndFlagsRegisters.Flags.Subtract  = true;
                break;

            case OpCode.NegateTwosComplement:
                registers.AccumulatorAndFlagsRegisters.A = alu.Subtract(0, registers.AccumulatorAndFlagsRegisters.A);
                break;

            case OpCode.InvertCarryFlag:
                registers.AccumulatorAndFlagsRegisters.Flags.SetUndocumentedFlags(registers.AccumulatorAndFlagsRegisters.A);
                registers.AccumulatorAndFlagsRegisters.Flags.HalfCarry = _cpuMode != CpuMode.GameBoy &&
                                                                         registers.AccumulatorAndFlagsRegisters.Flags.Carry;
                registers.AccumulatorAndFlagsRegisters.Flags.Subtract = false;
                registers.AccumulatorAndFlagsRegisters.Flags.Carry    = !registers.AccumulatorAndFlagsRegisters.Flags.Carry;
                break;

            case OpCode.SetCarryFlag:
                registers.AccumulatorAndFlagsRegisters.Flags.SetUndocumentedFlags(registers.AccumulatorAndFlagsRegisters.A);
                registers.AccumulatorAndFlagsRegisters.Flags.HalfCarry = false;
                registers.AccumulatorAndFlagsRegisters.Flags.Subtract  = false;
                registers.AccumulatorAndFlagsRegisters.Flags.Carry     = true;
                break;

            case OpCode.DisableInterrupts:
                registers.InterruptFlipFlop1 = false;
                registers.InterruptFlipFlop2 = false;
                break;

            case OpCode.EnableInterrupts:
                registers.InterruptFlipFlop1 = true;
                registers.InterruptFlipFlop2 = true;
                break;

            case OpCode.InterruptMode0:
                registers.InterruptMode = InterruptMode.InterruptMode0;
                break;

            case OpCode.InterruptMode1:
                registers.InterruptMode = InterruptMode.InterruptMode1;
                break;

            case OpCode.InterruptMode2:
                registers.InterruptMode = InterruptMode.InterruptMode2;
                break;

            case OpCode.Swap:
                helper.Operand1 = alu.Swap(helper.Operand1);
                break;

            case OpCode.LoadIncrement:
                helper.Operand1 = helper.Operand2;
                registers.GeneralPurposeRegisters.HL++;
                break;

            case OpCode.LoadDecrement:
                helper.Operand1 = helper.Operand2;
                registers.GeneralPurposeRegisters.HL--;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            if (operation.OpCodeMeta == OpCodeMeta.AutoCopy)
            {
                // Autocopy for DD/FD prefix
                helper.Operand2 = helper.Operand1;
            }

            return(timer.GetInstructionTimings());
        }
예제 #31
0
 private static void SyncProgramCounter(IRegisters registers, DecodedBlock block) => registers.ProgramCounter = (ushort)(registers.ProgramCounter + block.Length);
예제 #32
0
 public DestinationProvider(IRegisters registers, IRam ram)
 {
     this.registers = registers;
     this.ram = ram;
 }
예제 #33
0
 public SourceProvider(IRegisters registers, IRam ram)
 {
     this.registers = registers;
     this.ram = ram;
 }