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