Browse code

Add source code of the XiPC emulator

Pawel Jablonski authored on 17/03/2023 16:46:08
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,208 @@
1
+/*
2
+ * Author: Pawel Jablonski
3
+ * E-mail: pj@xirx.net
4
+ * WWW: xirx.net
5
+ * GIT: git.xirx.net
6
+ *
7
+ * License: You can use this code however you like
8
+ * but leave information about the original author.
9
+ * Code is free for non-commercial and commercial use.
10
+ */
11
+
12
+#ifndef CPU_H
13
+#define CPU_H
14
+
15
+#include <QObject>
16
+#include <QVector>
17
+#include <QTimer>
18
+
19
+#include "io.h"
20
+
21
+//! This class contains CPU contex and functions
22
+class CPU : public QObject
23
+{
24
+	Q_OBJECT
25
+
26
+	public:
27
+		static const int FREQUENCY = 1000000; //!< Base frequency of CPU
28
+
29
+		static const int INTERVAL = 125; //!< Time in milliseconds between every step of the emulation
30
+		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
31
+
32
+		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
33
+		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.
34
+
35
+		static const int MEMORY_PAGE_SIZE = 256; //!< Memory page size
36
+		static const int MEMORY_PAGE_QUANTITY = 128; //!< Quantity of pages in one memory block
37
+		static const int MEMORY_SIZE = (MEMORY_PAGE_SIZE * MEMORY_PAGE_QUANTITY); //!< Size of the memory block
38
+
39
+		static const int ROM_OS_ADDRESS = 0x0000; //!< Start of ROM OS address space
40
+		static const int ROM_APP_ADDRESS = 0x8000; //!< Start of ROM Application address space
41
+
42
+		static const int RAM_OS_ADDRESS = 0x0000; //!< Start of RAM OS address space
43
+		static const int RAM_SP_ADDRESS = 0x0f00; //!< Start of RAM Stack Pointer address space
44
+		static const int RAM_APP_ADDRESS = 0x1000; //!< Start of RAM Application address space
45
+
46
+		static const int STACK_PAGE = 0x0f; //!< Page number of the stack
47
+
48
+		static const int UROM_ADDRESS_CYCLE_MASK = 0x0f; //!< Micro-step mask of the CPU step for uROM
49
+
50
+		static const int UROM_ADDRESS_INSTRUCTION_POSITION = 0; //!< Offset of instruction for uROM
51
+		static const int UROM_ADDRESS_CYCLE_POSITION = 8; //!< Offset of micro-step for uROM
52
+		static const int UROM_ADDRESS_FLAG_C_POSITION = 12; //!< Offset of C Flag for uROM
53
+		static const int UROM_ADDRESS_FLAG_Z_POSITION = 13; //!< Offset of Z Flag for uROM
54
+
55
+		static const int UROM_0_BUS_AR_MASK = 0b00000111; //!< BUS A Read mask for first uROM bank
56
+		static const int UROM_0_BUS_AW_MASK = 0b01111000; //!< BUS A Write mask for first uROM bank
57
+		static const int UROM_0_BUS_B_MASK = 0b10000000; //!< BUS B mask for first uROM bank
58
+
59
+		static const int UROM_0_BUS_AR_POSITION = 0; //!< BUS A Read offset for first uROM bank
60
+		static const int UROM_0_BUS_AW_POSITION = 3; //!< BUS A Write offset for first uROM bank
61
+		static const int UROM_0_BUS_B_POSITION = 7; //!< BUS B offset for first uROM bank
62
+
63
+		static const int UROM_1_BUS_C_MASK = 0b00000011; //!< BUS C mask for second uROM bank
64
+		static const int UROM_1_ALU_S_MASK = 0b00111100; //!< ALU S Flags mask for second uROM bank
65
+		static const int UROM_1_ALU_M_MASK = 0b01000000; //!< ALU M Flag mask for second uROM bank
66
+		static const int UROM_1_ALU_C_MASK = 0b10000000; //!< ALU C Flag mask for second uROM bank
67
+
68
+		static const int UROM_1_BUS_C_POSITION = 0; //!< BUS C offset for second uROM bank
69
+		static const int UROM_1_ALU_S_POSITION = 2; //!< ALU S Flags offset for second uROM bank
70
+
71
+		static const int INSTRUCTION_REG_ABXY_FIRST_MASK = 0b00000011; //!< First argument ABXY Register mask for opcode
72
+		static const int INSTRUCTION_REG_ABXY_SECOND_MASK = 0b00001100; //!< Second argument ABXY Register mask for opcode
73
+		static const int INSTRUCTION_REG_AB_MASK = 0b00000100; //!< Second argument AB Register mask for opcode
74
+
75
+		static const int INSTRUCTION_REG_ABXY_FIRST_OFFSET = 0; //!< First argument ABXY Register offset for opcode
76
+		static const int INSTRUCTION_REG_ABXY_SECOND_OFFSET = 2; //!< Second argument ABXY Register offset for opcode
77
+		static const int INSTRUCTION_REG_AB_OFFSET = 2; //!< Second argument AB Register offset for opcode
78
+
79
+		static const int ALU_4BIT_MASK = 0x0f; //!< ALU Input/Output mask for lower and higher part of byte
80
+		static const int ALU_4BIT_OFFSET = 4; //!< ALU Input/Output offset for lower and higher part of byte
81
+
82
+		//! Memory buffer
83
+		struct Memory
84
+		{
85
+			QVector<unsigned char> data = QVector<unsigned char>(MEMORY_SIZE); //!< Memory data
86
+		};
87
+
88
+		//! Register buffer
89
+		struct Reg
90
+		{
91
+			unsigned char i; //!< Instruction register
92
+			bool c; //!< Carry Flag register
93
+			bool z; //!< Zero Flag register
94
+			unsigned char pch; //!< Program Counter High register
95
+			unsigned char pcl; //!< Program Counter Low register
96
+			unsigned char sph; //!< Stack Pointer High register
97
+			unsigned char spl; //!< Stack Pointer Low register
98
+			unsigned char maxSpl; //!< Maximum reached value of Stack Pointer
99
+			unsigned char a; //!< A register
100
+			unsigned char b; //!< B register
101
+			unsigned char x; //!< X register
102
+			unsigned char y; //!< Y rRegister
103
+			unsigned char in; //!< Input register
104
+			unsigned char out; //!< Output register
105
+			unsigned char d; //!< Hidden Data register
106
+			unsigned char t; //!< ALU Output register
107
+			unsigned char mah; //!< Memory Address High register
108
+			unsigned char mal; //!<Memory Address Low register
109
+		};
110
+
111
+		CPU(QObject *parent = nullptr);
112
+
113
+		void setUrom0(const CPU::Memory &urom);
114
+		void setUrom1(const CPU::Memory &urom);
115
+		void setRom(const CPU::Memory &rom);
116
+
117
+		void run();
118
+		void step();
119
+		void pause();
120
+		void stop();
121
+
122
+		const CPU::Reg &getReg() const;
123
+		unsigned long long getTicks() const;
124
+
125
+		const CPU::Memory &getRom() const;
126
+		const CPU::Memory &getRamLow() const;
127
+		const CPU::Memory &getRamHigh() const;
128
+
129
+	private:
130
+		//! Line select defines for the main reading data bus
131
+		enum class BusAR
132
+		{
133
+			ABXY = 0, //!< Main and auxiliary registers
134
+			D, //!< Hidden data register
135
+			IN, //!< Input register
136
+			T, //!< ALU temp register
137
+			Ram, //!< RAM access
138
+			Flash, //!< FLASH access
139
+			PCL, //!< Program Counter Low register
140
+			PCH //!< Program Counter High register
141
+		};
142
+
143
+		//! Line select defines for the main writing data bus
144
+		enum class BusAW
145
+		{
146
+			None = 0, //!< Not selected
147
+			ABXY, //!< Main and auxiliary registers
148
+			D, //!< Hidden data register
149
+			OUT, //!< Output register
150
+			ALU_T, //!< ALU operation
151
+			RPC, //!< Reset Program Counter
152
+			I, //!< Instruction register
153
+			Ram, //!< RAM access
154
+			PCL, //!< Program Counter Low register
155
+			PCH, //!< Program Counter High register
156
+			MAL, //!< Memory Address Low register
157
+			MAH, //!< Memory Address High register
158
+			PC_PLUS, //!< Increse Program Counter
159
+			SP_PLUS, //!< Increse Stack Pointer
160
+			SP_MINUS, //!< Decrese Stack Pointer
161
+			RPC_PLUS //!< Reset the step counter and increse Program Counter
162
+		};
163
+
164
+		//! Line select defines for the secondary reading data bus
165
+		enum class BusB
166
+		{
167
+			AB = 0, //!< Main registers
168
+			D //!< Hidden data register
169
+		};
170
+
171
+		//! Line select defines for the addressing data bus
172
+		enum class BusC
173
+		{
174
+			PC = 0, //!< Full 16 bit Program Counter register
175
+			MA, //!< Full 16 bit Memory Address register
176
+			SP, //!< Full 16 bit Stack Pointer register
177
+			XY //!< Full 16 bit auxiliary register
178
+		};
179
+
180
+		void reset();
181
+
182
+		unsigned char alu(unsigned char a, unsigned char b, unsigned char s, bool m, bool &c, bool &z);
183
+
184
+		bool stepMode; //!< Step mode enabler for emulation
185
+		unsigned long long ticks; //!< Counter of clock ticks of CPU
186
+		QTimer timer; //!< Timer for executing emulation steps
187
+
188
+		Memory urom0; //!< First uROM memory buffer
189
+		Memory urom1; //!< Second uROM memory buffer
190
+		Memory rom; //!< ROM memory buffer
191
+
192
+		Memory ramLow; //!< Lower 32 kB of RAM buffer
193
+		Memory ramHigh; //!< Higher 32 kB of RAM buffer
194
+
195
+		Reg reg; //!< Register buffer
196
+
197
+	signals:
198
+		void outSignal(unsigned char out);
199
+		void updateSignal();
200
+
201
+	public slots:
202
+		void inSlot(unsigned char in);
203
+
204
+	private slots:
205
+		void emulation();
206
+};
207
+
208
+#endif