1 // license:BSD-3-Clause
2 // copyright-holders:Juergen Buchmueller
3 /*****************************************************************************
4  *
5  *   Xerox AltoII emulator task
6  *
7  *****************************************************************************/
8 #include "emu.h"
9 #include "alto2cpu.h"
10 
11 /** @brief CTL2K_U3 address line for F2 function */
12 #define CTL2K_U3(f2) (f2 == f2_emu_idisp ? 0x80 : 0x00)
13 
14 /**
15  * width,from,to of the 16 bit instruction register
16  *                     1 1 1 1 1 1
17  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
18  * =============================================================
19  * x - - - - - - - - - - - - - - - arithmetic operation
20  * 0 m m - - - - - - - - - - - - - memory function
21  * 0 0 0 - - - - - - - - - - - - - jump functions
22  * 0 0 1 d d - - - - - - - - - - - LDA dstAC
23  * 0 1 0 d d - - - - - - - - - - - STA dstAC
24  * 0 1 1 - - - - - - - - - - - - - augmented functions
25  * 1 s s - - - - - - - - - - - - - source accumulator (0-3)
26  * 1 - - d d - - - - - - - - - - - destination accumulator (0-3)
27  * 1 s s d d x x x - - - - - - - - accumulator function
28  * 1 s s d d 0 0 0 - - - - - - - - COM dstAC, srcAC
29  * 1 s s d d 0 0 1 - - - - - - - - NEG dstAC, srcAC
30  * 1 s s d d 0 1 0 - - - - - - - - MOV dstAC, srcAC
31  * 1 s s d d 0 1 1 - - - - - - - - INC dstAC, srcAC
32  * 1 s s d d 1 0 0 - - - - - - - - ADC dstAC, srcAC
33  * 1 s s d d 1 0 1 - - - - - - - - SUB dstAC, srcAC
34  * 1 s s d d 1 1 0 - - - - - - - - ADD dstAC, srcAC
35  * 1 s s d d 1 1 1 - - - - - - - - AND dstAC, srcAC
36  * 1 - - - - - - - x x - - - - - - shift operation
37  * 1 - - - - - - - 0 0 - - - - - - nothing
38  * 1 - - - - - - - 0 1 - - - - - - rotate left through carry
39  * 1 - - - - - - - 1 0 - - - - - - rotate right through carry
40  * 1 - - - - - - - 1 1 - - - - - - swap byte halves
41  * 1 - - - - - - - - - x x - - - - carry in mode
42  * 1 - - - - - - - - - 0 0 - - - - nothing
43  * 1 - - - - - - - - - 0 1 - - - - Z carry in is zero
44  * 1 - - - - - - - - - 1 0 - - - - O carry in is one
45  * 1 - - - - - - - - - 1 1 - - - - C carry in is complemented carry
46  * 1 - - - - - - - - - - - x - - - NL
47  * - - - - - - - - - - - - - x x x conditional execution
48  * - - - - - - - - - - - - - 0 0 0 NVR never skip
49  * - - - - - - - - - - - - - 0 0 1 SKP always skip
50  * - - - - - - - - - - - - - 0 1 0 SZC skip if carry result is zero
51  * - - - - - - - - - - - - - 0 1 1 SNC skip if carry result is non-zero
52  * - - - - - - - - - - - - - 1 0 0 SZR skip if 16 bit result is zero
53  * - - - - - - - - - - - - - 1 0 1 SNR skip if 16 bit result is non-zero
54  * - - - - - - - - - - - - - 1 1 0 SEZ skip if either result is zero
55  * - - - - - - - - - - - - - 1 1 1 SBN skip if both results are non-zero
56  */
57 #define IR_ARITH(ir)    X_RDBITS(ir,16, 0, 0)
58 #define IR_SrcAC(ir)    X_RDBITS(ir,16, 1, 2)
59 #define IR_DstAC(ir)    X_RDBITS(ir,16, 3, 4)
60 #define IR_AFunc(ir)    X_RDBITS(ir,16, 5, 7)
61 #define IR_SH(ir)       X_RDBITS(ir,16, 8, 9)
62 #define IR_CY(ir)       X_RDBITS(ir,16,10,11)
63 #define IR_NL(ir)       X_RDBITS(ir,16,12,12)
64 #define IR_SK(ir)       X_RDBITS(ir,16,13,15)
65 
66 #define IR_MFunc(ir)    X_RDBITS(ir,16, 1, 2)
67 #define IR_JFunc(ir)    X_RDBITS(ir,16, 3, 4)
68 #define IR_I(ir)        X_RDBITS(ir,16, 5, 5)
69 #define IR_X(ir)        X_RDBITS(ir,16, 6, 7)
70 #define IR_DISP(ir)     X_RDBITS(ir,16, 8,15)
71 #define IR_AUGFUNC(ir)  X_RDBITS(ir,16, 3, 7)
72 
73 #define op_MFUNC_MASK   0060000     //!< instruction register memory function mask
74 #define op_MFUNC_JUMP   0000000     //!< jump functions value
75 #define op_JUMP_MASK    0014000     //!< jump functions mask
76 #define op_JMP          0000000     //!< jump
77 #define op_JSR          0004000     //!< jump to subroutine
78 #define op_ISZ          0010000     //!< increment and skip if zero
79 #define op_DSZ          0014000     //!< decrement and skip if zero
80 #define op_LDA          0020000     //!< load accu functions value
81 #define op_STA          0040000     //!< store accu functions value
82 #define op_AUGMENTED    0060000     //!< store accu functions value
83 #define op_AUGM_MASK    0077400     //!< mask covering all augmented functions
84 #define op_AUGM_NODISP  0061000     //!< augmented functions w/o displacement
85 #define op_AUGM_SUBFUNC 0000037     //!< mask for augmented subfunctions in DISP
86 #define op_CYCLE        0060000     //!< cycle AC0
87 #define op_NODISP       0061000     //!< NODISP: opcodes without displacement
88 #define op_DIR          0061000     //!< disable interrupts
89 #define op_EIR          0061001     //!< enable interrupts
90 #define op_BRI          0061002     //!< branch and return from interrupt
91 #define op_RCLK         0061003     //!< read clock to AC0, AC1
92 #define op_SIO          0061004     //!< start I/O
93 #define op_BLT          0061005     //!< block transfer
94 #define op_BLKS         0061006     //!< block set value
95 #define op_SIT          0061007     //!< start interval timer
96 #define op_JMPRAM       0061010     //!< jump to microcode RAM (actually ROM, too)
97 #define op_RDRAM        0061011     //!< read microcode RAM
98 #define op_WRTRAM       0061012     //!< write microcode RAM
99 #define op_DIRS         0061013     //!< disable interrupts, and skip, if already disabled
100 #define op_VERS         0061014     //!< get microcode version in AC0
101 #define op_DREAD        0061015     //!< double word read (Alto II)
102 #define op_DWRITE       0061016     //!< double word write (Alto II)
103 #define op_DEXCH        0061017     //!< double word exchange (Alto II)
104 #define op_MUL          0061020     //!< unsigned multiply
105 #define op_DIV          0061021     //!< unsigned divide
106 #define op_DIAGNOSE1    0061022     //!< write two different accus in fast succession
107 #define op_DIAGNOSE2    0061023     //!< write Hamming code and memory
108 #define op_BITBLT       0061024     //!< bit-aligned block transfer
109 #define op_XMLDA        0061025     //!< load accu AC0 from extended memory (Alto II/XM)
110 #define op_XMSTA        0061026     //!< store accu AC0 to extended memory (Alto II/XM)
111 #define op_JSRII        0064400     //!< jump to subroutine PC relative, doubly indirect
112 #define op_JSRIS        0065000     //!< jump to subroutine AC2 relative, doubly indirect
113 #define op_CONVERT      0067000     //!< convert bitmapped font to bitmap
114 #define op_ARITH_MASK   0103400     //!< mask for arithmetic functions
115 #define op_COM          0100000     //!< one's complement
116 #define op_NEG          0100400     //!< two's complement
117 #define op_MOV          0101000     //!< accu transfer
118 #define op_INC          0101400     //!< increment
119 #define op_ADC          0102000     //!< add one's complement
120 #define op_SUB          0102400     //!< subtract by adding two's complement
121 #define op_ADD          0103000     //!< add
122 #define op_AND          0103400     //!< logical and
123 
124 #define ea_DIRECT       0000000     //!< effective address is direct
125 #define ea_INDIRECT     0002000     //!< effective address is indirect
126 #define ea_MASK         0001400     //!< mask for effective address modes
127 #define ea_PAGE0        0000000     //!< e is page 0 address
128 #define ea_PCREL        0000400     //!< e is PC + signed displacement
129 #define ea_AC2REL       0001000     //!< e is AC2 + signed displacement
130 #define ea_AC3REL       0001400     //!< e is AC3 + signed displacement
131 
132 
133 #define sh_MASK         0000300     //!< shift mode mask (do novel shifts)
134 #define sh_L            0000100     //!< rotate left through carry
135 #define sh_R            0000200     //!< rotate right through carry
136 #define sh_S            0000300     //!< swap byte halves
137 
138 #define cy_MASK         0000060     //!< carry in mode mask
139 #define cy_Z            0000020     //!< carry in is zero
140 #define cy_O            0000040     //!< carry in is one
141 #define cy_C            0000060     //!< carry in is complemented carry
142 
143 #define nl_MASK         0000010     //!< no-load mask
144 #define nl_NONE         0000010     //!< do not load DstAC nor carry
145 
146 #define sk_MASK         0000007     //!< skip mask
147 #define sk_NVR          0000000     //!< never skip
148 #define sk_SKP          0000001     //!< always skip
149 #define sk_SZC          0000002     //!< skip if carry result is zero
150 #define sk_SNC          0000003     //!< skip if carry result is non-zero
151 #define sk_SZR          0000004     //!< skip if 16-bit result is zero
152 #define sk_SNR          0000005     //!< skip if 16-bit result is non-zero
153 #define sk_SEZ          0000006     //!< skip if either result is zero
154 #define sk_SBN          0000007     //!< skip if both results are non-zero
155 
156 /**
157  * @brief register selection
158  *
159  * <PRE>
160  * From the schematics: 08_ALU, page 6 (PDF page 4)
161  *
162  * EMACT            emulator task active
163  * F2[0-2]=111b     <-ACSOURCE and F2_17
164  * F2[0-2]=101b     DNS<- and ACDEST<-
165  *
166  *  u49 (8 input NAND 74S30)
167  *  ----------------------------------------------
168  *  F2[0] & F2[2] & F2[1]' & IR[03]' & EMACT
169  *
170  *      F2[0-2] IR[03]  EMACT   output u49pin8
171  *      --------------------------------------
172  *      101     0       1       0
173  *      all others              1
174  *
175  *
176  *  u59 (8 input NAND 74S30)
177  *  ----------------------------------------------
178  *  F2[0] & F2[2] & F2[1] & IR[01]' & EMACT
179  *
180  *      F2[0-2] IR[01] EMACT    output u59pin8
181  *      --------------------------------------
182  *      111     0      1        0
183  *      all others              1
184  *
185  *  u70d (2 input NOR 74S02 used as inverter)
186  *  ---------------------------------------------
187  *  RSEL3 -> RSEL3'
188  *
189  *  u79b (3 input NAND 74S10)
190  *  ---------------------------------------------
191  *      u49pin8 u59pin8 RSEL3'  output 6RA3
192  *      -------------------------------------
193  *      1       1       1       0
194  *      0       x       x       1
195  *      x       0       x       1
196  *      x       x       0       1
197  *
198  *
199  *  u60 (8 input NAND 74S30)
200  *  ----------------------------------------------
201  *  F2[0] & F2[2] & F2[1]' & IR[02]' & EMACT
202  *
203  *      F2[0-2] IR[02]  EMACT   output u60pin8
204  *      --------------------------------------
205  *      101     0       1       0
206  *      all others              1
207  *
208  *  u50 (8 input NAND 74S30)
209  *  ----------------------------------------------
210  *  F2[0] & F2[2] & F2[1] & IR[04]' & EMACT
211  *
212  *      F2[0-2] IR[04]  EMACT   output u50pin8
213  *      --------------------------------------
214  *      111     0       1       0
215  *      all others              1
216  *
217  *  u70c (2 input NOR 74S02 used as inverter)
218  *  ---------------------------------------------
219  *  RSEL4 -> RSEL4'
220  *
221  *
222  *  u79c (3 input NAND 74S10)
223  *  ---------------------------------------------
224  *  u60pin8 u50pin8 RSEL4'  output 8RA4
225  *  -------------------------------------
226  *  1       1       1       0
227  *  0       x       x       1
228  *  x       0       x       1
229  *  x       x       0       1
230  *
231  * BUG?: schematics seem to have swapped IR(04)' and IR(02)' inputs for the
232  * RA4 decoding, because SrcAC is selected from IR[1-2]?
233  * </PRE>
234  */
235 
236 /**
237  * @brief bs_disp early: drive bus by IR[8-15], possibly sign extended
238  *
239  * The high order bits of IR cannot be read directly, but the
240  * displacement field of IR (8 low order bits) may be read with
241  * the <-DISP bus source. If the X field of the instruction is
242  * zero (i.e., it specifies page 0 addressing), then the DISP
243  * field of the instruction is put on BUS[8-15] and BUS[0-7]
244  * is zeroed. If the X field of the instruction is non-zero
245  * (i.e. it specifies PC-relative or base-register addressing)
246  * then the DISP field is sign-extended and put on the bus.
247  *
248  */
bs_early_emu_disp()249 void alto2_cpu_device::bs_early_emu_disp()
250 {
251 	uint16_t r = IR_DISP(m_emu.ir);
252 	if (IR_X(m_emu.ir)) {
253 		r = ((signed char)r) & 0177777;
254 	}
255 	LOG((this,LOG_EMU,2, "   <-DISP (%06o)\n", r));
256 	m_bus &= r;
257 }
258 
259 /**
260  * @brief f1_block early: block task
261  *
262  * The task request for the active task is cleared
263  */
f1_early_emu_block()264 void alto2_cpu_device::f1_early_emu_block()
265 {
266 #if 0
267 	CPU_CLR_TASK_WAKEUP(m_task);
268 	LOG((this,LOG_EMU,2, "   BLOCK %02o:%s\n", m_task, task_name(m_task)));
269 #elif   0
270 	throw emu_fatalerror(1, "Emulator task want's to BLOCK.\n" \
271 			"%s-%04o: r:%02o af:%02o bs:%02o f1:%02o f2:%02o" \
272 			" t:%o l:%o next:%05o next2:%05o cycle:%lld\n",
273 			task_name(m_task), m_mpc,
274 			m_rsel, m_daluf, m_dbs, m_df1, mdf2,
275 			m_dloadt, m_dloatl, m_next, m_next2,
276 			ntime() / CPU_MICROCYCLE_TIME);
277 #else
278 	/* just ignore (?) */
279 #endif
280 }
281 
282 /**
283  * @brief f1_load_rmr late: load the reset mode register
284  */
f1_late_emu_load_rmr()285 void alto2_cpu_device::f1_late_emu_load_rmr()
286 {
287 	LOG((this,LOG_EMU,2,"    RMR<-; BUS (%#o)\n", m_bus));
288 	m_reset_mode = m_bus;
289 }
290 
291 /**
292  * @brief f1_load_esrb late: load the extended S register bank from BUS[12-14]
293  */
f1_late_emu_load_esrb()294 void alto2_cpu_device::f1_late_emu_load_esrb()
295 {
296 	LOG((this,LOG_EMU,2,"    ESRB<-; BUS[12-14] (%#o)\n", m_bus));
297 	m_s_reg_bank[m_task] = X_RDBITS(m_bus,16,12,14);
298 }
299 
300 /**
301  * @brief f1_rsnf early: drive the bus from the Ethernet node ID
302  *
303  * TODO: move this to the Ethernet code? It's really a emulator
304  * specific function that is decoded by the Ethernet card.
305  */
f1_early_rsnf()306 void alto2_cpu_device::f1_early_rsnf()
307 {
308 	uint16_t r = 0177400 | m_ether_id;
309 	LOG((this,LOG_EMU,2,"    <-RSNF; (%#o)\n", r));
310 	m_bus &= r;
311 }
312 
313 /**
314  * @brief f1_startf early: defines commands for for I/O hardware, including Ethernet
315  * <PRE>
316  * (SIO) Start I/O is included to facilitate I/O control, It places the contents of
317  * AC0 on the processor bus and executes the STARTF function (F1 = 17B). By convention,
318  * bits of AC0 must be "1" in order to signal devices. See Appendix C for a summary of
319  * assigned bits.
320  *    Bit 0  100000B   Standard Alto: Software boot feature
321  *    Bit 14 000002B   Standard Alto: Ethernet
322  *    Bit 15 000001B   Standard Alto: Ethernet
323  * If bit 0 of AC0 is 1, and if an Ethernet board is plugged into the Alto, the machine
324  * will boot, just as if the "boot button" were pressed (see sections 3.4, 8.4 and 9.2.2
325  * for discussions of bootstrapping).
326  *
327  * SIO also returns a result in AC0. If the Ethernet hardware is installed, the serial
328  * number and/or Ethernet host address of the machine (0-377B) is loaded into AC0[8-15].
329  * (On Alto I, the serial number and Ethernet host address are equivalent; on Alto II,
330  * the value loaded into AC0 is the Ethernet host address only.) If Ethernet hardware
331  * is missing, AC0[8-15] = 377B. Microcode installed after June 1976, which this manual
332  * describes, returns AC0[0] = 0. Microcode installed prior to June 1976 returns
333  * AC0[0] = 1; this is a quick way to acquire the approximate vintage of a machine's
334  * microcode.
335  * </PRE>
336  *
337  * TODO: move this to the Ethernet code? It's really a emulator
338  * specific function that is decoded by the Ethernet card.
339  */
f1_early_startf()340 void alto2_cpu_device::f1_early_startf()
341 {
342 	LOG((this,LOG_EMU,2,"    STARTF (BUS is %06o)\n", m_bus));
343 	/* TODO: what do we do here? reset the CPU on bit 0? */
344 	if (X_BIT(m_bus,16,0)) {
345 		LOG((this,LOG_EMU,2,"****    Software boot feature\n"));
346 		soft_reset();
347 	} else {
348 		LOG((this,LOG_EMU,2,"****    Ethernet start function\n"));
349 		eth_startf();
350 	}
351 }
352 
353 /**
354  * @brief branch on odd bus
355  */
f2_late_busodd()356 void alto2_cpu_device::f2_late_busodd()
357 {
358 	uint16_t r = m_bus & 1;
359 	LOG((this,LOG_EMU,2,"    BUSODD; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
360 	m_next2 |= r;
361 }
362 
363 /**
364  * @brief f2_magic late: shift and use T[0] or T[15] for bit 15 or 0
365  */
f2_late_magic()366 void alto2_cpu_device::f2_late_magic()
367 {
368 	int XC;
369 	switch (f1()) {
370 	case f1_l_lsh_1:    // <-L MLSH 1
371 		XC = (m_t >> 15) & 1;
372 		m_shifter = (m_l << 1) | XC;
373 		LOG((this,LOG_EMU,2,"    <-L MLSH 1 (shifer:%06o XC:%o)", m_shifter, XC));
374 		break;
375 	case f1_l_rsh_1:    // <-L MRSH 1
376 		XC = (m_t & 1) << 15;
377 		m_shifter = (m_l >> 1) | XC;
378 		LOG((this,LOG_EMU,2,"    <-L MRSH 1 (shifter:%06o XC:%o)", m_shifter, XC));
379 		break;
380 	case f1_l_lcy_8:    // <-L LCY 8
381 		m_shifter = (m_l >> 8) | (m_l << 8);
382 		break;
383 	default:            // other
384 		m_shifter = m_l;
385 		break;
386 	}
387 }
388 
389 /**
390  * @brief do novel shifts: modify RESELECT with DstAC = (3 - IR[3-4])
391  */
f2_early_load_dns()392 void alto2_cpu_device::f2_early_load_dns()
393 {
394 	X_WRBITS(m_rsel, 5, 3, 4, IR_DstAC(m_emu.ir) ^ 3);
395 	LOG((this,LOG_EMU,2,"    DNS<-; rsel := DstAC (%#o %s)\n", m_rsel, r_name(m_rsel)));
396 }
397 
398 /**
399  * @brief do novel shifts
400  *
401  * <PRE>
402  * New emulator carry is selected by instruction register
403  * bits CY = IR[10-11]. R register and emulator carry are
404  * loaded only if NL = IR[12] is 0 (NL = no load).
405  * SKIP is set according to SK = IR[13-15].
406  *
407  *  CARRY     = !m_emu.cy
408  *  exorB     = IR11 ^ IR10
409  *  ORA       = !(exorB | CARRY)
410  *            = (exorB | CARRY) ^ 1
411  *  exorC     = ORA ^ !IR11
412  *            = ORA ^ IR11 ^ 1
413  *  exorD     = exorC ^ LALUC0
414  *  XC        = !(!(DNS & exorD) & !(MAGIC & OUTza))
415  *            = (DNS & exorD) | (MAGIC & OUTza)
416  *            = exorD, because this is DNS
417  *  NEWCARRY  = [XC, L(00), L(15), XC] for F1 = no shift, <-L RSH 1, <-L LSH 1, LCY 8
418  *  SHZERO    = shifter == 0
419  *  DCARRY    = !((!IR12 & NEWCARRY) | (IR12 & CARRY))
420  *            = (((IR12 ^ 1) & NEWCARRY) | (IR12 & CARRY)) ^ 1
421  *  DSKIP     = !((!NEWCARRY & IR14) | (SHZERO & IR13)) ^ !IR15
422  *            = ((((NEWCARRY ^ 1) & IR14) | (SHZERO & IR13)) ^ 1) ^ (IR15 ^ 1)
423  *            = (((NEWCARRY ^ 1) & IR14) | (SHZERO & IR13)) ^ IR15
424  * </PRE>
425  */
f2_late_load_dns()426 void alto2_cpu_device::f2_late_load_dns()
427 {
428 	uint8_t IR10 = X_BIT(m_emu.ir,16,10);
429 	uint8_t IR11 = X_BIT(m_emu.ir,16,11);
430 	uint8_t IR12 = X_BIT(m_emu.ir,16,12);
431 	uint8_t IR13 = X_BIT(m_emu.ir,16,13);
432 	uint8_t IR14 = X_BIT(m_emu.ir,16,14);
433 	uint8_t IR15 = X_BIT(m_emu.ir,16,15);
434 	uint8_t exorB = IR11 ^ IR10;
435 	uint8_t CARRY = m_emu.cy ^ 1;
436 	uint8_t ORA = (exorB | CARRY) ^ 1;
437 	uint8_t exorC = ORA ^ (IR11 ^ 1);
438 	uint8_t exorD = exorC ^ m_laluc0;
439 	uint8_t XC = exorD;
440 	uint8_t NEWCARRY;
441 	uint8_t DCARRY;
442 	uint8_t DSKIP;
443 	uint8_t SHZERO;
444 
445 	switch (f1()) {
446 	case f1_l_rsh_1:    // <-L RSH 1
447 		NEWCARRY = m_l & 1;
448 		m_shifter = ((m_l >> 1) | (XC << 15)) & 0177777;
449 		LOG((this,LOG_EMU,2,"    DNS; <-L RSH 1 (shifter:%06o XC:%o NEWCARRY:%o)", m_shifter, XC, NEWCARRY));
450 		break;
451 	case f1_l_lsh_1:    // <-L LSH 1
452 		NEWCARRY = (m_l >> 15) & 1;
453 		m_shifter = ((m_l << 1) | XC) & 0177777;
454 		LOG((this,LOG_EMU,2,"    DNS; <-L LSH 1 (shifter:%06o XC:%o NEWCARRY:%o)", m_shifter, XC, NEWCARRY));
455 		break;
456 	case f1_l_lcy_8:    // <-L LCY 8
457 		NEWCARRY = XC;
458 		m_shifter = (m_l >> 8) | (m_l << 8);
459 		LOG((this,LOG_EMU,2,"    DNS; (shifter:%06o NEWCARRY:%o)", m_shifter, NEWCARRY));
460 		break;
461 	default:            // other
462 		NEWCARRY = XC;
463 		m_shifter = m_l;
464 		LOG((this,LOG_EMU,2,"    DNS; (shifter:%06o NEWCARRY:%o)", m_shifter, NEWCARRY));
465 		break;
466 	}
467 	SHZERO = (m_shifter == 0);
468 	DCARRY = (((IR12 ^ 1) & NEWCARRY) | (IR12 & CARRY)) ^ 1;
469 	DSKIP = (((NEWCARRY ^ 1) & IR14) | (SHZERO & IR13)) ^ IR15;
470 
471 	m_emu.cy = DCARRY;      // DCARRY is latched as new m_emu.cy
472 	m_emu.skip = DSKIP;     // DSKIP is latched as new m_emu.skip
473 
474 	/* !(IR12 & DNS) -> WR' = 0 for the register file */
475 	if (!IR12) {
476 		m_r[m_rsel] = m_shifter;
477 	}
478 }
479 
480 /**
481  * @brief destiantion accu: modify RSELECT with DstAC = (3 - IR[3-4])
482  */
f2_early_acdest()483 void alto2_cpu_device::f2_early_acdest()
484 {
485 	X_WRBITS(m_rsel, 5, 3, 4, IR_DstAC(m_emu.ir) ^ 3);
486 	LOG((this,LOG_EMU,2,"    ACDEST<-; mux (rsel:%#o %s)\n", m_rsel, r_name(m_rsel)));
487 }
488 
489 #if ALTO2_DEBUG
bitblt_info()490 void alto2_cpu_device::bitblt_info()
491 {
492 	static char const *const type_name[4] = {"bitmap","complement","and gray","gray"};
493 	static char const *const oper_name[4] = {"replace","paint","invert","erase"};
494 	int bbt = m_r[rsel_ac2];
495 	int val = debug_read_mem(bbt);
496 
497 	LOG((this,LOG_EMU,3,"    BITBLT AC1:%06o AC2:%06o\n", m_r[rsel_ac1], m_r[rsel_ac2]));
498 	LOG((this,LOG_EMU,3,"        function  : %06o\n", val));
499 	LOG((this,LOG_EMU,3,"            src extRAM: %o\n", X_BIT(val,16,10)));
500 	LOG((this,LOG_EMU,3,"            dst extRAM: %o\n", X_BIT(val,16,11)));
501 	LOG((this,LOG_EMU,3,"            src type  : %o (%s)\n", X_RDBITS(val,16,12,13), type_name[X_RDBITS(val,16,12,13)]));
502 	LOG((this,LOG_EMU,3,"            operation : %o (%s)\n", X_RDBITS(val,16,14,15), oper_name[X_RDBITS(val,16,14,15)]));
503 	val = debug_read_mem(bbt+1);
504 	LOG((this,LOG_EMU,3,"        unused AC2: %06o (%d)\n", val, val));
505 	val = debug_read_mem(bbt+2);
506 	LOG((this,LOG_EMU,3,"        DBCA      : %06o (%d)\n", val, val));
507 	val = debug_read_mem(bbt+3);
508 	LOG((this,LOG_EMU,3,"        DBMR      : %06o (%d words)\n", val, val));
509 	val = debug_read_mem(bbt+4);
510 	LOG((this,LOG_EMU,3,"        DLX       : %06o (%d bits)\n", val, val));
511 	val = debug_read_mem(bbt+5);
512 	LOG((this,LOG_EMU,3,"        DTY       : %06o (%d scanlines)\n", val, val));
513 	val = debug_read_mem(bbt+6);
514 	LOG((this,LOG_EMU,3,"        DW        : %06o (%d bits)\n", val, val));
515 	val = debug_read_mem(bbt+7);
516 	LOG((this,LOG_EMU,3,"        DH        : %06o (%d scanlines)\n", val, val));
517 	val = debug_read_mem(bbt+8);
518 	LOG((this,LOG_EMU,3,"        SBCA      : %06o (%d)\n", val, val));
519 	val = debug_read_mem(bbt+9);
520 	LOG((this,LOG_EMU,3,"        SBMR      : %06o (%d words)\n", val, val));
521 	val = debug_read_mem(bbt+10);
522 	LOG((this,LOG_EMU,3,"        SLX       : %06o (%d bits)\n", val, val));
523 	val = debug_read_mem(bbt+11);
524 	LOG((this,LOG_EMU,3,"        STY       : %06o (%d scanlines)\n", val, val));
525 	LOG((this,LOG_EMU,3,"        GRAY0-3   : %06o %06o %06o %06o\n",
526 		debug_read_mem(bbt+12), debug_read_mem(bbt+13),
527 		debug_read_mem(bbt+14), debug_read_mem(bbt+15)));
528 }
529 #endif  /* DEBUG */
530 
531 /**
532  * @brief load instruction register IR and branch on IR[0,5-7]
533  *
534  * Loading the IR clears the skip latch.
535  */
f2_late_load_ir()536 void alto2_cpu_device::f2_late_load_ir()
537 {
538 	uint16_t r = (X_BIT(m_bus,16,0) << 3) | X_RDBITS(m_bus,16,5,7);
539 
540 #if ALTO2_DEBUG
541 	/* special logging of some opcodes */
542 	switch (m_bus) {
543 	case op_CYCLE:
544 		LOG((this,LOG_EMU,3,"    CYCLE AC0:#o\n", m_r[rsel_ac0]));
545 		break;
546 	case op_CYCLE + 1: case op_CYCLE + 2: case op_CYCLE + 3: case op_CYCLE + 4:
547 	case op_CYCLE + 5: case op_CYCLE + 6: case op_CYCLE + 7: case op_CYCLE + 8:
548 	case op_CYCLE + 9: case op_CYCLE +10: case op_CYCLE +11: case op_CYCLE +12:
549 	case op_CYCLE +13: case op_CYCLE +14: case op_CYCLE +15:
550 		LOG((this,LOG_EMU,3,"    CYCLE %#o\n", m_bus - op_CYCLE));
551 		break;
552 	case op_BLT:
553 		LOG((this,LOG_EMU,3,"    BLT dst:%#o src:%#o size:%#o\n",
554 			(m_r[rsel_ac1] + m_r[rsel_ac3] + 1) & 0177777,
555 			(m_r[rsel_ac0] + 1) & 017777, -m_r[rsel_ac3] & 0177777));
556 		break;
557 	case op_BLKS:
558 		LOG((this,LOG_EMU,3,"    BLKS dst:%#o val:%#o size:%#o\n",
559 			(m_r[rsel_ac1] + m_r[rsel_ac3] + 1) & 0177777,
560 			m_r[rsel_ac0], -m_r[rsel_ac3] & 0177777));
561 		break;
562 	case op_DIAGNOSE1:
563 		LOG((this,LOG_EMU,3,"    DIAGNOSE1 AC0:%06o AC1:%06o AC2:%06o AC3:%06o\n",
564 			m_r[rsel_ac0], m_r[rsel_ac1],
565 			m_r[rsel_ac2], m_r[rsel_ac3]));
566 		break;
567 	case op_DIAGNOSE2:
568 		LOG((this,LOG_EMU,3,"    DIAGNOSE2 AC0:%06o AC1:%06o AC2:%06o AC3:%06o\n",
569 			m_r[rsel_ac0], m_r[rsel_ac1],
570 			m_r[rsel_ac2], m_r[rsel_ac3]));
571 		break;
572 	case op_BITBLT:
573 		bitblt_info();
574 		break;
575 	case op_RDRAM:
576 		LOG((this,LOG_EMU,3,"    RDRAM addr:%#o\n", m_r[rsel_ac1]));
577 		break;
578 	case op_WRTRAM:
579 		LOG((this,LOG_EMU,3,"    WRTAM addr:%#o upper:%06o lower:%06o\n", m_r[rsel_ac1], m_r[rsel_ac0], m_r[rsel_ac3]));
580 		break;
581 	case op_JMPRAM:
582 		LOG((this,LOG_EMU,3,"    JMPRAM addr:%#o\n", m_r[rsel_ac1]));
583 		break;
584 	case op_XMLDA:
585 		LOG((this,LOG_EMU,3,"    XMLDA AC0 = [bank:%o AC1:#o]\n", m_bank_reg[m_task] & 3, m_r[rsel_ac1]));
586 		break;
587 	case op_XMSTA:
588 		LOG((this,LOG_EMU,3,"    XMSTA [bank:%o AC1:#o] = AC0 (%#o)\n", m_bank_reg[m_task] & 3, m_r[rsel_ac1], m_r[rsel_ac0]));
589 		break;
590 	}
591 #endif
592 	m_emu.ir = m_bus;
593 	m_emu.skip = 0;
594 	m_next2 |= r;
595 }
596 
597 
598 /**
599  * @brief branch on: arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
600  */
f2_late_idisp()601 void alto2_cpu_device::f2_late_idisp()
602 {
603 	uint16_t r;
604 
605 	if (IR_ARITH(m_emu.ir)) {
606 		/* 1xxxxxxxxxxxxxxx */
607 		r = IR_SH(m_emu.ir) ^ 3;            /* complement of SH */
608 		LOG((this,LOG_EMU,2,"    IDISP<-; branch on SH^3 (%#o|%#o)\n", m_next2, r));
609 	} else {
610 		//int addr = CTL2K_U3(f2_emu_idisp) + X_RDBITS(m_emu.ir,16,1,7);
611 		// The above line triggers the following warning in PVS-Studio:
612 		// V501: There are identical sub-expressions to the left and to the right of the '==' operator: f2_emu_idisp == f2_emu_idisp
613 		// This is because CTL2K_U3(f2) checks f2 == f2_emu_idisp, and so will always evaluate to true in this case.
614 		// Consider checking if this is a typo or if it is correct.
615 		int addr = 0x80 + X_RDBITS(m_emu.ir,16,1,7);
616 		/* 0???????xxxxxxxx */
617 		r = m_ctl2k_u3[addr];
618 		LOG((this,LOG_EMU,2,"    IDISP<-; IR (%#o) branch on PROM ctl2k_u3[%03o] (%#o|%#o)\n", m_emu.ir, addr, m_next2, r));
619 	}
620 	m_next2 |= r;
621 }
622 
623 /**
624  * @brief source accu: modify RSELECT with SrcAC = (3 - IR[1-2])
625  */
f2_early_acsource()626 void alto2_cpu_device::f2_early_acsource()
627 {
628 	X_WRBITS(m_rsel, 5, 3, 4, IR_SrcAC(m_emu.ir) ^ 3);
629 	LOG((this,LOG_EMU,2,"    <-ACSOURCE; rsel := SrcAC (%#o %s)\n", m_rsel, r_name(m_rsel)));
630 }
631 
632 /**
633  * @brief branch on: arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
634  */
f2_late_acsource()635 void alto2_cpu_device::f2_late_acsource()
636 {
637 	uint16_t r;
638 
639 	if (IR_ARITH(m_emu.ir)) {
640 		/* 1xxxxxxxxxxxxxxx */
641 		r = IR_SH(m_emu.ir) ^ 3;            /* complement of SH */
642 		LOG((this,LOG_EMU,2,"    <-ACSOURCE; branch on SH^3 (%#o|%#o)\n", m_next2, r));
643 	} else {
644 		int addr = CTL2K_U3(f2_emu_acsource) + X_RDBITS(m_emu.ir,16,1,7);
645 		/* 0???????xxxxxxxx */
646 		r = m_ctl2k_u3[addr];
647 		LOG((this,LOG_EMU,2,"    <-ACSOURCE; branch on PROM ctl2k_u3[%03o] (%#o|%#o)\n", addr, m_next2, r));
648 	}
649 	m_next2 |= r;
650 }
651 
init_emu(int task)652 void alto2_cpu_device::init_emu(int task)
653 {
654 	memset(&m_emu, 0, sizeof(m_emu));
655 	save_item(NAME(m_emu.ir));
656 	save_item(NAME(m_emu.skip));
657 	save_item(NAME(m_emu.cy));
658 
659 	init_ram(task);
660 }
661 
exit_emu()662 void alto2_cpu_device::exit_emu()
663 {
664 	// nothing to do yet
665 }
666 
reset_emu()667 void alto2_cpu_device::reset_emu()
668 {
669 	m_emu.ir = 0;
670 	m_emu.skip = 0;
671 	m_emu.cy = 0;
672 }
673