Beispiel #1
0
        public void emulateCycle()
        {
            if (m_Interrupt != InterruptSignal.None)
            {
                m_State = CPUState.interrupt;
            }

            switch (m_State)
            {
            case CPUState.fetchopcode:
                m_PC_Start         = m_PC;
                m_Cycle            = 1;
                m_ExtraCycles      = false;
                m_byteDisplacement = 0;

                m_OpCodePrefix = 0;
                m_OpCodeIndex  = getNextMemByte();
                m_oc           = m_OpCodes[m_OpCodeIndex];

                int iIndexOffset = 0;

                if (m_OpCodeIndex == 0xCB ||       // evaluate prefix
                    m_OpCodeIndex == 0xDD ||
                    m_OpCodeIndex == 0xED ||
                    m_OpCodeIndex == 0xFD)
                {
                    m_OpCodePrefix = m_OpCodeIndex;
                    iIndexOffset   = m_dictOpCodePrefix[m_OpCodePrefix];
                    m_OpCodeIndex  = getNextMemByte();

                    if (m_OpCodeIndex == 0xCB)    // DD CB or FD CB combination
                    {
                        m_OpCodePrefix   <<= 8;
                        m_OpCodePrefix    |= m_OpCodeIndex;
                        iIndexOffset       = m_dictOpCodePrefix[m_OpCodePrefix];
                        m_byteDisplacement = getNextMemByte();     // contains displacement before OpCode
                        m_OpCodeIndex      = getNextMemByte();
                    }

                    m_oc = m_OpCodes[iIndexOffset + m_OpCodeIndex];
                }

                // check if OpCode is defined
                if (String.IsNullOrEmpty(m_oc.OpCode) || m_oc.executeOperation == null)
                {
                    string sMessage;
                    if (m_OpCodePrefix > 0)
                    {
                        sMessage = String.Format("PC {0:X4} : OpCode {1:X2} {2:X2} unknown!!!",
                                                 m_PC_Start, (byte)m_OpCodePrefix, (byte)m_OpCodeIndex);
                    }
                    else
                    {
                        sMessage = String.Format("PC {0:X4} : OpCode {1:X2} unknown!!!",
                                                 m_PC_Start, (byte)m_OpCodeIndex);
                    }
                    throw new NotImplementedException(sMessage);
                }

#if CPU_TRACE
                m_ei.Counter++;
                m_ei.PC    = m_PC_Start;
                m_ei.Bytes = "";
                if (m_OpCodePrefix != 0)
                {
                    m_ei.Bytes += String.Format("{0:X2} ", m_OpCodePrefix);
                }
                m_ei.Bytes += String.Format("{0:X2} ", m_OpCodeIndex);
                m_ei.OpCode = m_oc.OpCode;
                m_ei.Op1    = "";
                m_ei.Op2    = "";
#endif
                // increase R register (only bits 6-0)
                m_reg_R = (byte)((m_reg_R & 0x80) | ((m_reg_R + 1) & 0x7F));

                // set for next processing state
                m_wordValue = 0;
                m_byteValue = 0;
#if NO_CYCLE_FILLUP
                m_MaxCycles = m_PC - m_PC_Start;
#else
                m_MaxCycles = m_oc.Cycles;
#endif
                m_State = CPUState.addressing;
                break;

            case CPUState.interrupt:     // interrupt
                switch (m_Interrupt)
                {
                case InterruptSignal.NMI:
                    // perform a RST 66h
                    m_reg_SP -= 2;;
                    writeMemWord(m_reg_SP, m_PC);
                    m_PC        = 0x0066;
                    m_State     = CPUState.fetchopcode;
                    m_Interrupt = InterruptSignal.None;
                    break;

                case InterruptSignal.IRQ:
                    switch (m_IM)
                    {
                    case 0:
                        // TODO Z80 implement IM 0
                        throw new NotImplementedException("Z80 IM 0 not implemented!");

                    case 1:             // IM 1 - perform a RST 38h
                        m_reg_SP -= 2;;
                        writeMemWord(m_reg_SP, m_PC);
                        m_PC        = 0x0038;
                        m_State     = CPUState.fetchopcode;
                        m_Interrupt = InterruptSignal.None;
                        break;

                    case 2:             // IM 2 - jump to interrupt vector
                        m_reg_SP -= 2;;
                        writeMemWord(m_reg_SP, m_PC);
                        m_PC        = m_reg_I;
                        m_State     = CPUState.fetchopcode;
                        m_Interrupt = InterruptSignal.None;
                        break;
                    }
                    break;
                }
                break;

            case CPUState.addressing:     // addressing
                m_Cycle++;
                m_oc.executeAddressing();

                break;

            case CPUState.operation:
                if (m_Cycle >= m_MaxCycles)     // emulate cycle exactness by making operation effective on last cycle
                {
                    m_oc.executeOperation();
                    if (m_Cycle < m_MaxCycles)
                    {
                        m_Cycle++;     // operation executed induced another cycle (e.g. branch operations)
                    }
                    else
                    {
                        m_State = CPUState.fetchopcode;      // operation finished -> get next opcode
                    }
#if CPU_TRACE
                    //if (m_PC_Start == 0x188) { m_TraceActive = true; m_ei.Counter = 1; }
                    //if (m_PC_Start == 0x18B) m_TraceActive = false;

                    if (m_State == CPUState.fetchopcode && m_TraceActive)
                    {
                        StringBuilder sb = new StringBuilder();

                        if ((m_ei.Counter % 20) == 1)
                        {
                            sb.Clear();
                            sb.Append("PC-- ");
                            sb.Append("----------- OpCo Op1,Op2---|");
                            sb.Append("A  F  B  C  D  E  H  L  ");
                            //sb.Append("A' F' B' C' D' E' H' L' ");
                            sb.Append("IX   IY   SP   I  R  |");
                            sb.Append("SZ5H3vNC|");
                            sb.Append("Disassembly Check---|");
                            sb.Append("STACK ---------------");
                            Debug.WriteLine(sb.ToString());
                        }
                        sb.Clear();
                        sb.AppendFormat("{0:X4} ", m_ei.PC);
                        sb.Append(m_ei.Bytes.PadRight(12));
                        sb.Append(m_ei.OpCode.PadRight(5));
                        if (!String.IsNullOrEmpty(m_ei.Op1) && !String.IsNullOrEmpty(m_ei.Op2))
                        {
                            sb.Append((m_ei.Op1 + "," + m_ei.Op2).PadRight(10));
                        }
                        else
                        {
                            sb.Append((m_ei.Op1 + m_ei.Op2).PadRight(10));
                        }
                        sb.Append("|");

                        sb.AppendFormat("{0:X2} ", m_reg_A);
                        sb.AppendFormat("{0:X2} ", Flags);
                        sb.AppendFormat("{0:X2} ", m_reg_B);
                        sb.AppendFormat("{0:X2} ", m_reg_C);
                        sb.AppendFormat("{0:X2} ", m_reg_D);
                        sb.AppendFormat("{0:X2} ", m_reg_E);
                        sb.AppendFormat("{0:X2} ", m_reg_H);
                        sb.AppendFormat("{0:X2} ", m_reg_L);

                        //sb.AppendFormat("{0:X2} ", m_reg_A_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_Flags_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_B_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_C_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_D_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_E_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_H_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_L_Alt);

                        sb.AppendFormat("{0:X4} ", m_reg_IX);
                        sb.AppendFormat("{0:X4} ", m_reg_IY);
                        sb.AppendFormat("{0:X4} ", m_reg_SP);
                        sb.AppendFormat("{0:X2} ", m_reg_I);
                        sb.AppendFormat("{0:X2} ", m_reg_R);
                        sb.Append("|");

                        sb.Append(Convert.ToString(Flags, 2).PadLeft(8, '0'));
                        sb.Append("|");

                        string strDisassemblyCheck = m_dis.Disassemble(() => readMemByte(m_ei.PC++));
                        sb.Append(strDisassemblyCheck.PadRight(20));
                        sb.Append("|");

                        for (int spDump = m_reg_SP; spDump <= m_reg_SP + 5; spDump++)
                        {
                            sb.AppendFormat("{0:X2} ", readMemByte((UInt16)spDump));
                        }

                        Debug.WriteLine(sb.ToString());
                        sb = null;
                    }
#endif
                }
                else
                {
                    m_Cycle++;
                }
                break;
            }
        }
