/* * Author: Pawel Jablonski * E-mail: pj@xirx.net * WWW: xirx.net * GIT: git.xirx.net * * License: You can use this code however you like * but leave information about the original author. * Code is free for non-commercial and commercial use. */ #ifndef CPU_H #define CPU_H #include #include #include #include "io.h" //! This class contains CPU contex and functions class CPU : public QObject { Q_OBJECT public: static const int FREQUENCY = 1000000; //!< Base frequency of CPU static const int INTERVAL = 125; //!< Time in milliseconds between every step of the emulation static const int TICKS_PER_INTERVAL = ((FREQUENCY * INTERVAL) / 1000); //!< How many clock ticks of CPU will be processed in a single step of the emulation static const int CLOCK_INTERVAL = 125; //!< How many milliseconds is needed to toggle the clock pin status on the IO BUS. Default frequency is 8 Hz static const int CLOCK_TICKS_PER_INTERVAL = ((FREQUENCY * CLOCK_INTERVAL) / 1000); //!< How many clock ticks of CPU is needed to toggle the clock pin status on the IO BUS. static const int MEMORY_PAGE_SIZE = 256; //!< Memory page size static const int MEMORY_PAGE_QUANTITY = 128; //!< Quantity of pages in one memory block static const int MEMORY_SIZE = (MEMORY_PAGE_SIZE * MEMORY_PAGE_QUANTITY); //!< Size of the memory block static const int ROM_OS_ADDRESS = 0x0000; //!< Start of ROM OS address space static const int ROM_APP_ADDRESS = 0x8000; //!< Start of ROM Application address space static const int RAM_OS_ADDRESS = 0x0000; //!< Start of RAM OS address space static const int RAM_SP_ADDRESS = 0x0f00; //!< Start of RAM Stack Pointer address space static const int RAM_APP_ADDRESS = 0x1000; //!< Start of RAM Application address space static const int STACK_PAGE = 0x0f; //!< Page number of the stack static const int UROM_ADDRESS_CYCLE_MASK = 0x0f; //!< Micro-step mask of the CPU step for uROM static const int UROM_ADDRESS_INSTRUCTION_POSITION = 0; //!< Offset of instruction for uROM static const int UROM_ADDRESS_CYCLE_POSITION = 8; //!< Offset of micro-step for uROM static const int UROM_ADDRESS_FLAG_C_POSITION = 12; //!< Offset of C Flag for uROM static const int UROM_ADDRESS_FLAG_Z_POSITION = 13; //!< Offset of Z Flag for uROM static const int UROM_0_BUS_AR_MASK = 0b00000111; //!< BUS A Read mask for first uROM bank static const int UROM_0_BUS_AW_MASK = 0b01111000; //!< BUS A Write mask for first uROM bank static const int UROM_0_BUS_B_MASK = 0b10000000; //!< BUS B mask for first uROM bank static const int UROM_0_BUS_AR_POSITION = 0; //!< BUS A Read offset for first uROM bank static const int UROM_0_BUS_AW_POSITION = 3; //!< BUS A Write offset for first uROM bank static const int UROM_0_BUS_B_POSITION = 7; //!< BUS B offset for first uROM bank static const int UROM_1_BUS_C_MASK = 0b00000011; //!< BUS C mask for second uROM bank static const int UROM_1_ALU_S_MASK = 0b00111100; //!< ALU S Flags mask for second uROM bank static const int UROM_1_ALU_M_MASK = 0b01000000; //!< ALU M Flag mask for second uROM bank static const int UROM_1_ALU_C_MASK = 0b10000000; //!< ALU C Flag mask for second uROM bank static const int UROM_1_BUS_C_POSITION = 0; //!< BUS C offset for second uROM bank static const int UROM_1_ALU_S_POSITION = 2; //!< ALU S Flags offset for second uROM bank static const int INSTRUCTION_REG_ABXY_FIRST_MASK = 0b00000011; //!< First argument ABXY Register mask for opcode static const int INSTRUCTION_REG_ABXY_SECOND_MASK = 0b00001100; //!< Second argument ABXY Register mask for opcode static const int INSTRUCTION_REG_AB_MASK = 0b00000100; //!< Second argument AB Register mask for opcode static const int INSTRUCTION_REG_ABXY_FIRST_OFFSET = 0; //!< First argument ABXY Register offset for opcode static const int INSTRUCTION_REG_ABXY_SECOND_OFFSET = 2; //!< Second argument ABXY Register offset for opcode static const int INSTRUCTION_REG_AB_OFFSET = 2; //!< Second argument AB Register offset for opcode static const int ALU_4BIT_MASK = 0x0f; //!< ALU Input/Output mask for lower and higher part of byte static const int ALU_4BIT_OFFSET = 4; //!< ALU Input/Output offset for lower and higher part of byte //! Memory buffer struct Memory { QVector data = QVector(MEMORY_SIZE); //!< Memory data }; //! Register buffer struct Reg { unsigned char i; //!< Instruction register bool c; //!< Carry Flag register bool z; //!< Zero Flag register unsigned char pch; //!< Program Counter High register unsigned char pcl; //!< Program Counter Low register unsigned char sph; //!< Stack Pointer High register unsigned char spl; //!< Stack Pointer Low register unsigned char maxSpl; //!< Maximum reached value of Stack Pointer unsigned char a; //!< A register unsigned char b; //!< B register unsigned char x; //!< X register unsigned char y; //!< Y rRegister unsigned char in; //!< Input register unsigned char out; //!< Output register unsigned char d; //!< Hidden Data register unsigned char t; //!< ALU Output register unsigned char mah; //!< Memory Address High register unsigned char mal; //!