Example #1
0
        private Instruction InterruptHandler(Interrupts interrupt)
        {
            // Handle interrupt with a CALL instruction to the interrupt handler
            Instruction instruction = new Instruction();

            instruction.OpCode = 0xCD; // CALL!
            byte lowOpcode = (byte)instruction.OpCode;

            instruction.Length      = CPUInstructionLengths.Get(lowOpcode);
            instruction.Literal     = this.interruptHandlers[(Interrupts)interrupt];
            instruction.Ticks       = CPUInstructionPreClocks.Get(lowOpcode);
            instruction.Name        = CPUInstructionNames.Get(lowOpcode);
            instruction.Description = CPUInstructionDescriptions.Get(lowOpcode);

            // Disable interrupts during interrupt handling and clear the current one
            this._interruptController.InterruptMasterEnable = false;
            byte IF = this._memory.LowLevelRead((ushort)MMR.IF);

            IF &= (byte)~(byte)interrupt;
            this._memory.LowLevelWrite((ushort)MMR.IF, IF);
            return(instruction);
        }
Example #2
0
        public void Dissasemble(ushort currentAddress)
        {
            _addressToInstruction   = new Dictionary <ushort, InstructionViewModel>();
            _addressWithBreakpoints = new Dictionary <ushort, InstructionViewModel>();

            _disassembler.PoorManDisassemble(currentAddress);
            _instructions.Clear();
            byte[][] matrix    = _disassembler.DisassembledMatrix;
            int      instCount = 0xFFFF;

            for (int address = 0; address < instCount; ++address)
            {
                byte[] entry     = matrix[address];
                int    intLength = entry[0];
                bool   CB        = false;


                if (intLength == 0)
                {
                    searchStrings[address] = "";
                    continue;
                }

                string searchString = "";
                var    vm           = new InstructionViewModel(_cpu);
                // We check the length
                if (intLength == 1)
                {
                    vm.Address        = "0x" + address.ToString("x2");
                    vm.originalOpcode = entry[1];
                    vm.Opcode         = "0x" + entry[1].ToString("x2");
                    vm.Name           = CPUInstructionNames.Get(entry[1]);
                    vm.Description    = CPUInstructionDescriptions.Get(entry[1]);
                }
                else if (intLength == 2)
                {
                    if (entry[1] != 0xCB)
                    {
                        vm.Address        = "0x" + address.ToString("x2");
                        vm.originalOpcode = entry[1];
                        vm.Opcode         = "0x" + entry[1].ToString("x2");
                        vm.Name           = CPUInstructionNames.Get(entry[1]);
                        vm.Literal        = "0x" + entry[2].ToString("x2");
                        vm.Description    = CPUInstructionDescriptions.Get(entry[1]);
                    }
                    else
                    {
                        CB         = true;
                        vm.Address = "0x" + address.ToString("x2");
                        int instOpcode = ((entry[1] << 8) | entry[2]);
                        vm.originalOpcode = (ushort)instOpcode;
                        vm.Opcode         = "0x" + instOpcode.ToString("x2");
                        vm.Name           = CPUCBInstructionNames.Get(entry[2]);
                        vm.Literal        = "0x" + entry[2].ToString("x2");
                        vm.Description    = CPUCBInstructionDescriptions.Get(entry[2]);
                    }
                }
                else
                {
                    vm.Address        = "0x" + address.ToString("x2");
                    vm.originalOpcode = entry[1];
                    vm.Opcode         = "0x" + entry[1].ToString("x2");
                    vm.Name           = CPUInstructionNames.Get(entry[1]);
                    int literal = ((entry[2] << 8) | entry[3]);
                    vm.Literal     = "0x" + literal.ToString("x2");
                    vm.Description = CPUInstructionDescriptions.Get(entry[1]);
                }
                vm.originalAddress = (ushort)address;

                if (!CB)
                {
                    vm.Ticks = CPUSpace.Dictionaries.CPUInstructionClocks.Get((byte)vm.originalOpcode);
                }
                else
                {
                    vm.Ticks = CPUSpace.Dictionaries.CPUCBInstructionClocks.Get((byte)vm.originalOpcode);
                }

                _instructions.Add(vm);
                _addressToInstruction[(ushort)address] = vm;
                vm.BreakpointChanged += Vm_BreakpointChanged;

                searchString += vm.Address + "_";
                searchString += vm.Opcode + "_";
                searchString += vm.Name + "_";
                searchString += vm.Literal;

                searchStrings[address] = searchString;

                if (address == currentAddress)
                {
                    SelectedInstruction = vm;
                    SetCurrentInstruction(vm);
                }
            }

            // We update the breakpoints
            List <ushort> execBreakpoints = _cpu.GetBreakpoints(BreakpointKinds.EXECUTION);

            foreach (ushort breakpointAddress in execBreakpoints)
            {
                if (!_addressToInstruction.ContainsKey(breakpointAddress))
                {
                    continue;
                }

                InstructionViewModel inst = _addressToInstruction[breakpointAddress];
                _addressWithBreakpoints[breakpointAddress] = inst;
                inst.HasBreakpoint = true;
            }
        }
