1 |
3 |
gdevic |
//=========================================================================================
|
2 |
|
|
// This file contains substitute strings for macros used in the Excel timing table and
|
3 |
|
|
// is read and processed by genmatrix.py script to generate exec_matrix.i include file.
|
4 |
|
|
//
|
5 |
|
|
// Format of the file:
|
6 |
|
|
//
|
7 |
|
|
// * Each key is prefixed by ':' and corresponds to a spreadsheet column name.
|
8 |
|
|
// * A column (key) contains a number of macros, each starting at its own line.
|
9 |
|
|
// * A macro may span multiple lines, in which case use the '\' character after the name to
|
10 |
|
|
// continue on the next line.
|
11 |
|
|
// * Multiline macros end when a line does not _start_ with a space character.
|
12 |
|
|
// //-style comments are wrapped within /* ... */ if they don't start a line.
|
13 |
|
|
//=========================================================================================
|
14 |
|
|
|
15 |
|
|
//-----------------------------------------------------------------------------------------
|
16 |
|
|
:Function
|
17 |
|
|
//-----------------------------------------------------------------------------------------
|
18 |
|
|
//Fetch is M1
|
19 |
|
|
fMFetch
|
20 |
|
|
fMRead fMRead=1;
|
21 |
|
|
fMWrite fMWrite=1;
|
22 |
|
|
fIORead fIORead=1;
|
23 |
|
|
fIOWrite fIOWrite=1;
|
24 |
|
|
|
25 |
|
|
//-----------------------------------------------------------------------------------------
|
26 |
|
|
// Basic timing control
|
27 |
|
|
//-----------------------------------------------------------------------------------------
|
28 |
|
|
:valid
|
29 |
|
|
1 validPLA=1;
|
30 |
|
|
:nextM
|
31 |
|
|
1 nextM=1;
|
32 |
|
|
mr nextM=1; ctl_mRead=1;
|
33 |
|
|
mw nextM=1; ctl_mWrite=1;
|
34 |
|
|
ior nextM=1; ctl_iorw=1;
|
35 |
|
|
iow nextM=1; ctl_iorw=1;
|
36 |
|
|
CC nextM=!flags_cond_true;
|
37 |
|
|
INT nextM=1; ctl_mRead=in_intr & im2; // RST38 interrupt extension
|
38 |
|
|
:setM1
|
39 |
|
|
1 setM1=1;
|
40 |
|
|
SS setM1=!flags_cond_true;
|
41 |
|
|
CC setM1=!flags_cond_true;
|
42 |
|
|
ZF setM1=flags_zf; // Used in DJNZ
|
43 |
|
|
BR setM1=nonRep | !repeat_en;
|
44 |
|
|
BRZ setM1=nonRep | !repeat_en | flags_zf;
|
45 |
|
|
INT setM1=!(in_intr & im2); // RST38 interrupt extension
|
46 |
|
|
|
47 |
|
|
//-----------------------------------------------------------------------------------------
|
48 |
|
|
// Register file, address (downstream) endpoint
|
49 |
|
|
//-----------------------------------------------------------------------------------------
|
50 |
|
|
:A:reg rd
|
51 |
|
|
// General purpose registers
|
52 |
|
|
A ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10; ctl_sw_4d=1; // Read 8-bit general purpose A register, enable SW4 downstream
|
53 |
|
|
r16 ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1; // Read 16-bit general purpose register, enable SW4 downstream
|
54 |
|
|
BC ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1; // Read 16-bit BC, enable SW4 downstream
|
55 |
|
|
DE ctl_reg_gp_sel=`GP_REG_DE; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1; // Read 16-bit DE, enable SW4 downstream
|
56 |
|
|
HL ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1; // Read 16-bit HL, enable SW4 downstream
|
57 |
|
|
SP ctl_reg_use_sp=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b11; ctl_sw_4d=1;// Read 16-bit SP, enable SW4 downstream
|
58 |
|
|
|
59 |
|
|
// System registers
|
60 |
|
|
WZ ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4d=1; // Select 16-bit WZ
|
61 |
|
|
IR ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b11; // Select 16-bit IR
|
62 |
|
|
I* ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b10; ctl_sw_4d=1; // Select 8-bit I register
|
63 |
|
|
PC ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b11; // Select 16-bit PC
|
64 |
|
|
|
65 |
|
|
// Conditional assertions of WZ, HL instead of PC
|
66 |
|
|
WZ? \
|
67 |
|
|
if (flags_cond_true) begin // If cc is true, use WZ instead of PC (for jumps)
|
68 |
|
|
ctl_reg_not_pc=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4d=1;
|
69 |
|
|
end
|
70 |
|
|
|
71 |
|
|
:A:reg wr
|
72 |
|
|
// General purpose registers
|
73 |
|
|
r16 ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit general purpose register, enable SW4 upstream
|
74 |
|
|
BC ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit BC, enable SW4 upstream
|
75 |
|
|
DE ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_DE; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit BC, enable SW4 upstream
|
76 |
|
|
HL ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit HL, enable SW4 upstream
|
77 |
|
|
SP ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b11; ctl_reg_use_sp=1; ctl_sw_4u=1; // Write 16-bit SP, enable SW4 upstream
|
78 |
|
|
// System registers
|
79 |
|
|
WZ ctl_reg_sys_we=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4u=1; // Write 16-bit WZ, enable SW4 upstream
|
80 |
|
|
IR ctl_reg_sys_we=1; ctl_reg_sel_ir=1; ctl_reg_sys_hilo=2'b11; // Write 16-bit IR
|
81 |
|
|
// PC will not be incremented if we are in HALT, INTR or NMI state
|
82 |
|
|
PC ctl_reg_sys_we=1; ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b11; pc_inc=!(in_halt | in_intr | in_nmi); // Write 16-bit PC and control incrementer
|
83 |
|
|
> ctl_sw_4u=1;
|
84 |
|
|
|
85 |
|
|
//-----------------------------------------------------------------------------------------
|
86 |
|
|
// Controls the address latch incrementer, the address latch and the address pin mux
|
87 |
|
|
//-----------------------------------------------------------------------------------------
|
88 |
|
|
:inc/dec
|
89 |
|
|
+ ctl_inc_cy=pc_inc; // Increment
|
90 |
|
|
- ctl_inc_cy=pc_inc; ctl_inc_dec=1; // Decrement
|
91 |
|
|
op3 ctl_inc_cy=pc_inc; ctl_inc_dec=op3; // Decrement if op3 is set; increment otherwise
|
92 |
|
|
|
93 |
|
|
:A:latch
|
94 |
|
|
W ctl_al_we=1; // Write a value from the register bus to the address latch
|
95 |
|
|
R ctl_bus_inc_oe=1; // Output enable incrementer to the register bus
|
96 |
|
|
P ctl_apin_mux=1; // Apin sourced from incrementer
|
97 |
|
|
RL ctl_bus_inc_oe=1; ctl_apin_mux2=1; // Apin sourced from AL
|
98 |
|
|
|
99 |
|
|
//-----------------------------------------------------------------------------------------
|
100 |
|
|
// Register file, data (upstream) endpoint
|
101 |
|
|
//-----------------------------------------------------------------------------------------
|
102 |
|
|
:D:reg rd
|
103 |
|
|
//----- General purpose registers -----
|
104 |
|
|
A ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10;
|
105 |
|
|
AF ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b11;
|
106 |
|
|
B ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b10;
|
107 |
|
|
H ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b10;
|
108 |
|
|
L ctl_reg_gp_sel=`GP_REG_HL; ctl_reg_gp_hilo=2'b01;
|
109 |
|
|
r8 \ // r8 addressing does not allow reading F register (A and F are also indexed as swapped) (ex. in OUT (c),r)
|
110 |
|
|
if (op4 & op5 & !op3) ctl_bus_zero_oe=1; // Trying to read flags? Put 0 on the bus instead.
|
111 |
|
|
else begin ctl_reg_gp_sel=op54; ctl_reg_gp_hilo={!rsel3,rsel3}; end // Read 8-bit GP register
|
112 |
|
|
r8' ctl_reg_gp_sel=op21; ctl_reg_gp_hilo={!rsel0,rsel0};// Read 8-bit GP register selected by op[2:0]
|
113 |
|
|
rh ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b10; // Read 8-bit GP register high byte
|
114 |
|
|
rl ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b01; // Read 8-bit GP register low byte
|
115 |
|
|
//----- System registers -----
|
116 |
|
|
WZ ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11; ctl_sw_4u=1;
|
117 |
|
|
Z ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b01; ctl_sw_4u=1; // Selecting strictly Z
|
118 |
|
|
I/R ctl_reg_sel_ir=1; ctl_reg_sys_hilo={!op3,op3}; ctl_sw_4u=1; // Read either I or R based on op3 (0 or 1)
|
119 |
|
|
PCh ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b10; ctl_sw_4u=1;
|
120 |
|
|
PCl ctl_reg_sel_pc=1; ctl_reg_sys_hilo=2'b01; ctl_sw_4u=1;
|
121 |
|
|
|
122 |
|
|
:D:reg wr
|
123 |
|
|
? // Which register to be written is decided elsewhere
|
124 |
|
|
//----- General purpose registers -----
|
125 |
|
|
A ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b10;
|
126 |
|
|
F ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_AF; ctl_reg_gp_hilo=2'b01;
|
127 |
|
|
B ctl_reg_gp_we=1; ctl_reg_gp_sel=`GP_REG_BC; ctl_reg_gp_hilo=2'b10;
|
128 |
|
|
r8 ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo={!rsel3,rsel3}; // Write 8-bit GP register
|
129 |
|
|
r8' ctl_reg_gp_we=1; ctl_reg_gp_sel=op21; ctl_reg_gp_hilo={!rsel0,rsel0}; // Write 8-bit GP register selected by op[2:0]
|
130 |
|
|
rh ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b10; // Write 8-bit GP register high byte
|
131 |
|
|
rl ctl_reg_gp_we=1; ctl_reg_gp_sel=op54; ctl_reg_gp_hilo=2'b01; // Write 8-bit GP register low byte
|
132 |
|
|
//----- System registers -----
|
133 |
|
|
I/R ctl_reg_sys_we=1; ctl_reg_sel_ir=1; ctl_reg_sys_hilo={!op3,op3}; ctl_sw_4d=1; // Write either I or R based on op3 (0 or 1)
|
134 |
|
|
WZ ctl_reg_sys_we=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo=2'b11;
|
135 |
|
|
W ctl_reg_sys_we_hi=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo[1]=1; // Selecting only W
|
136 |
|
|
W? ctl_reg_sys_we_hi=flags_cond_true; ctl_reg_sel_wz=flags_cond_true; ctl_reg_sys_hilo[1]=1; // Conditionally selecting only W
|
137 |
|
|
Z ctl_reg_sys_we_lo=1; ctl_reg_sel_wz=1; ctl_reg_sys_hilo[0]=1; // Selecting only Z
|
138 |
|
|
|
139 |
|
|
//-----------------------------------------------------------------------------------------
|
140 |
|
|
// Controls the register file gate connecting it with the ALU and data bus
|
141 |
|
|
//-----------------------------------------------------------------------------------------
|
142 |
|
|
:Reg gate
|
143 |
|
|
< ctl_reg_in_hi=1; ctl_reg_in_lo=1; // From the ALU side into the register file
|
144 |
|
|
|
145 |
|
|
|
146 |
|
|
> ctl_reg_out_hi=1; ctl_reg_out_lo=1; // From the register file into the ALU
|
147 |
|
|
>l ctl_reg_out_lo=1; // From the register file into the ALU low byte only
|
148 |
|
|
>h ctl_reg_out_hi=1; // From the register file into the ALU high byte only
|
149 |
|
|
|
150 |
|
|
//-----------------------------------------------------------------------------------------
|
151 |
|
|
// Switches on the data bus for each direction (upstream, downstream)
|
152 |
|
|
//-----------------------------------------------------------------------------------------
|
153 |
|
|
:SW2
|
154 |
|
|
d ctl_sw_2d=1;
|
155 |
|
|
u ctl_sw_2u=1;
|
156 |
|
|
|
157 |
|
|
:SW1
|
158 |
|
|
< ctl_sw_1d=1;
|
159 |
|
|
> ctl_sw_1u=1;
|
160 |
|
|
|
161 |
|
|
//-----------------------------------------------------------------------------------------
|
162 |
|
|
// Data bus latches and pads control
|
163 |
|
|
//-----------------------------------------------------------------------------------------
|
164 |
|
|
:DB pads
|
165 |
|
|
R ctl_bus_db_oe=1; // Read DB pads to internal data bus
|
166 |
|
|
W ctl_bus_db_we=1; // Write DB pads with internal data bus value
|
167 |
|
|
00 ctl_bus_zero_oe=1; // Force 0x00 on the data bus
|
168 |
|
|
FF ctl_bus_ff_oe=1; // Force 0xFF on the data bus
|
169 |
|
|
|
170 |
|
|
//-----------------------------------------------------------------------------------------
|
171 |
|
|
// ALU
|
172 |
|
|
//-----------------------------------------------------------------------------------------
|
173 |
|
|
:ALU
|
174 |
|
|
// Controls the master ALU output enable and the ALU input, only one can be active at a time
|
175 |
|
|
// >bs if set, will override >s0 which is used by bit instructions to override default M1/T3 load
|
176 |
|
|
< ctl_alu_oe=1; // Enable ALU onto the data bus
|
177 |
|
|
>s0 ctl_alu_shift_oe=!ctl_alu_bs_oe; // Shifter unit without shift-enable
|
178 |
|
|
>s1 ctl_alu_shift_oe=1; ctl_shift_en=1; // Shifter unit AND shift enable!
|
179 |
|
|
>bs ctl_alu_bs_oe=1; // Bit-selector unit
|
180 |
|
|
|
181 |
|
|
:ALU bus
|
182 |
|
|
// Controls the writer to the internal ALU bus
|
183 |
|
|
op1 ctl_alu_op1_oe=1; // OP1 latch
|
184 |
|
|
op2 ctl_alu_op2_oe=1; // OP2 latch
|
185 |
|
|
res ctl_alu_res_oe=1; // Result latch
|
186 |
|
|
|
187 |
|
|
:op2 latch
|
188 |
|
|
// Controls a MUX to select the input to the OP2 latch
|
189 |
|
|
bus ctl_alu_op2_sel_bus=1; // Internal bus
|
190 |
|
|
lq ctl_alu_op2_sel_lq=1; // Cross-bus wire (see schematic)
|
191 |
|
|
|
192 |
|
|
|
193 |
|
|
:op1 latch
|
194 |
|
|
// Controls a MUX to select the input to the OP1 latch
|
195 |
|
|
bus ctl_alu_op1_sel_bus=1; // Internal bus
|
196 |
|
|
low ctl_alu_op1_sel_low=1; // Write low nibble with a high nibble
|
197 |
|
|
|
198 |
|
|
|
199 |
|
|
:operation
|
200 |
|
|
// Sets the ALU core operation
|
201 |
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
202 |
|
|
CP \
|
203 |
|
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_alu_sel_op2_neg=1;
|
204 |
|
|
if (ctl_alu_op_low) begin
|
205 |
|
|
ctl_flags_cf_set=1;
|
206 |
|
|
end else begin
|
207 |
|
|
ctl_alu_core_hf=1;
|
208 |
|
|
end
|
209 |
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
210 |
|
|
SUB \
|
211 |
|
|
|
212 |
|
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_alu_sel_op2_neg=1;
|
213 |
|
|
if (ctl_alu_op_low) begin
|
214 |
|
|
ctl_flags_cf_set=1;
|
215 |
|
|
end else begin
|
216 |
|
|
ctl_alu_core_hf=1;
|
217 |
|
|
end
|
218 |
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
219 |
|
|
SBC \
|
220 |
|
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_alu_sel_op2_neg=1;
|
221 |
|
|
if (ctl_alu_op_low) begin
|
222 |
|
|
ctl_flags_cf_cpl=1;
|
223 |
|
|
end else begin
|
224 |
|
|
ctl_alu_core_hf=1;
|
225 |
|
|
end
|
226 |
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
227 |
|
|
SBCh \
|
228 |
|
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_alu_sel_op2_neg=1;
|
229 |
|
|
if (!ctl_alu_op_low) begin
|
230 |
|
|
ctl_alu_core_hf=1;
|
231 |
|
|
end
|
232 |
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
233 |
|
|
ADC \
|
234 |
|
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0;
|
235 |
|
|
if (!ctl_alu_op_low) begin
|
236 |
|
|
ctl_alu_core_hf=1;
|
237 |
|
|
end
|
238 |
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
239 |
|
|
ADD \
|
240 |
|
|
ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=0;
|
241 |
|
|
if (ctl_alu_op_low) begin
|
242 |
|
|
ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
243 |
|
|
end else begin
|
244 |
|
|
ctl_alu_core_hf=1;
|
245 |
|
|
end
|
246 |
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
247 |
|
|
AND ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=1; ctl_flags_cf_set=1;
|
248 |
|
|
OR ctl_alu_core_R=1; ctl_alu_core_V=1; ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
249 |
|
|
XOR ctl_alu_core_R=1; ctl_alu_core_V=0; ctl_alu_core_S=0; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1;
|
250 |
|
|
|
251 |
|
|
NAND ctl_alu_core_R=0; ctl_alu_core_V=0; ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_alu_sel_op2_neg=1;
|
252 |
|
|
NOR ctl_alu_core_R=1; ctl_alu_core_V=1; ctl_alu_core_S=1; ctl_flags_cf_set=1; ctl_flags_cf_cpl=1; ctl_alu_sel_op2_neg=1;
|
253 |
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
254 |
|
|
|
255 |
|
|
PLA ctl_state_alu=1; // Assert the ALU PLA modifier to determine operation
|
256 |
|
|
|
257 |
|
|
:nibble
|
258 |
|
|
// ALU computational phase: low nibble or high nibble
|
259 |
|
|
L ctl_alu_op_low=1; // Activate ALU operation on low nibble
|
260 |
|
|
H ctl_alu_sel_op2_high=1; // Activate ALU operation on high nibble
|
261 |
|
|
|
262 |
|
|
//-----------------------------------------------------------------------------------------
|
263 |
|
|
// FLAGT
|
264 |
|
|
//-----------------------------------------------------------------------------------------
|
265 |
|
|
:FLAGT
|
266 |
|
|
< ctl_flags_oe=1; // Enable FLAGT onto the data bus
|
267 |
|
|
> ctl_flags_bus=1; // Load FLAGT from the data bus
|
268 |
|
|
alu ctl_flags_alu=1; // Load FLAGT from the ALU
|
269 |
|
|
|
270 |
|
|
// Write enables for various flag bits and segments
|
271 |
|
|
:SZ
|
272 |
|
|
* ctl_flags_sz_we=1;
|
273 |
|
|
:XY
|
274 |
|
|
* ctl_flags_xy_we=1;
|
275 |
|
|
?
|
276 |
|
|
:HF
|
277 |
|
|
* ctl_flags_hf_we=1;
|
278 |
|
|
W2 ctl_flags_hf2_we=1; // Write HF2 flag (DAA only)
|
279 |
|
|
:PF
|
280 |
|
|
* ctl_flags_pf_we=1;
|
281 |
|
|
P ctl_flags_pf_we=1; ctl_pf_sel=`PFSEL_P;
|
282 |
|
|
V ctl_flags_pf_we=1; ctl_pf_sel=`PFSEL_V;
|
283 |
|
|
iff2 ctl_flags_pf_we=1; ctl_pf_sel=`PFSEL_IFF2;
|
284 |
|
|
REP ctl_flags_pf_we=1; ctl_pf_sel=`PFSEL_REP;
|
285 |
|
|
?
|
286 |
|
|
:NF
|
287 |
|
|
* ctl_flags_nf_we=1; // Previous NF, to be used when loading FLAGT
|
288 |
|
|
|
289 |
|
|
1 ctl_flags_nf_we=1; ctl_flags_nf_set=1;
|
290 |
|
|
S ctl_flags_nf_we=1; // Sign bit, to be used with FLAGT source set to "alu"
|
291 |
|
|
?
|
292 |
|
|
:CF
|
293 |
|
|
* ctl_flags_cf_we=1;
|
294 |
|
|
|
295 |
|
|
1 ctl_flags_cf_set=1; // Set CF going into the ALU core
|
296 |
|
|
^ ctl_flags_cf_we=1; ctl_flags_cf_cpl=1; // CCF
|
297 |
|
|
:CF2
|
298 |
|
|
R ctl_flags_use_cf2=1;
|
299 |
|
|
W ctl_flags_cf2_we=1; ctl_flags_cf2_sel=0;
|
300 |
|
|
W.sh ctl_flags_cf2_we=1; ctl_flags_cf2_sel=1;
|
301 |
|
|
W.daa ctl_flags_cf2_we=1; ctl_flags_cf2_sel=2;
|
302 |
|
|
W.0 ctl_flags_cf2_we=1; ctl_flags_cf2_sel=3;
|
303 |
|
|
|
304 |
|
|
//-----------------------------------------------------------------------------------------
|
305 |
|
|
// Special sequence macros for some instructions make it simpler for all other entries
|
306 |
|
|
//-----------------------------------------------------------------------------------------
|
307 |
|
|
:Special
|
308 |
|
|
USE_SP ctl_reg_use_sp=1; // For 16-bit loads: use SP instead of AF
|
309 |
|
|
|
310 |
|
|
// A few more specific states and instructions:
|
311 |
|
|
Ex_DE_HL ctl_reg_ex_de_hl=1; // EX DE,HL
|
312 |
|
|
Ex_AF_AF' ctl_reg_ex_af=1; // EX AF,AF'
|
313 |
|
|
EXX ctl_reg_exx=1; // EXX
|
314 |
|
|
HALT ctl_state_halt_set=1; // Enter HALT state
|
315 |
|
|
DI_EI ctl_iffx_bit=op3; ctl_iffx_we=1; // DI/EI
|
316 |
|
|
IM ctl_im_we=1; // IM n ('n' is read by opcode[4:3])
|
317 |
|
|
|
318 |
|
|
WZ=IX+d ixy_d=1; // Compute WZ=IX+d
|
319 |
|
|
IX_IY ctl_state_ixiy_we=1; ctl_state_iy_set=op5; setIXIY=1; // IX/IY prefix
|
320 |
|
|
CLR_IX_IY ctl_state_ixiy_we=1; ctl_state_ixiy_clr=!setIXIY; // Clear IX/IY flag
|
321 |
|
|
|
322 |
|
|
CB ctl_state_tbl_cb_set=1; setCBED=1; // CB-table prefix
|
323 |
|
|
ED ctl_state_tbl_ed_set=1; setCBED=1; // ED-table prefix
|
324 |
|
|
CLR_CB_ED ctl_state_tbl_clr=!setCBED; // Clear CB/ED prefix
|
325 |
|
|
|
326 |
|
|
// If the NF is set, complement HF and CF on the way out to the bus
|
327 |
|
|
// This is used to correctly set those flags after subtraction operations
|
328 |
|
|
?NF_HF_CF ctl_flags_hf_cpl=flags_nf; ctl_flags_cf_cpl=flags_nf;
|
329 |
|
|
?NF_HF ctl_flags_hf_cpl=flags_nf;
|
330 |
|
|
?~CF_HF ctl_flags_hf_cpl=!flags_cf; // Used for CCF
|
331 |
|
|
?SF_NEG ctl_alu_sel_op2_neg=flags_sf;
|
332 |
|
|
NEG_OP2 ctl_alu_sel_op2_neg=1;
|
333 |
|
|
?NF_SUB ctl_alu_sel_op2_neg=flags_nf; ctl_flags_cf_cpl=!flags_nf;
|
334 |
|
|
|
335 |
|
|
// M1 opcode read cycle and the refresh register increment cycle
|
336 |
|
|
// Write opcode into the instruction register through internal db0 bus:
|
337 |
|
|
OpcodeToIR ctl_ir_we=1;
|
338 |
|
|
// At the common instruction load M1/T3, override opcode byte when servicing interrupts:
|
339 |
|
|
// 1. We are in HALT mode: push NOP (0x00) instead
|
340 |
|
|
// 2. We are in INTR mode (IM1 or IM2): push RST38 (0xFF) instead
|
341 |
|
|
// 3. We are in NMI mode: push RST38 (0xFF) instead
|
342 |
|
|
OverrideIR ctl_bus_zero_oe=in_halt; ctl_bus_ff_oe=(in_intr & (im1 | im2)) | in_nmi;
|
343 |
|
|
|
344 |
|
|
// RST instruction uses opcode[5:3] to specify a vector and this control passes those 3 bits through
|
345 |
|
|
MASK_543 ctl_sw_mask543_en=!((in_intr & im2) | in_nmi);
|
346 |
|
|
// Based on the in_nmi state, several things are set:
|
347 |
|
|
// 1. Disable SW1 so the opcode will not get onto db1 bus
|
348 |
|
|
// 2. Generate 0x66 on the db1 bus which will be used as the target vector address
|
349 |
|
|
// 3. Clear IFF1 (done by the nmi logic on posedge of in_nmi)
|
350 |
|
|
RST_NMI ctl_sw_1d=!in_nmi; ctl_66_oe=in_nmi;
|
351 |
|
|
// Based on the in_intr state, several things are set:
|
352 |
|
|
// 1. IM1 mode, force 0xFF on the db0 bus
|
353 |
|
|
// 2. Clear IFF1 and IFF2 (done by the intr logic on posedge of in_intr)
|
354 |
|
|
RST_INT ctl_bus_ff_oe=in_intr & im1;
|
355 |
|
|
RETN ctl_iff1_iff2=1; // RETN copies IFF2 into IFF1
|
356 |
|
|
NO_INTS ctl_no_ints=1; // Disable interrupt generation for this opcode (DI/EI/CB/ED/DD/FD)
|
357 |
|
|
|
358 |
|
|
EvalCond ctl_eval_cond=1; // Evaluate flags condition based on the opcode[5:3]
|
359 |
|
|
CondShort ctl_cond_short=1; // M1/T3 only: force a short flags condition (SS)
|
360 |
|
|
Limit6 ctl_inc_limit6=1; // Limit the incrementer to 6 bits
|
361 |
|
|
DAA ctl_daa_oe=1; // Write DAA correction factor to the bus
|
362 |
|
|
ZERO_16BIT ctl_alu_zero_16bit=1; // 16-bit arithmetic operation uses ZF calculated over 2 bytes
|
363 |
|
|
NonRep nonRep=1; // Non-repeating block instruction
|
364 |
|
|
WriteBC=1 ctl_repeat_we=1; // Update repeating flag latch with BC=1 status
|
365 |
|
|
NOT_PC! ctl_reg_not_pc=1; // For M1/T1 load from a register other than PC
|