Beispiel #2
0
        public static void GenerateOpcodeSizes()
        {
            Z80_Disassembler disasm = new Z80_Disassembler();

            for (int i = 0; i < 256; i++)
            {
                int    pc     = 0;
                byte[] opcode = { (byte)i, 0, 0, 0 };
                disasm.Disassemble(() => opcode[pc++]);
                opcodeSizes[0, i] = (sbyte)pc;
            }

            opcodeSizes[0, 0xCB] = -1;
            opcodeSizes[0, 0xED] = -2;
            opcodeSizes[0, 0xDD] = -3;
            opcodeSizes[0, 0xFD] = -4;

            for (int i = 0; i < 256; i++)
            {
                int    pc     = 0;
                byte[] opcode = { 0xCB, (byte)i, 0, 0, 0 };
                disasm.Disassemble(() => opcode[pc++]);
                opcodeSizes[1, i] = (sbyte)pc;
            }

            for (int i = 0; i < 256; i++)
            {
                int    pc     = 0;
                byte[] opcode = { 0xED, (byte)i, 0, 0, 0 };
                disasm.Disassemble(() => opcode[pc++]);
                opcodeSizes[2, i] = (sbyte)pc;
            }

            for (int i = 0; i < 256; i++)
            {
                int    pc     = 0;
                byte[] opcode = { 0xDD, (byte)i, 0, 0, 0 };
                disasm.Disassemble(() => opcode[pc++]);
                opcodeSizes[3, i] = (sbyte)pc;
            }

            opcodeSizes[3, 0xCB] = -5;
            opcodeSizes[3, 0xED] = -2;

            for (int i = 0; i < 256; i++)
            {
                int    pc     = 0;
                byte[] opcode = { 0xFD, (byte)i, 0, 0, 0 };
                disasm.Disassemble(() => opcode[pc++]);
                opcodeSizes[4, i] = (sbyte)pc;
            }

            opcodeSizes[3, 0xCB] = -6;
            opcodeSizes[3, 0xED] = -2;

            for (int i = 0; i < 256; i++)
            {
                int    pc     = 0;
                byte[] opcode = { 0xDD, 0xCB, (byte)i, 0, 0, 0 };
                disasm.Disassemble(() => opcode[pc++]);
                opcodeSizes[5, i] = (sbyte)pc;
            }

            for (int i = 0; i < 256; i++)
            {
                int    pc     = 0;
                byte[] opcode = { 0xFD, 0xCB, (byte)i, 0, 0, 0 };
                disasm.Disassemble(() => opcode[pc++]);
                opcodeSizes[6, i] = (sbyte)pc;
            }
        }