Esempio n. 1
0
        /// <summary>
        /// Read OpCode Parameter value. 
        /// 
        /// BBBBBB AAAAAA 0000
        /// 
        /// Will decode either A or B (based on what is given in _opParam) and
        /// populate data into a readParamValue struct. 
        /// 
        /// The PC register is automatically incremented based on what needs to be read.
        /// </summary>
        /// <param name="_opParam"></param>
        /// <returns></returns>
        private readParamValue ReadParamValue(ushort _opParam)
        {
            readParamValue result = new readParamValue();            

            switch (_opParam)
            {
                // read Value in register
                case (ushort)dcpuRegisterCodes.A:
                case (ushort)dcpuRegisterCodes.B:
                case (ushort)dcpuRegisterCodes.C:
                case (ushort)dcpuRegisterCodes.X:
                case (ushort)dcpuRegisterCodes.Y:
                case (ushort)dcpuRegisterCodes.Z:
                case (ushort)dcpuRegisterCodes.I:
                case (ushort)dcpuRegisterCodes.J:
                    result.ParmType = ParamType.Register;
                    result.Location = _opParam;
                    result.Value = m_registers.GP[result.Location];
                    break;

                // read value at memory location where register is pointing too
                case (ushort)dcpuRegisterCodes.A_Mem:
                case (ushort)dcpuRegisterCodes.B_Mem:
                case (ushort)dcpuRegisterCodes.C_Mem:
                case (ushort)dcpuRegisterCodes.X_Mem:
                case (ushort)dcpuRegisterCodes.Y_Mem:
                case (ushort)dcpuRegisterCodes.Z_Mem:
                case (ushort)dcpuRegisterCodes.I_Mem:
                case (ushort)dcpuRegisterCodes.J_Mem:
                    result.ParmType = ParamType.Memory;
                    result.Location = m_registers.GP[_opParam - (ushort)dcpuRegisterCodes.A_Mem];
                    result.Value = m_memory.RAM[result.Location];
                    m_cycles++;
                    break;

                case (ushort)dcpuRegisterCodes.A_NextWord:
                case (ushort)dcpuRegisterCodes.B_NextWord:
                case (ushort)dcpuRegisterCodes.C_NextWord:
                case (ushort)dcpuRegisterCodes.X_NextWord:
                case (ushort)dcpuRegisterCodes.Y_NextWord:
                case (ushort)dcpuRegisterCodes.Z_NextWord:
                case (ushort)dcpuRegisterCodes.I_NextWord:
                case (ushort)dcpuRegisterCodes.J_NextWord:
                    result.ParmType = ParamType.Memory;
                    result.Location = (ushort)(m_registers.GP[_opParam - (ushort)dcpuRegisterCodes.A_NextWord] + ReadNextWord());
                    result.Value = m_memory.RAM[result.Location];
                    m_cycles += 2; // we read 2 words so this must cost 2 cycles. 
                    break;

                case (ushort)dcpuRegisterCodes.POP:
                    if (m_ignoreNextInstruction != true)
                    {
                        result.ParmType = ParamType.Memory;
                        result.Location = m_registers.SP++;
                        result.Value = m_memory.RAM[result.Location];
                    }
                    m_cycles++;
                    break;

                case (ushort)dcpuRegisterCodes.PEEK:
                    result.ParmType = ParamType.Memory;
                    result.Location = m_registers.SP;
                    result.Value = m_memory.RAM[result.Location];
                    m_cycles++; 
                    break;

                case (ushort)dcpuRegisterCodes.PUSH:
                    if (m_ignoreNextInstruction != true)
                    {
                        result.ParmType = ParamType.Memory;
                        result.Location = --m_registers.SP;
                        result.Value = m_memory.RAM[result.Location];
                    }
                    m_cycles++;
                    break;

                case (ushort)dcpuRegisterCodes.O:
                    result.ParmType = ParamType.Register;
                    result.Location = _opParam;
                    result.Value = m_registers.O;
                    break;

                case (ushort)dcpuRegisterCodes.PC:
                    result.ParmType = ParamType.Register;
                    result.Location = _opParam;
                    result.Value = m_registers.PC;
                    break;

                case (ushort)dcpuRegisterCodes.SP:
                    result.ParmType = ParamType.Register;
                    result.Location = _opParam;
                    result.Value = m_registers.SP;
                    break;

                case (ushort)dcpuRegisterCodes.NextWord_Literal_Mem:
                    result.ParmType = ParamType.Memory;
                    result.Location = ReadNextWord();
                    result.Value = m_memory.RAM[result.Location];     
                    m_cycles += 2; // we read 2 words so this must cost 2 cycles. 
                    break;

                /*
                 * DensitY here once again :)
                 * 
                 * We're going todo something special with the result
                 * basically someone might do something like this
                 * SET 0x8000, I
                 * when they mean
                 * SET [0x8000], I
                 * So in case we do that, we'll handle it. 
                 * 
                 * SAYING THAT!
                 * SET I, 0x8000
                 * and 
                 * SET I, [0x8000]
                 * Will work properly! (first putting 0x8000 into the register I, second reading data from the memory location 0x8000 into register I)
                 * 
                 * ----------------------------------------------------------------------------------
                 * UPDATE: DensitY 11th April 2012
                 * From Notch's Bible
                 * "If any instruction tries to assign a literal value, the assignment fails silently. Other than that, the instruction behaves as normal."
                 *  Basically what I decided on doing above was against Notch's spec, so I'm taking it out.
                 *  ---------------------------------------------------------------------------------
                 */
                case (ushort)dcpuRegisterCodes.NextWord_Literal_Value:
                    result.ParmType = ParamType.Literal;
                    result.Location = ReadNextWord();
                    result.Value = result.Location;
                    m_cycles++;
                    break;

                default:
                    break;
            }
            // Special Case for literal Values that are stored in the byte's param and not next word. used for values < 0x1F. 
            if (_opParam >= 0x20 && _opParam <= 0x3F)
            {
                result.ParmType = ParamType.Literal; 
                result.Location = (ushort)(_opParam - 0x20);
                result.Value = result.Location;
                // cycle free!
            }

            return result;
        }