Example #3
0
        /// <summary>
        /// Fetches and Decodes an instruction
        /// </summary>
        /// <param name="instruction">
        /// As FetchAndDecode gets called *several* times a frame (and many times during
        /// disassembly), it is better to have a pre-allocated instruction and to replace
        /// the values, instead of getting the overhead of allocating a new Instrucion
        /// everytime.
        /// </param>
        /// <param name="instructionAddress"></param>
        /// <param name="haltLoad"></param>
        /// <returns></returns>
        internal Instruction FetchAndDecode(ref Instruction instruction,
                                            ushort instructionAddress, bool haltLoad = false)
        {
            instruction.Address = instructionAddress;
            byte opcode = this._memory.LowLevelRead(instructionAddress);

            instruction.OpCode = opcode;

            if (instruction.OpCode != 0xCB)
            {
                instruction.CB = false;
                byte lowOpcode = (byte)instruction.OpCode;
                if (_instructionHistogram[lowOpcode] < ushort.MaxValue)
                {
                    _instructionHistogram[lowOpcode]++;
                }
                // Normal instructions
                instruction.Length = CPUInstructionLengths.Get(lowOpcode);

                // Extract literal
                if (instruction.Length == 2)
                {
                    // 8 bit literal
                    instruction.Operands[0] = this._memory.LowLevelRead((ushort)(instructionAddress + 1));
                    if (haltLoad)
                    {
                        instruction.Operands[0] = opcode;
                    }
                    instruction.Literal = (byte)instruction.Operands[0];
                }
                else if (instruction.Length == 3)
                {
                    // 16 bit literal, little endian
                    instruction.Operands[0] = this._memory.LowLevelRead((ushort)(instructionAddress + 2));
                    instruction.Operands[1] = this._memory.LowLevelRead((ushort)(instructionAddress + 1));

                    if (haltLoad)
                    {
                        instruction.Operands[1] = instruction.Operands[0];
                        instruction.Operands[0] = opcode;
                    }

                    instruction.Literal  = (byte)instruction.Operands[1];
                    instruction.Literal += (ushort)(instruction.Operands[0] << 8);
                }

                instruction.Ticks       = CPUInstructionPreClocks.Get(lowOpcode);
                instruction.Name        = CPUInstructionNames.Get(lowOpcode);
                instruction.Description = CPUInstructionDescriptions.Get(lowOpcode);
            }
            else
            {
                instruction.CB = true;
                // CB instructions block
                instruction.OpCode <<= 8;
                if (!haltLoad)
                {
                    instruction.OpCode += this._memory.LowLevelRead((ushort)(instructionAddress + 1));
                }
                else
                {
                    instruction.OpCode += 0xCB; // The first byte is duplicated
                }

                byte lowOpcode = (byte)instruction.OpCode;

                if (_cbInstructionHistogram[lowOpcode] < ushort.MaxValue)
                {
                    _cbInstructionHistogram[lowOpcode]++;
                }
                instruction.Length = CPUCBInstructionLengths.Get(lowOpcode);
                // There is no literal in CB instructions!

                //instruction.Lambda = this.CBInstructionLambdas[lowOpcode];
                instruction.Ticks       = CPUCBInstructionPreClocks.Get(lowOpcode);
                instruction.Name        = CPUCBInstructionNames.Get(lowOpcode);
                instruction.Description = CPUCBInstructionDescriptions.Get(lowOpcode);
            }

            // NOTE(Cristian): On haltLoad (HALT with IME disabled), the next byte after the HALT opcode
            //                 is "duplicated". This is a hardware bug.
            if (haltLoad)
            {
                instruction.Length--;
            }

            return(instruction);
        }