Esempio n. 2
0
        /// <summary>
        /// Stores Read param values back into RAM or Registers.
        /// This is normally called after resolving a OpCode instruction in
        /// ExecuteInstruction().
        /// </summary>
        /// <param name="_resultValue">read param value</param>
        private void SetResultValue(readParamValue _resultValue)
        {
            if (_resultValue.ParmType == ParamType.Memory)
            {
                // write to memory location
                m_memory.RAM[_resultValue.Location] = _resultValue.Value;

                /**
                 * Notch's spec doesn't say anything (that I can find) regarding cost of write backs. So I'm assuming
                 * they are the same as reads. Meaning registers are free, Memory/word writebacks cost 1 cycle
                 */
                m_cycles++; 
            }
            else if (_resultValue.ParmType == ParamType.Register)
            {
                // Write to respective register
                switch (_resultValue.Location)
                {
                    case (ushort)dcpuRegisterCodes.A:
                    case (ushort)dcpuRegisterCodes.B:
                    case (ushort)dcpuRegisterCodes.C:
                    case (ushort)dcpuRegisterCodes.X:
                    case (ushort)dcpuRegisterCodes.Y:
                    case (ushort)dcpuRegisterCodes.Z:
                    case (ushort)dcpuRegisterCodes.I:
                    case (ushort)dcpuRegisterCodes.J:
                        m_registers.GP[_resultValue.Location] = _resultValue.Value;
                        break;

                    case (ushort)dcpuRegisterCodes.PC:  // program Counter
                        m_registers.PC = _resultValue.Value;
                        break;

                    case (ushort)dcpuRegisterCodes.SP:  // stack pointer
                        m_registers.SP = _resultValue.Value;
                        break;

                    case (ushort)dcpuRegisterCodes.O:   // overflow reigster
                        m_registers.O = _resultValue.Value;
                        break;

                    default:                     
                        break;
                }
            }
            // ignore literal assignment as per Notch's spec                
        }