Previous 199869 Revisions Next

r26287 Tuesday 19th November, 2013 at 21:58:55 UTC by Jürgen Buchmüller
Use picoseconds integers for the CPU in-execution-loop timing.
[/branches/alto2/src/emu/cpu]cpu.mak
[/branches/alto2/src/emu/cpu/alto2]a2curt.c a2dht.c a2disk.c a2disp.c a2dvt.c a2dwt.c a2emu.c a2ether.c a2hw.c a2kbd.c a2ksec.c a2kwd.c a2mem.c a2mouse.c a2mrt.c a2part.c a2ram.c a2roms.c alto2.c alto2.h alto2cpu.c* alto2cpu.h* alto2dsm.c
[/branches/alto2/src/mess/drivers]alto2.c
[/branches/alto2/src/mess/includes]alto2.h

branches/alto2/src/emu/cpu/alto2/alto2.h
r26286r26287
1/*****************************************************************************
2 *
3 *   Portable Xerox AltoII CPU core interface
4 *
5 *   Copyright: Juergen Buchmueller <pullmoll@t-online.de>
6 *
7 *   Licenses: MAME, GPLv2
8 *
9 *****************************************************************************/
10#include "emu.h"
11#include "debugger.h"
12
13#pragma once
14
15#ifndef _CPU_ALTO2_H_
16#define _CPU_ALTO2_H
17
18#include "machine/diablo_hd.h"
19
20#define   ALTO2_TAG "alto2"
21
22#ifndef   ALTO2_DEBUG
23#define   ALTO2_DEBUG             0   //!< define to 1 to enable logerror() output
24#endif
25
26#define   USE_PRIO_F9318         0   //!< define to 1 to use the F9318 priority encoder code
27#define   USE_ALU_74181         1   //!< define to 1 to use the SN74181 ALU code
28#define   DEBUG_DISPLAY_TIMING   0   //!< define to 1 to debug the display timing
29#define   USE_BITCLK_TIMER      0   //!< define to 1 to use a very high rate timer for the disk bit clock
30#define   ALTO2_HAMMING_CHECK      0   //!< define to 1 to incorporate the Hamming code and Parity check
31
32#define   ALTO2_TASKS      16         //!< 16 task slots
33#define   ALTO2_REGS      32         //!< 32 16-bit words in the R register file
34#define   ALTO2_ALUF      16         //!< 16 ALU functions (74181)
35#define   ALTO2_BUSSRC   8         //!< 8 bus sources
36#define   ALTO2_F1MAX      16         //!< 16 F1 functions
37#define   ALTO2_F2MAX      16         //!< 16 F2 functions
38#define   ALTO2_UCYCLE   169         //!< time in nano seconds for a CPU micro cycle: 29.4912MHz/5 -> 5.898240Hz ~= 169.542ns/clock
39
40#define   ALTO2_ETHER_FIFO_SIZE   16
41
42#ifndef   ALTO2_CRAM_CONFIG
43#define   ALTO2_CRAM_CONFIG   2      //!< use default configuration 2
44#endif
45
46#if   (ALTO2_CRAM_CONFIG==1)
47#define   ALTO2_UCODE_ROM_PAGES   1      //!< number of microcode ROM pages
48#define   ALTO2_UCODE_RAM_PAGES   1      //!< number of microcode RAM pages
49#elif (ALTO2_CRAM_CONFIG==2)
50#define   ALTO2_UCODE_ROM_PAGES   2      //!< number of microcode ROM pages
51#define   ALTO2_UCODE_RAM_PAGES   1      //!< number of microcode RAM pages
52#elif (ALTO2_CRAM_CONFIG==3)
53#define   ALTO2_UCODE_ROM_PAGES   1      //!< number of microcode ROM pages
54#define   ALTO2_UCODE_RAM_PAGES   3      //!< number of microcode RAM pages
55#else
56#error "Undefined CROM/CRAM configuration"
57#endif
58
59/**
60 * \brief number of S register banks
61 * This depends on the number of RAM pages
62 *   8 pages in 3K CRAM configuration
63 *   1 page in 1K CRAM configurations
64 */
65#if   (ALTO2_UCODE_RAM_PAGES == 3)
66#define   ALTO2_SREG_BANKS   8
67#else
68#define   ALTO2_SREG_BANKS   1
69#endif
70
71#define   ALTO2_UCODE_PAGE_SIZE   1024                  //!< number of words of microcode
72#define   ALTO2_UCODE_PAGE_MASK   (ALTO2_UCODE_PAGE_SIZE-1)   //!< mask for microcode ROM/RAM address
73#define   ALTO2_UCODE_SIZE      ((ALTO2_UCODE_ROM_PAGES + ALTO2_UCODE_RAM_PAGES) * ALTO2_UCODE_PAGE_SIZE)   //!< total number of words of microcode
74#define   ALTO2_UCODE_RAM_BASE   (ALTO2_UCODE_ROM_PAGES * ALTO2_UCODE_PAGE_SIZE)   //!< base offset for the RAM page(s)
75#define   ALTO2_CONST_SIZE      256                     //!< number words in the constant ROM
76#define   ALTO2_RAM_SIZE         0200000                  //!< size of main memory in words
77#define   ALTO2_IO_PAGE_BASE      0177000                  //!< base address of the memory mapped io range
78#define   ALTO2_IO_PAGE_SIZE      01000                  //!< size of the memory mapped io range
79
80//! inverted bits in the micro instruction 32 bit word
81#define   ALTO2_UCODE_INVERTED   ((1 << 10) | (1 << 15) | (1 << 19))
82
83/**
84 * @brief start value for the horizontal line counter
85 *
86 * This value is loaded into the three 4 bit counters (type 9316)
87 * with numbers 65, 67, and 75.
88 * 65: A=0 B=1 C=1 D=0
89 * 67: A=1 B=0 C=0 D=1
90 * 75: A=0 B=0 C=0 D=0
91 *
92 * The value is 150
93 */
94#define   ALTO2_DISPLAY_HLC_START (2+4+16+128)
95
96/**
97 * @brief end value for the horizontal line counter
98 *
99 * This is decoded by H30, an 8 input NAND gate.
100 * The value is 1899; horz. line count range 150…1899 = 1750.
101 *
102 * There are 1750 / 2 = 875 total scanlines.
103 */
104#define   ALTO2_DISPLAY_HLC_END (1+2+8+32+64+256+512+1024)
105
106/**
107 * @brief display total height, including overscan (vertical blanking and synch)
108 *
109 * The display is interleaved in two fields, alternatingly drawing the even and odd
110 * scanlines to the monitor. The frame rate is 60Hz, which is actually the rate
111 * of the half-frames. The rate for full frames is thus 30Hz.
112 */
113#define   ALTO2_DISPLAY_TOTAL_HEIGHT ((ALTO2_DISPLAY_HLC_END + 1 - ALTO2_DISPLAY_HLC_START) / 2)
114
115/**
116 * @brief display total width, including horizontal blanking
117 *
118 * Known facts:
119 *
120 * We have 606x808 visible pixels, and the pixel clock is said to be 50ns
121 * (20MHz), while the crystal in the schematics is labeled 20.16 MHz,
122 * so the pixel clock would actually be 49.6031ns.
123 *
124 * The total number of scanlines is, according to the docs, 875.
125 *
126 * 875 scanlines at 30 frames per second, thus the scanline rate is 26.250 kHz.
127 *
128 * If I divide 20.16 MHz by 26.250 kHz, I get 768 pixels for the total width
129 * of a scanline in pixels.
130 *
131 * The horizontal blanking period would then be 768 - 606 = 162 pixels, and
132 * thus 162 * 49.6031ns ~= 8036ns = 8.036us for the HBLANK time.
133 *
134 * In the display schematics there is a divide by 24 logic, and when
135 * dividing the 768 pixels per scanline by 24, we have 32 phases of a scanline.
136 *
137 * A S8223 PROM (a63) with 32x8 bits contains the status of the HBLANK and
138 * HSYNC signals for these phases, the SCANEND and HLCGATE signals, as well
139 * as its own next address A0-A3!
140 *
141 */
142#define   ALTO2_DISPLAY_TOTAL_WIDTH 768
143
144
145#define   ALTO2_DISPLAY_SCANLINE_WORDS (ALTO2_DISPLAY_TOTAL_WIDTH/16)      //!< words per scanline
146#define   ALTO2_DISPLAY_HEIGHT 808                              //!< number of visible scanlines per frame; 808 really, but there are some empty lines?
147#define   ALTO2_DISPLAY_WIDTH 606                                 //!< visible width of the display; 38 words - 2 pixels
148#define   ALTO2_DISPLAY_VISIBLE_WORDS ((ALTO2_DISPLAY_WIDTH+15)/16)      //!< visible words per scanline
149#define   ALTO2_DISPLAY_BITCLOCK 20160000ll                        //!< display bit clock in in Hertz (20.16MHz)
150#define   ALTO2_DISPLAY_BITTIME(n) ((n)*U64(1000000000)/ALTO2_DISPLAY_BITCLOCK)   //!< display bit time in in atto seconds (~= 49.6031ns)
151#define   ALTO2_DISPLAY_SCANLINE_TIME   ALTO2_DISPLAY_BITTIME(ALTO2_DISPLAY_TOTAL_WIDTH)   //!< time for a scanline in nano seconds (768 * 49.6031ns)
152#define   ALTO2_DISPLAY_VISIBLE_TIME ALTO2_DISPLAY_BITTIME(ALTO2_DISPLAY_WIDTH)   //!< time of the visible part of a scanline (606 * 49.6031ns)
153#define   ALTO2_DISPLAY_WORD_TIME   ALTO2_DISPLAY_BITTIME(16)            //!< time for a word (16 pixels * 49.6031ns)
154#define   ALTO2_DISPLAY_VBLANK_TIME ((ALTO2_DISPLAY_TOTAL_HEIGHT-ALTO2_DISPLAY_HEIGHT)*HZ_TO_ATTOSECONDS(26250))
155#define   ALTO2_DISPLAY_FIFO 16                                 //!< the display fifo has 16 words
156
157enum {
158   // micro code task, micro program counter, next and next2
159   A2_TASK, A2_MPC, A2_NEXT, A2_NEXT2,
160   // BUS, ALU, temp, latch, memory latch and carry flags
161   A2_BUS, A2_T, A2_ALU, A2_ALUC0,   A2_L, A2_SHIFTER, A2_LALUC0, A2_M,
162   // DISK controller registers
163   A2_DRIVE, A2_KADDR, A2_KADR, A2_KSTAT, A2_KCOM, A2_KRECNO,
164   A2_SHIFTIN, A2_SHIFTOUT, A2_DATAIN, A2_DATAOUT, A2_KRWC,
165   A2_KFER, A2_WDTSKENA, A2_WDINIT0, A2_WDINIT, A2_STROBE,
166   A2_BITCLK, A2_DATIN, A2_BITCNT, A2_CARRY, A2_SECLATE,
167   A2_SEEKOK, A2_OKTORUN, A2_READY,
168   A2_R,   // 32 R registers
169   A2_AC3 = A2_R, A2_AC2, A2_AC1, A2_AC0, A2_R04, A2_R05, A2_PC,  A2_R07,
170   A2_R10, A2_R11, A2_R12, A2_R13, A2_R14, A2_R15, A2_R16, A2_R17,
171   A2_R20, A2_R21, A2_R22, A2_R23, A2_R24, A2_R25, A2_R26, A2_R27,
172   A2_R30, A2_R31, A2_R32, A2_R33, A2_R34, A2_R35, A2_R36, A2_R37,
173   A2_S,   // 32 S registers
174   A2_S00 = A2_S, A2_S01, A2_S02, A2_S03, A2_S04, A2_S05, A2_S06, A2_S07,
175   A2_S10, A2_S11, A2_S12, A2_S13, A2_S14, A2_S15, A2_S16, A2_S17,
176   A2_S20, A2_S21, A2_S22, A2_S23, A2_S24, A2_S25, A2_S26, A2_S27,
177   A2_S30, A2_S31, A2_S32, A2_S33, A2_S34, A2_S35, A2_S36, A2_S37
178};
179
180/**
181 * @brief enumeration of the inputs and outputs of a JK flip-flop type 74109
182 * <PRE>
183 * 74109
184 * Dual J-/K flip-flops with set and reset.
185 *
186 *       +----------+           +-----------------------------+
187 * /1RST |1  +--+ 16| VCC       | J |/K |CLK|/SET|/RST| Q |/Q |
188 *    1J |2       15| /2RST     |---+---+---+----+----+---+---|
189 *   /1K |3       14| 2J        | X | X | X |  0 |  0 | 1 | 1 |
190 *  1CLK |4   74  13| /2K       | X | X | X |  0 |  1 | 1 | 0 |
191 * /1SET |5  109  12| 2CLK      | X | X | X |  1 |  0 | 0 | 1 |
192 *    1Q |6       11| /2SET     | 0 | 0 | / |  1 |  1 | 0 | 1 |
193 *   /1Q |7       10| 2Q        | 0 | 1 | / |  1 |  1 | - | - |
194 *   GND |8        9| /2Q       | 1 | 0 | / |  1 |  1 |/Q | Q |
195 *       +----------+           | 1 | 1 | / |  1 |  1 | 1 | 0 |
196 *                              | X | X |!/ |  1 |  1 | - | - |
197 *                              +-----------------------------+
198 *
199 * [This information is part of the GIICM]
200 * </PRE>
201 */
202typedef enum {
203   JKFF_0,               //!< no inputs or outputs
204   JKFF_CLK   = (1 << 0),   //!< clock signal
205   JKFF_J      = (1 << 1),   //!< J input
206   JKFF_K      = (1 << 2),   //!< K' input
207   JKFF_S      = (1 << 3),   //!< S' input
208   JKFF_C      = (1 << 4),   //!< C' input
209   JKFF_Q      = (1 << 5),   //!< Q  output
210   JKFF_Q0      = (1 << 6)   //!< Q' output
211}   jkff_t;
212
213class alto2_cpu_device :  public cpu_device
214{
215public:
216   // construction/destruction
217   alto2_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
218   ~alto2_cpu_device();
219
220   //! driver interface to set diablo_hd_device
221   void set_diablo(int unit, diablo_hd_device* ptr);
222
223   //! call in for the next sector callback
224   void next_sector(int unit);
225
226   //! return the display bitmap
227   bitmap_ind16& display() { return *m_displ_bitmap; }
228
229   DECLARE_ADDRESS_MAP( ucode_map, 32 );
230   DECLARE_ADDRESS_MAP( const_map, 16 );
231   DECLARE_ADDRESS_MAP( iomem_map, 16 );
232
233   //! register a mouse motion in x direction
234   DECLARE_INPUT_CHANGED_MEMBER( mouse_motion_x );
235   //! register a mouse motion in y direction
236   DECLARE_INPUT_CHANGED_MEMBER( mouse_motion_y );
237   //! register a mouse button change
238   DECLARE_INPUT_CHANGED_MEMBER( mouse_buttons );
239
240protected:
241   //! device-level override for start
242   virtual void device_start();
243   //! device-level override for reset
244   virtual void device_reset();
245
246   //! device-level override for post reset
247   void interface_post_reset();
248
249   //! device_execute_interface overrides
250   virtual UINT32 execute_min_cycles() const { return 1; }
251   virtual UINT32 execute_max_cycles() const { return 1; }
252   virtual UINT32 execute_input_lines() const { return 1; }
253   virtual void execute_run();
254   virtual void execute_set_input(int inputnum, int state);
255
256   //! device_memory_interface overrides
257   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
258
259   //! device (P)ROMs
260   virtual const rom_entry *device_rom_region() const;
261   //! device_state_interface overrides
262   void state_string_export(const device_state_entry &entry, astring &string);
263
264   //! device_disasm_interface overrides
265   virtual UINT32 disasm_min_opcode_bytes() const { return 4; }
266   virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
267   virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
268
269private:
270#if   ALTO2_DEBUG
271   enum {
272      LOG_0,
273      LOG_CPU      = (1 <<  0),
274      LOG_EMU      = (1 <<  1),
275      LOG_T01      = (1 <<  2),
276      LOG_T02      = (1 <<  3),
277      LOG_T03      = (1 <<  4),
278      LOG_KSEC   = (1 <<  5),
279      LOG_T05      = (1 <<  6),
280      LOG_T06      = (1 <<  7),
281      LOG_ETH      = (1 <<  8),
282      LOG_MRT      = (1 <<  9),
283      LOG_DWT      = (1 << 10),
284      LOG_CURT   = (1 << 11),
285      LOG_DHT      = (1 << 12),
286      LOG_DVT      = (1 << 13),
287      LOG_PART   = (1 << 14),
288      LOG_KWD      = (1 << 15),
289      LOG_T17      = (1 << 16),
290      LOG_MEM      = (1 << 17),
291      LOG_RAM      = (1 << 18),
292      LOG_DRIVE   = (1 << 19),
293      LOG_DISK   = (1 << 20),
294      LOG_DISPL   = (1 << 21),
295      LOG_MOUSE   = (1 << 22),
296      LOG_HW      = (1 << 23),
297      LOG_KBD      = (1 << 24),
298      LOG_ALL      = ((1 << 25) - 1)
299   };
300   int m_log_types;
301   int m_log_level;
302   bool m_log_newline;
303   void logprintf(int type, int level, const char* format, ...);
304#   define   LOG(x) logprintf x
305#else
306#   define   LOG(x)
307#endif
308
309   void fatal(int level, const char *format, ...);
310
311   address_space_config m_ucode_config;
312   address_space_config m_const_config;
313   address_space_config m_iomem_config;
314
315   address_space* m_iomem;
316
317   UINT8* m_ucode_crom;
318   UINT8* m_ucode_cram;
319   UINT8* m_const_data;
320
321   //! read microcode CROM
322   DECLARE_READ32_MEMBER ( crom_r );
323
324   //! read microcode CRAM
325   DECLARE_READ32_MEMBER ( cram_r );
326
327   //! write microcode CRAM
328   DECLARE_WRITE32_MEMBER( cram_w );
329
330   //! read constants PROM
331   DECLARE_READ16_MEMBER ( const_r );
332
333   //! read i/o space RAM
334   DECLARE_READ16_MEMBER ( ioram_r );
335
336   //!< write i/o space RAM
337   DECLARE_WRITE16_MEMBER( ioram_w );
338
339   //!< read memory mapped i/o
340   DECLARE_READ16_MEMBER ( mmio_r );
341
342   //!< write memory mapped i/o
343   DECLARE_WRITE16_MEMBER( mmio_w );
344
345   int m_icount;
346
347   static const UINT8 m_ether_id = 0377;
348
349   typedef void (alto2_cpu_device::*a2func)();
350   typedef void (alto2_cpu_device::*a2cb)(int unit);
351   typedef void (alto2_cpu_device::*a2io_wr)(UINT32 addr, UINT16 data);
352   typedef UINT16 (alto2_cpu_device::*a2io_rd)(UINT32 addr);
353
354   //! task numbers
355   enum {
356      task_emu,      //!< emulator task
357      task_1,         //!< unused
358      task_2,         //!< unused
359      task_3,         //!< unused
360      task_ksec,      //!< disk sector task
361      task_5,         //!< unused
362      task_6,         //!< unused
363      task_ether,      //!< ethernet task
364      task_mrt,      //!< memory refresh task
365      task_dwt,      //!< display word task
366      task_curt,      //!< cursor task
367      task_dht,      //!< display horizontal task
368      task_dvt,      //!< display vertical task
369      task_part,      //!< parity task
370      task_kwd,      //!< disk word task
371      task_17         //!< unused task slot 017
372   };
373
374   //! register select values accessing R (Note: register numbers are octal)
375   enum {
376      rsel_ac3,      //!< AC3 used by emulator as accu 3. Also used by Mesa emulator to keep bytecode to execute after breakpoint
377      rsel_ac2,      //!< AC2 used by emulator as accu 2. Also used by Mesa emulator as x register for xfer
378      rsel_ac1,      //!< AC1 used by emulator as accu 1. Also used by Mesa emulator as r-temporary for return indices and values
379      rsel_ac0,      //!< AC0 used by emulator as accu 0. Also used by Mesa emulator as new field bits for WF and friends
380      rsel_r04,      //!< NWW state of the interrupt system
381      rsel_r05,      //!< SAD. Also used by Mesa emulator as scratch R-register for counting
382      rsel_pc,      //!< PC used by emulator as program counter
383      rsel_r07,      //!< XREG. Also used by Mesa emulator as task hole, i.e. pigeonhole for saving things across tasks.
384      rsel_r10,      //!< XH. Also used by Mesa emulator as instruction byte register
385      rsel_r11,      //!< CLOCKTEMP - used in the MRT
386      rsel_r12,      //!< ECNTR remaining words in buffer - ETHERNET
387      rsel_r13,      //!< EPNTR points BEFORE next word in buffer - ETHERNET
388      rsel_r14,
389      rsel_r15,      //!< MPC. Used by the Mesa emulator as program counter
390      rsel_r16,      //!< STKP. Used by the Mesa emulator as stack pointer [0-10] 0 empty, 10 full
391      rsel_r17,      //!< XTSreg. Used by the Mesa emulator to xfer trap state
392      rsel_r20,      //!< CURX. Holds cursor X; used by the cursor task
393      rsel_r21,      //!< CURDATA. Holds the cursor data; used by the cursor task
394      rsel_r22,      //!< CBA. Holds the address of the currently active DCB+1
395      rsel_r23,      //!< AECL. Holds the address of the end of the current scanline's bitmap
396      rsel_r24,      //!< SLC. Holds the number of scanlines remaining in currently active DCB
397      rsel_r25,      //!< MTEMP. Holds the temporary cell
398      rsel_r26,      //!< HTAB. Holds the number of tab words remaining on current scanline
399      rsel_r27,      //!< YPOS
400      rsel_r30,      //!< DWA. Holds the address of the bit map doubleword currently being fetched for transmission to the hardware buffer.
401      rsel_r31,      //!< KWDCT. Used by the disk tasks as word counter
402      rsel_r32,      //!< CKSUMR. Used by the disk tasks as checksum register (and *amble counter?)
403      rsel_r33,      //!< KNMAR. Used by the disk tasks as transfer memory address register
404      rsel_r34,      //!< DCBR. Used by the disk tasks to keep the current device control block
405      rsel_r35,      //!< TEMP. Used by the Mesa emulator, and also by BITBLT
406      rsel_r36,      //!< TEMP2. Used by the Mesa emulator, and also by BITBLT
407      rsel_r37      //!< CLOCKREG. Low order bits of the real time clock
408   };
409
410   //! ALU function numbers
411   enum {
412      /**
413       * \brief 00: ALU <- BUS
414       * PROM data for S3-0,M,C: 1111/1/0
415       * function F=A
416       * T source is ALU
417       */
418      aluf_bus__alut,
419      /**
420       * \brief 01: ALU <- T
421       * PROM data for S3-0,M,C: 1010/1/0
422       * function F=B
423       * T source is BUS
424       */
425      aluf_treg,
426      /**
427       * \brief 02: ALU <- BUS | T
428       * PROM data for S3-0,M,C: 1110/1/0
429       * function F=A|B
430       * T source is ALU
431       */
432      aluf_bus_or_t__alut,
433      /**
434       * \brief 03: ALU <- BUS & T
435       * PROM data for S3-0,M,C: 1011/1/0
436       * function F=A&B
437       * T source is BUS
438       */
439      aluf_bus_and_t,
440      /**
441       * \brief 04: ALU <- BUS ^ T
442       * PROM data for S3-0,M,C: 0110/1/0
443       * function F=A^B
444       * T source is BUS
445       */
446      aluf_bus_xor_t,
447      /**
448       * \brief 05: ALU <- BUS + 1
449       * PROM data for S3-0,M,C: 0000/0/0
450       * function F=A+1
451       * T source is ALU
452       */
453      aluf_bus_plus_1__alut,
454      /**
455       * \brief 06: ALU <- BUS - 1
456       * PROM data for S3-0,M,C: 1111/0/1
457       * function F=A-1
458       * T source is ALU
459       */
460      aluf_bus_minus_1__alut,
461      /**
462       * \brief 07: ALU <- BUS + T
463       * PROM data for S3-0,M,C: 1001/0/1
464       * function F=A+B
465       * T source is BUS
466       */
467      aluf_bus_plus_t,
468      /**
469       * \brief 10: ALU <- BUS - T
470       * PROM data for S3-0,M,C: 0110/0/0
471       * function F=A-B
472       * T source is BUS
473       */
474      aluf_bus_minus_t,
475      /**
476       * \brief 11: ALU <- BUS - T - 1
477       * PROM data for S3-0,M,C: 0110/0/1
478       * function F=A-B-1
479       * T source is BUS
480       */
481      aluf_bus_minus_t_minus_1,
482      /**
483       * \brief 12: ALU <- BUS + T + 1
484       * PROM data for S3-0,M,C: 1001/0/0
485       * function F=A+B+1
486       * T source is ALU
487       */
488      aluf_bus_plus_t_plus_1__alut,
489      /**
490       * \brief 13: ALU <- BUS + SKIP
491       * PROM data for S3-0,M,C: 0000/0/SKIP
492       * function F=A (SKIP=1) or F=A+1 (SKIP=0)
493       * T source is ALU
494       */
495      aluf_bus_plus_skip__alut,
496      /**
497       * \brief 14: ALU <- BUS & T
498       * PROM data for S3-0,M,C: 1011/1/0
499       * function F=A&B
500       * T source is ALU
501       */
502      aluf_bus_and_t__alut,
503      /**
504       * \brief 15: ALU <- BUS & ~T
505       * PROM data for S3-0,M,C: 0111/1/0
506       * function F=A&~B
507       * T source is BUS
508       */
509      aluf_bus_and_not_t,
510      /**
511       * \brief 16: ALU <- ???
512       * PROM data for S3-0,M,C: ????/?/?
513       * perhaps F=0 (0011/0/0)
514       * T source is BUS
515       */
516      aluf_undef_16,
517      /**
518       * \brief 17: ALU <- ???
519       * PROM data for S3-0,M,C: ????/?/?
520       * perhaps F=0 (0011/0/0)
521       * T source is BUS
522       */
523      aluf_undef_17
524   };
525
526   //! BUS source selection numbers
527   enum {
528      bs_read_r,                     //!< BUS source is R register
529      bs_load_r,                     //!< load R register from BUS
530      bs_no_source,                  //!< BUS is open (0177777)
531      bs_task_3,                     //!< BUS source is task specific
532      bs_task_4,                     //!< BUS source is task specific
533      bs_read_md,                     //!< BUS source is memory data
534      bs_mouse,                     //!< BUS source is mouse data
535      bs_disp,                     //!< BUS source displacement
536
537      bs_ram_read_slocation= bs_task_3,   //!< ram related: read S register
538      bs_ram_load_slocation= bs_task_4,   //!< ram related: load S register
539
540      bs_emu_read_sreg   = bs_task_3,   //!< emulator task: read S register
541      bs_emu_load_sreg   = bs_task_4,   //!< emulator task: load S register from BUS
542
543      bs_ksec_read_kstat   = bs_task_3,   //!< disk sector task: read status register
544      bs_ksec_read_kdata   = bs_task_4,   //!< disk sector task: read data register
545
546      bs_ether_eidfct      = bs_task_3,   //!< ethernet task: Ethernet input data function
547
548      bs_kwd_read_kstat   = bs_task_3,   //!< disk word task: read status register
549      bs_kwd_read_kdata   = bs_task_4      //!< disk word task: read data register
550   };
551
552   //! Function 1 numbers
553   enum {
554      f1_nop,                        //!< f1 (0000) no operation
555      f1_load_mar,                  //!< f1 (0001) load memory address register
556      f1_task,                     //!< f1 (0010) task switch
557      f1_block,                     //!< f1 (0011) block task
558      f1_l_lsh_1,                     //!< f1 (0100) left shift L once
559      f1_l_rsh_1,                     //!< f1 (0101) right shift L once
560      f1_l_lcy_8,                     //!< f1 (0110) cycle L 8 times
561      f1_const,                     //!< f1 (0111) constant from PROM
562
563      f1_task_10,                     //!< f1 (1000) task specific
564      f1_task_11,                     //!< f1 (1001) task specific
565      f1_task_12,                     //!< f1 (1010) task specific
566      f1_task_13,                     //!< f1 (1011) task specific
567      f1_task_14,                     //!< f1 (1100) task specific
568      f1_task_15,                     //!< f1 (1101) task specific
569      f1_task_16,                     //!< f1 (1110) task specific
570      f1_task_17,                     //!< f1 (1111) task specific
571
572      f1_ram_swmode      = f1_task_10,   //!< f1 (1000) ram related: switch mode to CROM/CRAM in same page
573      f1_ram_wrtram      = f1_task_11,   //!< f1 (1001) ram related: start WRTRAM cycle
574      f1_ram_rdram      = f1_task_12,   //!< f1 (1010) ram related: start RDRAM cycle
575#if   (ALTO2_UCODE_RAM_PAGES == 3)
576      f1_ram_load_rmr      = f1_task_13,   //!< f1 (1011) ram related: load the reset mode register
577#else   // ALTO2_UCODE_RAM_PAGES != 3
578      f1_ram_load_srb      = f1_task_13,   //!< f1 (1011) ram related: load the S register bank from BUS[12-14]
579#endif
580
581      f1_emu_swmode      = f1_task_10,   //!< f1 (1000) emu: switch mode; branch to ROM/RAM microcode
582      f1_emu_wrtram      = f1_task_11,   //!< f1 (1001) emu: write microcode RAM
583      f1_emu_rdram      = f1_task_12,   //!< f1 (1010) emu: read microcode RAM
584      f1_emu_load_rmr      = f1_task_13,   //!< f1 (1011) emu: load reset mode register
585                                 //!< f1 (1100) emu: undefined
586      f1_emu_load_esrb   = f1_task_15,   //!< f1 (1101) emu: load extended S register bank
587      f1_emu_rsnf         = f1_task_16,   //!< f1 (1110) emu: read serial number (Ethernet ID)
588      f1_emu_startf      = f1_task_17,   //!< f1 (1111) emu: start I/O hardware (Ethernet)
589
590      f1_ksec_strobe      = f1_task_11,   //!< f1 (1001) ksec: strobe
591      f1_ksec_load_kstat   = f1_task_12,   //!< f1 (1010) ksec: load kstat register
592      f1_ksec_increcno   = f1_task_13,   //!< f1 (1011) ksec: increment record number
593      f1_ksec_clrstat      = f1_task_14,   //!< f1 (1100) ksec: clear status register
594      f1_ksec_load_kcom   = f1_task_15,   //!< f1 (1101) ksec: load kcom register
595      f1_ksec_load_kadr   = f1_task_16,   //!< f1 (1110) ksec: load kadr register
596      f1_ksec_load_kdata   = f1_task_17,   //!< f1 (1111) ksec: load kdata register
597
598      f1_ether_eilfct      = f1_task_13,   //!< f1 (1011) ether: Ethernet input look function
599      f1_ether_epfct      = f1_task_14,   //!< f1 (1100) ether: Ethernet post function
600      f1_ether_ewfct      = f1_task_15,   //!< f1 (1101) ether: Ethernet countdown wakeup function
601
602      f1_kwd_strobe      = f1_task_11,   //!< f1 (1001) kwd: strobe
603      f1_kwd_load_kstat   = f1_task_12,   //!< f1 (1010) kwd: load kstat register
604      f1_kwd_increcno      = f1_task_13,   //!< f1 (1011) kwd: increment record number
605      f1_kwd_clrstat      = f1_task_14,   //!< f1 (1100) kwd: clear status register
606      f1_kwd_load_kcom   = f1_task_15,   //!< f1 (1101) kwd: load kcom register
607      f1_kwd_load_kadr   = f1_task_16,   //!< f1 (1110) kwd: load kadr register
608      f1_kwd_load_kdata   = f1_task_17,   //!< f1 (1111) kwd: load kdata register
609   };
610
611   //! Function 2 numbers
612   enum {
613      f2_nop,                        //!< f2 00 no operation
614      f2_bus_eq_zero,                  //!< f2 01 branch on bus equals 0
615      f2_shifter_lt_zero,               //!< f2 02 branch on shifter less than 0
616      f2_shifter_eq_zero,               //!< f2 03 branch on shifter equals 0
617      f2_bus,                        //!< f2 04 branch on BUS[6-15]
618      f2_alucy,                     //!< f2 05 branch on (latched) ALU carry
619      f2_load_md,                     //!< f2 06 load memory data
620      f2_const,                     //!< f2 07 constant from PROM
621      f2_task_10,                     //!< f2 10 task specific
622      f2_task_11,                     //!< f2 11 task specific
623      f2_task_12,                     //!< f2 12 task specific
624      f2_task_13,                     //!< f2 13 task specific
625      f2_task_14,                     //!< f2 14 task specific
626      f2_task_15,                     //!< f2 15 task specific
627      f2_task_16,                     //!< f2 16 task specific
628      f2_task_17,                     //!< f2 17 task specific
629
630      f2_emu_busodd      = f2_task_10,   //!< f2 (1000) emu: branch on bus odd
631      f2_emu_magic      = f2_task_11,   //!< f2 (1001) emu: magic shifter (MRSH 1: shifter[15]=T[0], MLSH 1: shifter[015])
632      f2_emu_load_dns      = f2_task_12,   //!< f2 (1010) emu: do novel shift (RSH 1: shifter[15]=XC, LSH 1: shifer[0]=XC)
633      f2_emu_acdest      = f2_task_13,   //!< f2 (1011) emu: destination accu
634      f2_emu_load_ir      = f2_task_14,   //!< f2 (1100) emu: load instruction register and branch
635      f2_emu_idisp      = f2_task_15,   //!< f2 (1101) emu: load instruction displacement and branch
636      f2_emu_acsource      = f2_task_16,   //!< f2 (1110) emu: source accu
637
638      f2_ksec_init      = f2_task_10,   //!< f2 (1000) ksec: branches NEXT[5-9] on WDTASKACT && WDINIT
639      f2_ksec_rwc         = f2_task_11,   //!< f2 (1001) ksec: branches NEXT[8-9] on READ/WRITE/CHECK for record
640      f2_ksec_recno      = f2_task_12,   //!< f2 (1010) ksec: branches NEXT[8-9] on RECNO[0-1]
641      f2_ksec_xfrdat      = f2_task_13,   //!< f2 (1011) ksec: branches NEXT[9] on !SEEKONLY
642      f2_ksec_swrnrdy      = f2_task_14,   //!< f2 (1100) ksec: branches NEXT[9] on !SWRDY
643      f2_ksec_nfer      = f2_task_15,   //!< f2 (1101) ksec: branches NEXT[9] on !KFER
644      f2_ksec_strobon      = f2_task_16,   //!< f2 (1110) ksec: branches NEXT[9] on STROBE
645
646      f2_ether_eodfct      = f2_task_10,   //!< f2 (1000) ether: Ethernet output data function
647      f2_ether_eosfct      = f2_task_11,   //!< f2 (1001) ether: Ethernet output start function
648      f2_ether_erbfct      = f2_task_12,   //!< f2 (1010) ether: Ethernet reset branch function
649      f2_ether_eefct      = f2_task_13,   //!< f2 (1011) ether: Ethernet end of transmission function
650      f2_ether_ebfct      = f2_task_14,   //!< f2 (1100) ether: Ethernet branch function
651      f2_ether_ecbfct      = f2_task_15,   //!< f2 (1101) ether: Ethernet countdown branch function
652      f2_ether_eisfct      = f2_task_16,   //!< f2 (1110) ether: Ethernet input start function
653
654      f2_dwt_load_ddr      = f2_task_10,   //!< f2 (1000) dwt: load display data register
655
656      f2_curt_load_xpreg   = f2_task_10,   //!< f2 (1000) curt: load x position register
657      f2_curt_load_csr   = f2_task_11,   //!< f2 (1001) curt: load cursor shift register
658
659      f2_dht_evenfield   = f2_task_10,   //!< f2 (1000) dht: load even field
660      f2_dht_setmode      = f2_task_11,   //!< f2 (1001) dht: set mode
661
662      f2_dvt_evenfield   = f2_task_10,   //!< f2 (1000) dvt: load even field
663
664      f2_kwd_init         = f2_task_10,   //!< f2 (1000) kwd: branches NEXT[5-9] on WDTASKACT && WDINIT
665      f2_kwd_rwc         = f2_task_11,   //!< f2 (1001) kwd: branches NEXT[8-9] on READ/WRITE/CHECK for record
666      f2_kwd_recno      = f2_task_12,   //!< f2 (1010) kwd: branches NEXT[8-9] on RECNO[0-1]
667      f2_kwd_xfrdat      = f2_task_13,   //!< f2 (1011) kwd: branches NEXT[9] on !SEEKONLY
668      f2_kwd_swrnrdy      = f2_task_14,   //!< f2 (1100) kwd: branches NEXT[9] on !SWRDY
669      f2_kwd_nfer         = f2_task_15,   //!< f2 (1101) kwd: branches NEXT[9] on !KFER
670      f2_kwd_strobon      = f2_task_16,   //!< f2 (1110) kwd: branches NEXT[9] on STROBE
671   };
672
673   enum {
674      p_dynamic,         //!< dynamic functions (e.g. ALU and SHIFTER operations)
675      p_latches         //!< latching function (T, L, M, R, etc. register latch)
676   };
677
678
679   /**
680    * Bit field primitives
681    * These are some inline functions to make it easier to access variable by the
682    * bit-reversed notation that the Xerox Alto documents use all over the place.
683    * Bit number 0 is the most significant there, and bit number (width - 1)
684    * is the least significant.
685    */
686
687   //! get the left shift required to access bit %to in a word of %width bits
688   static inline UINT8 A2_BITSHIFT(UINT8 width, UINT8 to) { return width - 1 - to; }
689
690   //! build a least significant bit mask for bits %from to %to (inclusive)
691   static inline UINT32 A2_BITMASK(UINT8 from, UINT8 to) { return (1ul << (to + 1 - from)) - 1; }
692
693   //! get a single bit number %bit value from %reg, a word of %width bits
694   static inline UINT8 A2_BIT8(UINT8 reg, UINT8 width, UINT8 bit) { return (reg >> A2_BITSHIFT(width,bit)) & 1; }
695
696   //! get a bit field from %reg, a word of %width bits, starting at bit %from until bit %to
697   static inline UINT8 A2_GET8(UINT8 reg, UINT8 width, UINT8 from, UINT8 to) { return (reg >> A2_BITSHIFT(width,to)) & A2_BITMASK(from,to); }
698
699   //! put a value %val into %reg, a word of %width bits, starting at bit %from until bit %to
700   static inline void A2_PUT8(UINT8& reg, UINT8 width, UINT8 from, UINT8 to, UINT8 val) {
701      UINT8 mask = A2_BITMASK(from,to) << A2_BITSHIFT(width,to);
702      reg = (reg & ~mask) | ((val << A2_BITSHIFT(width,to)) & mask);
703   }
704
705   //! get a single bit number %bit value from %reg, a word of %width bits
706   static inline UINT16 A2_BIT16(UINT16 reg, UINT8 width, UINT8 bit) { return (reg >> A2_BITSHIFT(width,bit)) & 1; }
707
708   //! get a bit field from %reg, a word of %width bits, starting at bit %from until bit %to
709   static inline UINT16 A2_GET16(UINT16 reg, UINT8 width, UINT8 from, UINT8 to) { return (reg >> A2_BITSHIFT(width,to)) & A2_BITMASK(from,to); }
710
711   //! put a value %val into %reg, a word of %width bits, starting at bit %from until bit %to
712   static inline void A2_PUT16(UINT16& reg, UINT8 width, UINT8 from, UINT8 to, UINT16 val) {
713      UINT16 mask = A2_BITMASK(from,to) << A2_BITSHIFT(width,to);
714      reg = (reg & ~mask) | ((val << A2_BITSHIFT(width,to)) & mask);
715   }
716
717   //! get a single bit number %bit value from %reg, a word of %width bits
718   static inline UINT32 A2_BIT32(UINT32 reg, UINT8 width, UINT8 bit) { return (reg >> A2_BITSHIFT(width,bit)) & 1; }
719
720   //! get a bit field from %reg, a word of %width bits, starting at bit %from until bit %to
721   static inline UINT32 A2_GET32(UINT32 reg, UINT8 width, UINT8 from, UINT8 to) { return (reg >> A2_BITSHIFT(width,to)) & A2_BITMASK(from,to); }
722
723   //! put a value %val into %reg, a word of %width bits, starting at bit %from until bit %to
724   static inline void A2_PUT32(UINT32& reg, UINT8 width, UINT8 from, UINT8 to, UINT32 val) {
725      UINT32 mask = A2_BITMASK(from,to) << A2_BITSHIFT(width,to);
726      reg = (reg & ~mask) | ((val << A2_BITSHIFT(width,to)) & mask);
727   }
728
729   //! enumeration of the micro code word bits
730   //! Note: The Alto documents enumerate bits from left (MSB = 0) to right (LSB = 31)
731   enum {
732      DRSEL0, DRSEL1, DRSEL2, DRSEL3, DRSEL4,
733      DALUF0, DALUF1, DALUF2, DALUF3,
734      DBS0, DBS1, DBS2,
735      DF1_0, DF1_1, DF1_2, DF1_3,
736      DF2_0, DF2_1, DF2_2, DF2_3,
737      LOADT,
738      LOADL,
739      NEXT0, NEXT1, NEXT2, NEXT3, NEXT4, NEXT5, NEXT6, NEXT7, NEXT8, NEXT9
740   };
741
742   //! get the RSEL value from a micro instruction word
743   static inline UINT32 MIR_RSEL(UINT32 mir) { return A2_GET32(mir, 32, DRSEL0, DRSEL4); }
744
745   //! get the ALUF value from a micro instruction word
746   static inline UINT32 MIR_ALUF(UINT32 mir) { return A2_GET32(mir, 32, DALUF0, DALUF3); }
747
748   //! get the BS value from a micro instruction word
749   static inline UINT32 MIR_BS(UINT32 mir) { return A2_GET32(mir, 32, DBS0, DBS2); }
750
751   //! get the F1 value from a micro instruction word
752   static inline UINT32 MIR_F1(UINT32 mir) { return A2_GET32(mir, 32, DF1_0, DF1_3); }
753
754   //! get the F2 value from a micro instruction word
755   static inline UINT32 MIR_F2(UINT32 mir) { return A2_GET32(mir, 32, DF2_0, DF2_3); }
756
757   //! get the T value from a micro instruction word
758   static inline UINT32 MIR_T(UINT32 mir) { return A2_BIT32(mir, 32, LOADT); }
759
760   //! get the L value from a micro instruction word
761   static inline UINT32 MIR_L(UINT32 mir) { return A2_BIT32(mir, 32, LOADL); }
762
763   //! get the NEXT value from a micro instruction word
764   static inline UINT32 MIR_NEXT(UINT32 mir) { return A2_GET32(mir, 32, NEXT0, NEXT9); }
765
766   //! get the normally accessed bank number from a bank register
767   static inline UINT16 GET_BANK_NORMAL(UINT16 breg) { return A2_GET16(breg,16,12,13); }
768
769   //! get the extended bank number (accessed via XMAR) from a bank register
770   static inline UINT16 GET_BANK_EXTENDED(UINT16 breg) { return A2_GET16(breg,16,14,15); }
771
772   //! get an ignored bit field from a control RAM address
773   static inline UINT16 GET_CRAM_IGNORE(UINT16 addr) { return A2_GET16(addr,16,0,1); }
774
775   //! get the bank select bit field from a control RAM address
776   static inline UINT16 GET_CRAM_BANKSEL(UINT16 addr) { return A2_GET16(addr,16,2,3); }
777
778   //! get the ROM/RAM flag from a control RAM address
779   static inline UINT16 GET_CRAM_RAMROM(UINT16 addr) { return A2_GET16(addr,16,4,4); }
780
781   //! get the half select flag from a control RAM address
782   static inline UINT16 GET_CRAM_HALFSEL(UINT16 addr) { return A2_GET16(addr,16,5,5); }
783
784   //! get the word address bit field from a control RAM address
785   static inline UINT16 GET_CRAM_WORDADDR(UINT16 addr)   { return A2_GET16(addr,16,6,15); }
786
787   UINT16 m_task_mpc[ALTO2_TASKS];               //!< per task micro program counter
788   UINT16 m_task_next2[ALTO2_TASKS];            //!< per task address modifier
789   attoseconds_t m_ntime[ALTO2_TASKS];            //!< per task atto seconds executed
790   UINT8 m_task;                           //!< active task
791   UINT8 m_next_task;                        //!< next micro instruction's task
792   UINT8 m_next2_task;                        //!< next but one micro instruction's task
793   UINT16 m_mpc;                           //!< micro program counter
794   UINT32 m_mir;                           //!< micro instruction register
795
796   /**
797    * \brief current micro instruction's register selection
798    * The emulator F2s ACSOURCE and ACDEST modify this.
799    * Note: S registers are addressed by the original RSEL[0-4],
800    * even when the the emulator modifies this.
801    */
802   UINT8 m_rsel;
803
804   UINT16 m_next;                           //!< current micro instruction's next
805   UINT16 m_next2;                           //!< next micro instruction's next
806   UINT16 m_r[ALTO2_REGS];                     //!< R register file
807   UINT16 m_s[ALTO2_SREG_BANKS][ALTO2_REGS];      //!< S register file(s)
808   UINT16 m_bus;                           //!< wired-AND bus
809   UINT16 m_t;                              //!< T register
810   UINT16 m_alu;                           //!< the current ALU
811   UINT16 m_aluc0;                           //!< the current ALU carry output
812   UINT16 m_l;                              //!< L register
813   UINT16 m_shifter;                        //!< shifter output
814   UINT16 m_laluc0;                        //!< the latched ALU carry output
815   UINT16 m_m;                              //!< M register of RAM related tasks (MYL latch in the schematics)
816   UINT16 m_cram_addr;                        //!< constant RAM address
817   UINT16 m_task_wakeup;                     //!< task wakeup: bit 1<<n set if task n requesting service
818   a2func m_active_callback[ALTO2_TASKS];         //!< task activation callbacks
819
820   UINT16 m_reset_mode;                     //!< reset mode register: bit 1<<n set if task n starts in ROM
821   bool m_rdram_flag;                        //!< set by rdram, action happens on next cycle
822   bool m_wrtram_flag;                        //!< set by wrtram, action happens on next cycle
823
824   UINT8 m_s_reg_bank[ALTO2_TASKS];            //!< active S register bank per task
825   UINT8 m_bank_reg[ALTO2_TASKS];               //!< normal and extended RAM banks per task
826   bool m_ether_enable;                     //!< set to true, if the ethernet should be simulated
827   bool m_ewfct;                           //!< set by Ether task when it want's a wakeup at switch to task_mrt
828   int m_dsp_time;                           //!< display_state_machine() time accu
829   UINT8 m_dsp_state;                        //!< display_state_machine() previous state
830   int m_unload_time;                        //!< unload word time accu
831   int m_unload_word;                        //!< unload word number
832   int   m_bitclk_time;                        //!< bitclk call time accu
833   int m_bitclk_index;                        //!< bitclk index (bit number)
834
835   static const char *task_name(int task);         //!< human readable task names
836   static const char *r_name(UINT8 reg);         //!< human readable register names
837   static const char *aluf_name(UINT8 aluf);      //!< human readable ALU function names
838   static const char *bs_name(UINT8 bs);         //!< human readable bus source names
839   static const char *f1_name(UINT8 f1);         //!< human readable F1 function names
840   static const char *f2_name(UINT8 f2);         //!< human readable F2 function names
841
842   /**
843    * @brief 2KCTL PROM u3 - 256x4
844    * <PRE>
845    * PROM u3 is 256x4 type 3601-1, looks like SN74387, and it
846    * controls NEXT[6-9]', i.e. the outputs are wire-AND to NEXT
847    *
848    *           SN74387
849    *         +---+-+---+
850    *         |   +-+   |
851    *    A6  -|1      16|-  Vcc
852    *         |         |
853    *    A5  -|2      15|-  A7
854    *         |         |
855    *    A4  -|3      14|-  FE1'
856    *         |         |
857    *    A3  -|4      13|-  FE2'
858    *         |         |
859    *    A0  -|5      12|-  D0
860    *         |         |
861    *    A1  -|6      11|-  D1
862    *         |         |
863    *    A2  -|7      10|-  D2
864    *         |         |
865    *   GND  -|8       9|-  D3
866    *         |         |
867    *         +---------+
868    *
869    *
870    * It is enabled whenever the Emulator task is active and:
871    *   both F2[0] and F2[1] are 1  F2 functions 014, 015, 016, 017
872    *   F2=14 is 0                  not for F2 = 14 (load IR<-)
873    *   IR[0] is 0                  not for arithmetic group
874    *
875    * This means it controls the F2 functions 015:IDISP<- and 016:<-ACSOURCE
876    *
877    * Its address lines are:
878    *   line   pin   connected to         load swap
879    *   -------------------------------------------------------------------
880    *   A0     5     F2[2] (i.e. MIR[18]) IR[07]
881    *   A1     6     IR[01]               IR[06]
882    *   A2     7     IR[02]               IR[05]
883    *   A3     4     IR[03]               IR[04]
884    *   A4     3     IR[04]               IR[03]
885    *   A5     2     IR[05]               IR[02]
886    *   A6     1     IR[06]               IR[01]
887    *   A7     15    IR[07]               F2[2]
888    *
889    * Its data lines are:
890    *   line   pin   connected to         load
891    *   -------------------------------------------------------------------
892    *   D3     9     NEXT[06]'            NEXT[06]
893    *   D2     10    NEXT[07]'            NEXT[07]
894    *   D1     11    NEXT[08]'            NEXT[08]
895    *   D0     12    NEXT[09]'            NEXT[09]
896    *
897    * Its address lines are reversed at load time to make it easier to
898    * access it. Also both, address and data lines, are inverted.
899    * </PRE>
900    */
901   UINT8* m_ctl2k_u3;
902
903   /**
904    * @brief 2KCTL PROM u38; 82S23; 32x8 bit
905    * <PRE>
906    *
907    *            82S23
908    *         +---+-+---+
909    *         |   +-+   |
910    *    B0  -|1      16|-  Vcc
911    *         |         |
912    *    B1  -|2      15|-  EN'
913    *         |         |
914    *    B2  -|3      14|-  A4
915    *         |         |
916    *    B3  -|4      13|-  A3
917    *         |         |
918    *    B4  -|5      12|-  A2
919    *         |         |
920    *    B5  -|6      11|-  A1
921    *         |         |
922    *    B6  -|7      10|-  A0
923    *         |         |
924    *   GND  -|8       9|-  B7
925    *         |         |
926    *         +---------+
927    *
928    * Task priority encoder
929    *
930    *    line   pin    signal
931    *   -------------------------------
932    *   A0     10     CT1 (current task LSB)
933    *   A1     11     CT2
934    *   A2     12     CT4
935    *   A3     13     CT8 (current task MSB)
936    *   A4     14     0 (GND)
937    *
938    *   line   pin    signal
939    *   -------------------------------
940    *   B0     1      RDCT8'
941    *   B1     2      RDCT4'
942    *   B2     3      RDCT2'
943    *   B3     4      RDCT1'
944    *   B4     5      NEXT[09]'
945    *   B5     6      NEXT[08]'
946    *   B6     7      NEXT[07]'
947    *   B7     9      NEXT[06]'
948    * </PRE>
949    */
950   UINT8* m_ctl2k_u38;
951
952   //! output lines of the 2KCTL U38 PROM
953   enum {
954      U38_RDCT8,
955      U38_RDCT4,
956      U38_RDCT2,
957      U38_RDCT1,
958      U38_NEXT09,
959      U38_NEXT08,
960      U38_NEXT07,
961      U38_NEXT06
962   };
963
964   /**
965    * @brief 2KCTL PROM u76; P3601-1; 256x4; PC0I and PC1I decoding
966    * <PRE>
967    * Replacement for u51, which is used in 1KCTL
968    *
969    *           SN74387
970    *         +---+-+---+
971    *         |   +-+   |
972    *    A6  -|1      16|-  Vcc
973    *         |         |
974    *    A5  -|2      15|-  A7
975    *         |         |
976    *    A4  -|3      14|-  FE1'
977    *         |         |
978    *    A3  -|4      13|-  FE2'
979    *         |         |
980    *    A0  -|5      12|-  D0
981    *         |         |
982    *    A1  -|6      11|-  D1
983    *         |         |
984    *    A2  -|7      10|-  D2
985    *         |         |
986    *   GND  -|8       9|-  D3
987    *         |         |
988    *         +---------+
989    *
990    *   input line    signal
991    *   ----------------------------
992    *   A7    15      EMACT'
993    *   A6    1       F1(0)
994    *   A5    2       F1(1)'
995    *   A4    3       F1(2)'
996    *   A3    4       F1(3)'
997    *   A2    7       0 (GND)
998    *   A1    6       PC1O
999    *   A0    5       PC0O
1000    *
1001    *   output line   signal
1002    *   ----------------------------
1003    *   D0     12     PC1T
1004    *   D1     11     PC1F
1005    *   D2     10     PC0T
1006    *   D3     9      PC0F
1007    *
1008    * The outputs are connected to a dual 4:1 demultiplexer 74S153, so that
1009    * depending on NEXT01' and RESET the following signals are passed through:
1010    *
1011    *   RESET  NEXT[01]'  PC0I    PC1I
1012    *   --------------------------------------
1013    *   0      0          PC0T    PC1T
1014    *   0      1          PC0F    PC1F
1015    *   1      0          PC0I4   T14 (?)
1016    *   1      1          -"-     -"-
1017    *
1018    * This selects the microcode "page" to jump to on SWMODE (F1 = 010)
1019    * depending on the current NEXT[01]' level.
1020    * </PRE>
1021    */
1022   UINT8* m_ctl2k_u76;
1023
1024   /**
1025    * @brief 3k CRAM PROM a37
1026    */
1027   UINT8* m_cram3k_a37;
1028
1029   /**
1030    * @brief memory addressing PROM a64
1031    */
1032   UINT8* m_madr_a64;
1033
1034   /**
1035    * @brief memory addressing PROM a65
1036    */
1037   UINT8* m_madr_a65;
1038
1039   /**
1040    * @brief unused PROM a90
1041    */
1042   UINT8* m_madr_a90;
1043
1044   /**
1045    * @brief unused PROM a91
1046    */
1047   UINT8* m_madr_a91;
1048
1049   //! no operating function to put in the m_bs, m_f1 and m_f2 slots
1050   void noop() {}
1051
1052   //! per task bus source function pointers, early (0) and late (1)
1053   a2func m_bs[2][ALTO2_TASKS][ALTO2_BUSSRC];
1054   void set_bs(UINT8 task, UINT8 fn, a2func f0, a2func f1) {
1055      m_bs[0][task][fn] = f0 ? f0 : &alto2_cpu_device::noop;
1056      m_bs[1][task][fn] = f1 ? f1 : &alto2_cpu_device::noop;
1057   }
1058
1059   //! per task f1 function pointers, early (0) and late (1)
1060   a2func m_f1[2][ALTO2_TASKS][ALTO2_F1MAX];
1061   void set_f1(UINT8 task, UINT8 fn, a2func f0, a2func f1) {
1062      m_f1[0][task][fn] = f0 ? f0 : &alto2_cpu_device::noop;
1063      m_f1[1][task][fn] = f1 ? f1 : &alto2_cpu_device::noop;
1064   }
1065
1066   //! per task f2 function pointers, early (0) and late (1)
1067   a2func m_f2[2][ALTO2_TASKS][ALTO2_F2MAX];
1068   void set_f2(UINT8 task, UINT8 fn, a2func f0, a2func f1) {
1069      m_f2[0][task][fn] = f0 ? f0 : &alto2_cpu_device::noop;
1070      m_f2[1][task][fn] = f1 ? f1 : &alto2_cpu_device::noop;
1071   }
1072
1073   bool m_ram_related[ALTO2_TASKS];            //!< set when task is RAM related
1074
1075   UINT64 m_cycle;                           //!< number of cycles executed in the current slice
1076
1077   UINT64 cycle() { return m_cycle; }            //!< return the current CPU cycle
1078   UINT64 ntime() { return m_cycle*ALTO2_UCYCLE; }   //!< return the current nano seconds
1079
1080   void hard_reset();                        //!< reset the various registers
1081   int soft_reset();                        //!< soft reset
1082
1083   void fn_bs_bad_0();                        //! bs dummy early function
1084   void fn_bs_bad_1();                        //! bs dummy late function
1085
1086   void fn_f1_bad_0();                        //! f1 dummy early function
1087   void fn_f1_bad_1();                        //! f1 dummy late function
1088
1089   void fn_f2_bad_0();                        //! f2 dummy early function
1090   void fn_f2_bad_1();                        //! f2 dummy late function
1091
1092   DECLARE_READ16_MEMBER( noop_r );            //!< read open bus (0177777)
1093   DECLARE_WRITE16_MEMBER( noop_w );            //!< write open bus
1094
1095   DECLARE_READ16_MEMBER( bank_reg_r );         //!< read bank register in memory mapped I/O range
1096   DECLARE_WRITE16_MEMBER( bank_reg_w );         //!< write bank register in memory mapped I/O range
1097
1098   void bs_read_r_0();                        //!< bs_read_r early: drive bus by R register
1099   void bs_load_r_0();                        //!< bs_load_r early: load R places 0 on the BUS
1100   void bs_load_r_1();                        //!< bs_load_r late: load R from SHIFTER
1101   void bs_read_md_0();                     //!< bs_read_md early: drive BUS from read memory data
1102   void bs_mouse_0();                        //!< bs_mouse early: drive bus by mouse
1103   void bs_disp_0();                        //!< bs_disp early: drive bus by displacement (which?)
1104   void f1_load_mar_1();                     //!< f1_load_mar late: load memory address register
1105   void f1_task_0();                        //!< f1_task early: task switch
1106   void f2_bus_eq_zero_1();                  //!< f2_bus_eq_zero late: branch on bus equals zero
1107   void f2_shifter_lt_zero_1();               //!< f2_shifter_lt_zero late: branch on shifter less than zero
1108   void f2_shifter_eq_zero_1();               //!< f2_shifter_eq_zero late: branch on shifter equals zero
1109   void f2_bus_1();                        //!< f2_bus late: branch on bus bits BUS[6-15]
1110   void f2_alucy_1();                        //!< f2_alucy late: branch on latched ALU carry
1111   void f2_load_md_1();                     //!< f2_load_md late: load memory data
1112
1113   UINT8* m_alu_a10;                        //!< ALU function to 74181 operation lookup PROM
1114   UINT32 alu_74181(UINT32 a, UINT32 b, UINT8 smc);
1115
1116   void rdram();                           //!< read the microcode ROM/RAM halfword
1117   void wrtram();                           //!< write the microcode RAM from M register and ALU
1118
1119   // ************************************************
1120   // ram related stuff
1121   // ************************************************
1122   void bs_read_sreg_0();                     //!< bs_read_sreg early: drive bus by S register or M (MYL), if rsel is = 0
1123   void bs_load_sreg_0();                     //!< bs_load_sreg early: load S register puts garbage on the bus
1124   void bs_load_sreg_1();                     //!< bs_load_sreg late: load S register from M
1125   void branch_ROM(const char *from, int page);   //!< branch to ROM page
1126   void branch_RAM(const char *from, int page);   //!< branch to RAM page
1127   void f1_swmode_1();                        //!< f1_swmode early: switch to micro program counter BUS[6-15] in other bank
1128   void f1_wrtram_1();                        //!< f1_wrtram late: start WRTRAM cycle
1129   void f1_rdram_1();                        //!< f1_rdram late: start RDRAM cycle
1130#if   (ALTO2_UCODE_RAM_PAGES == 3)
1131   void f1_load_rmr_1();                     //!< f1_load_rmr late: load the reset mode register
1132#else   // ALTO2_UCODE_RAM_PAGES != 3
1133   void f1_load_srb_1();                     //!< f1_load_srb late: load the S register bank from BUS[12-14]
1134#endif
1135   void init_ram(int task);                  //!< called by RAM related tasks
1136   void exit_ram();
1137
1138   // ************************************************
1139   // memory mapped i/o stuff
1140   // ************************************************
1141   /**
1142    * @brief get printer paper ready bit
1143    * Paper ready bit. 0 when the printer is ready for a paper scrolling operation.
1144    */
1145   static inline UINT16 GET_PPRDY(UINT16 utilin) { return A2_GET16(utilin,16,0,0); }
1146
1147   /** @brief put printer paper ready bit */
1148   static inline void PUT_PPRDY(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,0,0,val); }
1149
1150   /**
1151    * @brief get printer check bit
1152    * Printer check bit bit. Should the printer find itself in an abnormal state,
1153    * it sets this bit to 0
1154    */
1155   static inline UINT16 GET_PCHECK(UINT16 utilin) { return A2_GET16(utilin,16,1,1); }
1156
1157   /** @brief put printer check bit */
1158   static inline void PUT_PCHECK(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,1,1,val); }
1159
1160   /** @brief get unused bit 2 */
1161   static inline UINT16 GET_UNUSED_2(UINT16 utilin) { return A2_GET16(utilin,16,2,2); }
1162
1163   /** @brief put unused bit 2 */
1164   static inline void PUT_UNUSED_2(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,2,2,val); }
1165
1166   /**
1167    * @brief get printer daisy ready bit
1168    * Daisy ready bit. 0 when the printer is ready to print a character.
1169    */
1170   static inline UINT16 GET_PCHRDY(UINT16 utilin) { return A2_GET16(utilin,16,3,3); }
1171
1172   /** @brief put printer daisy ready bit */
1173   static inline void PUT_PCHRDY(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,3,3,val); }
1174
1175   /**
1176    * @brief get printer carriage ready bit
1177    * Carriage ready bit. 0 when the printer is ready for horizontal positioning.
1178    */
1179   static inline UINT16 GET_PCARRDY(UINT16 utilin) { return A2_GET16(utilin,16,4,4); }
1180
1181   /** @brief put printer carriage ready bit */
1182   static inline void PUT_PCARRDY(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,4,4,val); }
1183
1184   /**
1185    * @brief get printer ready bit
1186    * Ready bit. Both this bit and the appropriate other ready bit (carriage,
1187    * daisy, etc.) must be 0 before attempting any output operation.
1188    */
1189   static inline UINT16 GET_PREADY(UINT16 utilin) { return A2_GET16(utilin,16,5,5); }
1190
1191   /** @brief put printer ready bit */
1192   static inline void PUT_PREADY(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,5,5,val); }
1193
1194   /**
1195    * @brief memory configuration switch
1196    */
1197   static inline UINT16 GET_MEMCONFIG(UINT16 utilin) { return A2_GET16(utilin,16,6,6); }
1198
1199   /** @brief put memory configuration switch */
1200   static inline void PUT_MEMCONFIG(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,6,6,val); }
1201
1202   /** @brief get unused bit 7 */
1203   static inline UINT16 GET_UNUSED_7(UINT16 utilin) { return A2_GET16(utilin,16,7,7); }
1204   /** @brief put unused bit 7 */
1205   static inline void PUT_UNUSED_7(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,7,7,val); }
1206
1207   /** @brief get key set key 0 */
1208   static inline UINT16 GET_KEYSET_KEY0(UINT16 utilin) { return A2_GET16(utilin,16,8,8); }
1209   /** @brief put key set key 0 */
1210   static inline void PUT_KEYSET_KEY0(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,8,8,val); }
1211
1212   /** @brief get key set key 1 */
1213   static inline UINT16 GET_KEYSET_KEY1(UINT16 utilin) { return A2_GET16(utilin,16,9,9); }
1214   /** @brief put key set key 1 */
1215   static inline void PUT_KEYSET_KEY1(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,9,9,val); }
1216
1217   /** @brief get key set key 2 */
1218   static inline UINT16 GET_KEYSET_KEY2(UINT16 utilin) { return A2_GET16(utilin,16,10,10); }
1219   /** @brief put key set key 2 */
1220   static inline void PUT_KEYSET_KEY2(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,10,10,val); }
1221
1222   /** @brief get key set key 3 */
1223   static inline UINT16 GET_KEYSET_KEY3(UINT16 utilin) { return A2_GET16(utilin,16,11,11); }
1224   /** @brief put key set key 3 */
1225   static inline void PUT_KEYSET_KEY3(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,11,11,val); }
1226
1227   /** @brief get key set key 4 */
1228   static inline UINT16 GET_KEYSET_KEY4(UINT16 utilin) { return A2_GET16(utilin,16,12,12); }
1229   /** @brief put key set key 4 */
1230   static inline void PUT_KEYSET_KEY4(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,12,12,val); }
1231
1232   /** @brief get mouse red button bit */
1233   static inline UINT16 GET_MOUSE_RED(UINT16 utilin) { return A2_GET16(utilin,16,13,13); }
1234   /** @brief put mouse red button bit */
1235   static inline void PUT_MOUSE_RED(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,13,13,val); }
1236
1237   /** @brief get mouse blue button bit */
1238   static inline UINT16 GET_MOUSE_BLUE(UINT16 utilin) { return A2_GET16(utilin,16,14,14); }
1239   /** @brief put mouse blue button bit */
1240   static inline void PUT_MOUSE_BLUE(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,14,14,val); }
1241
1242   /** @brief get mouse yellow button bit */
1243   static inline UINT16 GET_MOUSE_YELLOW(UINT16 utilin) { return A2_GET16(utilin,16,15,15); }
1244   /** @brief put mouse yellow button bit */
1245   static inline void PUT_MOUSE_YELLOW(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,15,15,val); }
1246
1247   /** @brief put mouse bits */
1248   static inline void PUT_MOUSE(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,13,15,val); }
1249
1250   /**
1251    * @brief printer paper strobe bit
1252    * Paper strobe bit. Toggling this bit causes a paper scrolling operation.
1253    */
1254   static inline UINT16 GET_PPPSTR(UINT16 utilout) { return A2_GET16(utilout,16,0,0); }
1255
1256   /**
1257    * @brief printer retstore bit
1258    * Restore bit. Toggling this bit resets the printer (including clearing
1259    * the "check" condition if present) and moves the carriage to the
1260    * left margin.
1261    */
1262   static inline UINT16 GET_PREST(UINT16 utilout) { return A2_GET16(utilout,16,1,1); }
1263
1264   /**
1265    * @brief printer ribbon bit
1266    * Ribbon bit. When this bit is 1 the ribbon is up (in printing
1267    * position); when 0, it is down.
1268    */
1269   static inline UINT16 GET_PRIB(UINT16 utilout) { return A2_GET16(utilout,16,2,2); }
1270
1271   /**
1272    * @brief printer daisy strobe bit
1273    * Daisy strobe bit. Toggling this bit causes a character to be printed.
1274    */
1275   static inline UINT16 GET_PCHSTR(UINT16 utilout) { return A2_GET16(utilout,16,3,3); }
1276
1277   /**
1278    * @brief printer carriage strobe bit
1279    * Carriage strobe bit. Toggling this bit causes a horizontal position operation.
1280    */
1281   static inline UINT16 GET_PCARSTR(UINT16 utilout) { return A2_GET16(utilout,16,4,4); }
1282
1283   /**
1284    * @brief printer data
1285    * Argument to various output operations:
1286    * 1. Printing characters. When the daisy bit is toggled bits 9-15 of this field
1287    * are interpreted as an ASCII character code to be printed (it should be noted
1288    * that all codes less than 040 print as lower case "w").
1289    * 2. For paper and carriage operations the field is interpreted as a displacement
1290    * (-1024 to +1023), in units of 1/48 inch for paper and 1/60 inch for carriage.
1291    * Positive is down or to the right, negative up or to the left. The value is
1292    * represented as sign-magnitude (i.e., bit 5 is 1 for negative numbers, 0 for
1293    * positive; bits 6-15 are the absolute value of the number).
1294    */
1295   static inline UINT16 GET_PDATA(UINT16 utilout) { return A2_GET16(utilout,16,5,15); }
1296
1297   /** @brief miscellaneous hardware registers in the memory mapped I/O range */
1298   struct {
1299      UINT16 eia;            //!< the EIA port at 0177001
1300      UINT16 utilout;         //!< the UTILOUT port at 0177016 (active-low outputs) */
1301      UINT16 xbus[4];         //!< the XBUS port at 0177020 to 0177023
1302      UINT16 utilin;         //!< the UTILIN port at 0177030 to 0177033 (same value on all addresses)
1303   }   m_hw;
1304
1305   DECLARE_READ16_MEMBER( utilin_r );         //!< read an UTILIN address
1306   DECLARE_READ16_MEMBER( utilout_r );         //!< read the UTILOUT address
1307   DECLARE_WRITE16_MEMBER( utilout_w );      //!< write the UTILOUT address
1308   DECLARE_READ16_MEMBER( xbus_r );         //!< read an XBUS address
1309   DECLARE_WRITE16_MEMBER( xbus_w );         //!< write an XBUS address (?)
1310   void init_hw();                        //!< initialize miscellaneous hardware
1311   void exit_hw();                        //!< deinitialize miscellaneous hardware
1312
1313   // ************************************************
1314   // keyboard stuff
1315   // ************************************************
1316   struct {
1317      UINT16 bootkey;                     //!< boot key - key code pressed before power on
1318      UINT16 matrix[4];                  //!< a bit map of the keys pressed (ioports ROW0 ... ROW3)
1319   }   m_kbd;
1320   DECLARE_READ16_MEMBER( kbd_ad_r );         //!< read the keyboard matrix
1321   void init_kbd(UINT16 bootkey = 0177777);   //!< initialize the keyboard hardware, optinally set the boot key
1322   void exit_kbd();                     //!< deinitialize the keyboard hardware
1323
1324   // ************************************************
1325   // mouse stuff
1326   // ************************************************
1327   /**
1328    * @brief PROM madr.a32 contains a lookup table to translate mouse motions
1329    *
1330    * <PRE>
1331    * The 4 mouse motion signals MX1, MX2, MY1, and MY2 are connected
1332    * to a 256x4 PROM's (3601, SN74387) address lines A0, A2, A4, and A6.
1333    * The previous (latched) state of the 4 signals is connected to the
1334    * address lines A1, A3, A5, and A7.
1335    *
1336    *                  SN74387
1337    *               +---+--+---+
1338    *               |   +--+   |
1339    *  MY2     A6  -|1       16|-  Vcc
1340    *               |          |
1341    *  LMY1    A5  -|2       15|-  A7     LMY2
1342    *               |          |
1343    *  MY1     A4  -|3       14|-  FE1'   0
1344    *               |          |
1345    *  LMX2    A3  -|4       13|-  FE2'   0
1346    *               |          |
1347    *  MX1     A0  -|5       12|-  D0     BUS[12]
1348    *               |          |
1349    *  LMX1    A1  -|6       11|-  D1     BUS[13]
1350    *               |          |
1351    *  MX2     A2  -|7       10|-  D2     BUS[14]
1352    *               |          |
1353    *         GND  -|8        9|-  D3     BUS[15]
1354    *               |          |
1355    *               +----------+
1356    *
1357    * A motion to the west will first toggle MX2, then MX1.
1358    * sequence: 04 -> 0d -> 0b -> 02
1359    * A motion to the east will first toggle MX1, then MX2.
1360    * sequence: 01 -> 07 -> 0e -> 08
1361    *
1362    * A motion to the north will first toggle MY2, then MY1.
1363    * sequence: 40 -> d0 -> b0 -> 20
1364    * A motion to the south will first toggle MY1, then MY2.
1365    * sequence: 10 -> 70 -> e0 -> 80
1366    *
1367    * This dump is from PROM madr.a32:
1368    * 0000: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1369    * 0020: 003,015,005,003,005,003,003,015,015,003,003,005,003,005,015,003,
1370    * 0040: 011,001,016,011,016,011,011,001,001,011,011,016,011,016,001,011,
1371    * 0060: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1372    * 0100: 011,001,016,011,016,011,011,001,001,011,011,016,011,016,001,011,
1373    * 0120: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1374    * 0140: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1375    * 0160: 003,015,005,003,005,003,003,015,015,003,003,005,003,005,015,003,
1376    * 0200: 003,015,005,003,005,003,003,015,015,003,003,005,003,005,015,003,
1377    * 0220: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1378    * 0240: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1379    * 0260: 011,001,016,011,016,011,011,001,001,011,011,016,011,016,001,011,
1380    * 0300: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1381    * 0320: 011,001,016,011,016,011,011,001,001,011,011,016,011,016,001,011,
1382    * 0340: 003,015,005,003,005,003,003,015,015,003,003,005,003,005,015,003,
1383    * 0360: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017
1384    * </PRE>
1385    */
1386   UINT8* m_madr_a32;
1387
1388   //! mouse context
1389   struct {
1390      int x;                              //!< current X coordinate
1391      int y;                              //!< current Y coordinate
1392      int dx;                              //!< destination X coordinate (real mouse X)
1393      int dy;                              //!< destination Y coordinate (real mouse Y)
1394      UINT8 latch;                        //!< current latch value
1395      UINT8 phase;                        //!< current read latch phase
1396   }   m_mouse;
1397
1398   UINT16 mouse_read();                     //!< return the mouse motion flags
1399   void init_mouse();                        //!< initialize the mouse context to useful values
1400   void exit_mouse();                        //!< deinitialize the mouse
1401
1402   // ************************************************
1403   // disk controller stuff
1404   // ************************************************
1405   diablo_hd_device* m_drive[2];      //!< two diablo_hd_device drives
1406
1407   //! disk controller context
1408   struct {
1409      UINT8 drive;               //!< selected drive from KADDR[14] (written to data out with SENDADR)
1410      UINT16 kaddr;               //!< A[0-15] disk hardware address (sector, cylinder, head, drive, restore)
1411      UINT16 kadr;               //!< C[0-15] with read/write/check modes for header, label and data
1412      UINT16 kstat;               //!< S[0-15] disk status
1413      UINT16 kcom;               //!< disk command (5 bits kcom[1-5])
1414      UINT8 krecno;               //!< record number (2 bits indexing header, label, data, -/-)
1415      UINT8 egate;               //!< current erase gate signal to the DIABLO hd
1416      UINT8 wrgate;               //!< current write gate signal to the DIABLO hd
1417      UINT8 rdgate;               //!< current read gate signal to the DIABLO hd
1418      UINT32 shiftin;               //!< input shift register
1419      UINT32 shiftout;            //!< output shift register
1420      UINT32 datain;               //!< disk data in latch
1421      UINT32 dataout;               //!< disk data out latch
1422      UINT8 krwc;                  //!< read/write/check for current record
1423      UINT8 kfer;                  //!< disk fatal error signal state
1424      UINT8 wdtskena;               //!< disk word task enable (active low)
1425      UINT8 wddone;               //!< previous state of WDDONE
1426      UINT8 wdinit0;               //!< disk word task init at the early microcycle
1427      UINT8 wdinit;               //!< disk word task init at the late microcycle
1428      UINT8 strobe;               //!< strobe (still) active
1429      emu_timer* strobon_timer;      //!< set strobe on timer
1430      UINT8 bitclk;               //!< current bitclk state (either crystal clock, or rdclk from the drive)
1431#if   USE_BITCLK_TIMER
1432      emu_timer* bitclk_timer;      //!< bit clock timer
1433#else
1434      int bitclk_time;            //!< time in clocks per bit
1435#endif
1436      UINT8 datin;               //!< current datin from the drive
1437      UINT8 bitcount;               //!< bit counter
1438      UINT8 carry;               //!< carry output of the bitcounter
1439      UINT8 seclate;               //!< sector late (monoflop output)
1440      emu_timer* seclate_timer;      //!< sector late timer
1441      UINT8 seekok;               //!< seekok state (SKINC' & LAI' & ff_44a.Q')
1442      UINT8 ok_to_run;            //!< ok to run signal (set to 1 some time after reset)
1443      emu_timer* ok_to_run_timer;      //!< ok to run timer
1444      UINT8 ready_mf31a;            //!< ready monoflop 31a
1445      emu_timer* ready_timer;         //!< ready timer
1446      UINT8 seclate_mf31b;         //!< seclate monoflop 31b
1447      jkff_t ff_21a;               //!< JK flip-flop 21a (sector task)
1448      jkff_t ff_21a_old;            //!< -"- previous state
1449      jkff_t ff_21b;               //!< JK flip-flop 21b (sector task)
1450      jkff_t ff_22a;               //!< JK flip-flop 22a (sector task)
1451      jkff_t ff_22b;               //!< JK flip-flop 22b (sector task)
1452      jkff_t ff_43b;               //!< JK flip-flop 43b (word task)
1453      jkff_t ff_53a;               //!< JK flip-flop 53a (word task)
1454      jkff_t ff_43a;               //!< JK flip-flop 43a (word task)
1455      jkff_t ff_53b;               //!< brief JK flip-flop 53b (word task)
1456      jkff_t ff_44a;               //!< JK flip-flop 44a (LAI' clocked)
1457      jkff_t ff_44b;               //!< JK flip-flop 44b (CKSUM)
1458      jkff_t ff_45a;               //!< JK flip-flop 45a (ready latch)
1459      jkff_t ff_45b;               //!< JK flip-flop 45b (seqerr latch)
1460   }   m_dsk;
1461
1462   jkff_t m_sysclka0[4];            //!< simulate previous sysclka
1463   jkff_t m_sysclka1[4];            //!< simulate current sysclka
1464   jkff_t m_sysclkb0[4];            //!< simulate previous sysclkb
1465   jkff_t m_sysclkb1[4];            //!< simulate current sysclkb
1466   //! lookup JK flip-flop state change from s0 to s1
1467   inline jkff_t update_jkff(UINT8 s0, UINT8 s1);
1468
1469   void kwd_timing(int bitclk, int datin, int block);   //!< disk word timing
1470   TIMER_CALLBACK_MEMBER( disk_seclate );         //!< timer callback to take away the SECLATE pulse (monoflop)
1471   TIMER_CALLBACK_MEMBER( disk_ok_to_run );      //!< timer callback to take away the OK TO RUN pulse (reset)
1472   TIMER_CALLBACK_MEMBER( disk_strobon );         //!< timer callback to pulse the STROBE' signal to the drive
1473   TIMER_CALLBACK_MEMBER( disk_ready_mf31a );      //!< timer callback to change the READY monoflop 31a
1474#if   USE_BITCLK_TIMER
1475   TIMER_CALLBACK_MEMBER( disk_bitclk );         //!< callback to update the disk controller with a new bitclk
1476#else
1477   void disk_bitclk(void *ptr, int arg);         //!< function to update the disk controller with a new bitclk
1478#endif
1479   void disk_block(int task);                  //!< called if one of the disk tasks (task_kwd or task_ksec) blocks
1480   void bs_read_kstat_0();                     //!< bs_read_kstat early: bus driven by disk status register KSTAT
1481   void bs_read_kdata_0();                     //!< bs_read_kdata early: bus driven by disk data register KDATA input
1482   void f1_strobe_1();                        //!< f1_strobe late: initiates a disk seek
1483   void f1_load_kstat_1();                     //!< f1_load_kstat late: load disk status register
1484   void f1_load_kdata_1();                     //!< f1_load_kdata late: load data out register, or the disk address register
1485   void f1_increcno_1();                     //!< f1_increcno late: advances shift registers holding KADR
1486   void f1_clrstat_1();                     //!< f1_clrstat late: reset all error latches
1487   void f1_load_kcom_1();                     //!< f1_load_kcom late: load the KCOM register from bus
1488   void f1_load_kadr_1();                     //!< f1_load_kadr late: load the KADR register from bus
1489   void f2_init_1();                        //!< f2_init late: branch on disk word task active and init
1490   void f2_rwc_1();                        //!< f2_rwc late: branch on read/write/check state of the current record
1491   void f2_recno_1();                        //!< f2_recno late: branch on the current record number by a lookup table
1492   void f2_xfrdat_1();                        //!< f2_xfrdat late: branch on the data transfer state
1493   void f2_swrnrdy_1();                     //!< f2_swrnrdy late: branch on the disk ready signal
1494   void f2_nfer_1();                        //!< f2_nfer late: branch on the disk fatal error condition
1495   void f2_strobon_1();                     //!< f2_strobon late: branch on the seek busy status
1496   void init_disk();                        //!< initialize the disk context
1497   void exit_disk();                        //!< deinitialize the disk context
1498
1499   // ************************************************
1500   // display stuff
1501   // ************************************************
1502   /**
1503    * @brief structure of the display context
1504    *
1505    * Schematics of the task clear and wakeup signal generators
1506    * <PRE>
1507    * A quote (') appended to a signal name means inverted signal.
1508    *
1509    *  AND |     NAND|      NOR |       FF | Q    N174
1510    * -----+--- -----+---  -----+---  -----+---   -----
1511    *  0 0 | 0   0 0 | 1    0 0 | 1    S'\0| 1    delay
1512    *  0 1 | 0   0 1 | 1    0 1 | 0    R'\0| 0
1513    *  1 0 | 0   1 0 | 1    1 0 | 0
1514    *  1 1 | 1   1 1 | 0    1 1 | 0
1515    *
1516    *
1517    *                                                       DVTAC'
1518    *                                                      >-------·  +-----+
1519    *                                                              |  |  FF |
1520    * VBLANK'+----+ DELVBLANK' +---+  DELVBLANK   +----+           ·--|S'   |
1521    * >------|N174|------+-----|inv|--------------|NAND| VBLANKPULSE  |     |              WAKEDVT'
1522    *        +----+      |     +---+              |    o--+-----------|R'  Q|---------------------->
1523    *                    |                      ·-|    |  |           |     |
1524    *        +----+      |     DDELVBLANK'      | +----+  |           +-----+
1525    *      ·-|N174|-----------------------------·         |      +---+
1526    *      | +----+      |                                +------oAND|
1527    *      |             |                      DSP07.01  |      |   o----------·
1528    *      ·-------------·                      >---------|------o   |          |
1529    *                                                     |      +---+          |
1530    *                                                     |                     |
1531    *                                                     | +-----+             |
1532    *                                                     | |  FF |             |  +-----+
1533    *        DHTAC'       +---+                           | |     |             |  |  FF |
1534    *      >--------------oNOR|  *07.25       +----+      ·-|S'   |   DHTBLK'   |  |     |
1535    *        BLOCK'       |   |---------------|NAND|        |    Q|--+----------|--|S1'  | WAKEDHT'
1536    *      >--------------o   |     DCSYSCLK  |    o--------|R'   |  | >--------|--|S2' Q|--------->
1537    *                     +---+     >---------|    |        +-----+  |  DHTAC'  ·--|R'   |
1538    *                                         +----+                 |             +-----+
1539    *                                                   ·------------·
1540    *                                                   |
1541    *        DWTAC'       +---+                         |   +-----+
1542    *      >--------------oNOR|  *07.26 +----+          |   |  FF |
1543    *        BLOCK'       |   |---------|NAND| DSP07.01 |   |     |
1544    *      >--------------o   | DCSYSCLK|    o----------|---|S1'  | DWTCN' +---+        DWTCN
1545    *                     +---+ >-------|    |          ·---|S2' Q|--------|inv|-----------+----
1546    *                                   +----+          ·---|R'   |        +---+           |
1547    *                                                   |   +-----+                        |
1548    *                 SCANEND     +----+                |                                  |
1549    *               >-------------|NAND|  CLRBUF'       |           .----------------------·
1550    *                 DCLK        |    o----------------·           |
1551    *               >-------------|    |                            |  +-----+
1552    *                             +----+                            ·--| NAND|
1553    *                                                       STOPWAKE'  |     |preWake +----+ WAKEDWT'
1554    *                                                      >-----------|     o--------|N174|--------->
1555    *                                                        VBLANK'   |     |        +----+
1556    *                                                      >-----------|     |
1557    *                                                                  +-----+
1558    *                                                     a40c
1559    *                                        VBLANKPULSE +----+
1560    *                                       -------------|NAND|
1561    *                                                    |    o--·
1562    *                                                 ·--|    |  |
1563    *                                                 |  +----+  |
1564    *                                                 ·----------|-·
1565    *                                                 ·----------· |
1566    *        CURTAC'      +---+                       |  +----+    |     a20d
1567    *      >--------------oNOR|  *07.27 +----+        ·--|NAND|    |    +----+
1568    *        BLOCK'       |   |---------|NAND| DSP07.07  |    o----+----o NOR| preWK  +----+ WAKECURT'
1569    *      >--------------o   | DCSYSCLK|    o-----------|    |         |    |--------|N174|--------->
1570    *                     +---+ >-------|    |           +----+    +----o    |        +----+
1571    *                                   +----+            a40d     |    +----+
1572    *                                          a30c                |
1573    *                              CURTAC'    +----+               |
1574    *                            >------------|NAND|    DSP07.03   |
1575    *                                         |    o--+------------·
1576    *                                      ·--|    |  |
1577    *                                      |  +----+  |
1578    *                                      ·----------|-·
1579    *                                      ·----------· |
1580    *                                      |  +----+    |
1581    *                                      ·--|NAND|    |
1582    *                              CLRBUF'    |    o----·
1583    *                            >------------|    |
1584    *                                         +----+
1585    *                                          a30d
1586    * </PRE>
1587    */
1588   struct {
1589      UINT16 hlc;                     //!< horizontal line counter
1590      UINT8 a63;                     //!< most recent value read from the PROM a63
1591      UINT8 a66;                     //!< most recent value read from the PROM a66
1592      UINT16 setmode;                  //!< value written by last SETMODE<-
1593      UINT16 inverse;                  //!< set to 0xffff if line is inverse, 0x0000 otherwise
1594      UINT8 halfclock;               //!< set 0 for normal pixel clock, 1 for half pixel clock
1595      UINT8 clr;                     //!< set non-zero if any of VBLANK or HBLANK is active (a39a 74S08)
1596      UINT16 fifo[ALTO2_DISPLAY_FIFO];   //!< display word fifo
1597      UINT8 fifo_wr;                  //!< fifo input pointer (4-bit)
1598      UINT8 fifo_rd;                  //!< fifo output pointer (4-bit)
1599      UINT8 dht_blocks;               //!< set non-zero, if the DHT executed BLOCK
1600      UINT8 dwt_blocks;               //!< set non-zero, if the DWT executed BLOCK
1601      UINT8 curt_blocks;               //!< set non-zero, if the CURT executed BLOCK
1602      UINT8 curt_wakeup;               //!< set non-zero, if CURT wakeups are generated
1603      UINT16 vblank;                  //!< most recent HLC with VBLANK still high (11-bit)
1604      UINT16 xpreg;                  //!< cursor cursor x position register (10-bit)
1605      UINT16 csr;                     //!< cursor shift register (16-bit)
1606      UINT32 curword;                  //!< helper: first cursor word in current scanline
1607      UINT32 curdata;                  //!< helper: shifted cursor data (32-bit)
1608      UINT16 *raw_bitmap;               //!< array of words of the raw bitmap that is displayed
1609      UINT16 **scanline;               //!< array of pointers to the scanlines
1610   }   m_dsp;
1611
1612   /**
1613    * @brief PROM a38 contains the STOPWAKE' and MBEMBPTY' signals for the FIFO
1614    * <PRE>
1615    * The inputs to a38 are the UNLOAD counter RA[0-3] and the DDR<- counter
1616    * WA[0-3], and the designer decided to reverse the address lines :-)
1617    *
1618    *   a38  counter FIFO counter
1619    *   --------------------------
1620    *    A0  RA[0]   fifo_rd
1621    *    A1  RA[1]
1622    *    A2  RA[2]
1623    *    A3  RA[3]
1624    *    A4  WA[0]   fifo_wr
1625    *    A5  WA[1]
1626    *    A6  WA[2]
1627    *    A7  WA[3]
1628    *
1629    * Only two bits of a38 are used:
1630    *    O1 (002) = STOPWAKE'
1631    *    O3 (010) = MBEMPTY'
1632    * </PRE>
1633    */
1634   UINT8* m_disp_a38;
1635
1636   //! output bits of PROM A38
1637   enum {
1638      A38_STOPWAKE   = (1 << 1),
1639      A38_MBEMPTY      = (1 << 3)
1640   };
1641
1642   //! PROM a38 bit O1 is STOPWAKE' (stop DWT if bit is zero)
1643   inline UINT8 FIFO_STOPWAKE_0() { return m_disp_a38[m_dsp.fifo_rd * 16 + m_dsp.fifo_wr] & A38_STOPWAKE; }
1644
1645   //! PROM a38 bit O3 is MBEMPTY' (FIFO is empty if bit is zero)
1646   inline UINT8 FIFO_MBEMPTY_0() { return m_disp_a38[m_dsp.fifo_rd * 16 + m_dsp.fifo_wr] & A38_MBEMPTY; }
1647
1648   /**
1649    * @brief emulation of PROM a63 in the display schematics page 8
1650    * <PRE>
1651    * The PROM's address lines are driven by a clock CLK, which is
1652    * pixel clock / 24, and an inverted half-scanline signal H[1]'.
1653    *
1654    * It is 32x8 bits and its output bits (B) are connected to the
1655    * signals, as well as its own address lines (A) through a latch
1656    * of the type SN74774 like this:
1657    *
1658    * B    174     A   others
1659    * ------------------------
1660    * 0     5      -   HBLANK
1661    * 1     0      -   HSYNC
1662    * 2     4      0
1663    * 3     1      1
1664    * 4     3      2
1665    * 5     2      3
1666    * 6     -      -   SCANEND
1667    * 7     -      -   HLCGATE
1668    * ------------------------
1669    * H[1]' -      4
1670    *
1671    * The display_state_machine() is called by the CPU at a rate of pixelclock/24,
1672    * which happens to be very close to every 7th CPU micrcocycle.
1673    * </PRE>
1674    */
1675   UINT8* m_disp_a63;
1676
1677   enum {
1678      A63_HBLANK   = (1 << 0),            //!< PROM a63 B0 is latched as HBLANK signal
1679      A63_HSYNC   = (1 << 1),            //!< PROM a63 B1 is latched as HSYNC signal
1680      A63_A0      = (1 << 2),            //!< PROM a63 B2 is the latched next address bit A0
1681      A63_A1      = (1 << 3),            //!< PROM a63 B3 is the latched next address bit A1
1682      A63_A2      = (1 << 4),            //!< PROM a63 B4 is the latched next address bit A2
1683      A63_A3      = (1 << 5),            //!< PROM a63 B5 is the latched next address bit A3
1684      A63_SCANEND   = (1 << 6),            //!< PROM a63 B6 SCANEND signal, which resets the FIFO counters
1685      A63_HLCGATE   = (1 << 7)            //!< PROM a63 B7 HLCGATE signal, which enables counting the HLC
1686   };
1687
1688   /**
1689    * @brief vertical blank and synch PROM
1690    *
1691    * PROM a66 is a 256x4 bit (type 3601), containing the vertical blank + synch.
1692    * Address lines are driven by H[1] to H[128] of the the horz. line counters.
1693    * The PROM is enabled whenever H[256] and H[512] are both 0.
1694    *
1695    * Q1 (001) is VSYNC for the odd field (with H1024=1)
1696    * Q2 (002) is VSYNC for the even field (with H1024=0)
1697    * Q3 (004) is VBLANK for the odd field (with H1024=1)
1698    * Q4 (010) is VBLANK for the even field (with H1024=0)
1699    */
1700   UINT8* m_disp_a66;
1701
1702   enum {
1703      A66_VSYNC_ODD   = (1 << 0),
1704      A66_VSYNC_EVEN   = (1 << 1),
1705      A66_VBLANK_ODD   = (1 << 2),
1706      A66_VBLANK_EVEN   = (1 << 3)
1707   };
1708
1709   //! test the VSYNC (vertical synchronisation) signal in PROM a66 being high
1710   static inline bool A66_VSYNC_HI(UINT8 a, int hlc1024) { return a & (hlc1024 ? A66_VSYNC_ODD : A66_VSYNC_EVEN) ? false : true; }
1711   //! test the VSYNC (vertical synchronisation) signal in PROM a66 being low
1712   static inline bool A66_VSYNC_LO(UINT8 a, int hlc1024) { return a & (hlc1024 ? A66_VSYNC_ODD : A66_VSYNC_EVEN) ? true : false; }
1713   //! test the VBLANK (vertical blanking) signal in PROM a66 being high
1714   static inline bool A66_VBLANK_HI(UINT8 a, int hlc1024) { return a & (hlc1024 ? A66_VBLANK_ODD : A66_VBLANK_EVEN) ? false : true; }
1715   //! test the VBLANK (vertical blanking) signal in PROM a66 being low
1716   static inline bool A66_VBLANK_LO(UINT8 a, int hlc1024) { return a & (hlc1024 ? A66_VBLANK_ODD : A66_VBLANK_EVEN) ? true : false; }
1717
1718   //! screen bitmap
1719   bitmap_ind16* m_displ_bitmap;
1720
1721   //! update a word in the screen bitmap
1722   void update_bitmap_word(int x, int y, UINT16 word);
1723
1724   //! unload the next word from the display FIFO and shift it to the screen
1725   int unload_word(int x);
1726
1727   /**
1728    * @brief function called by the CPU to enter the next display state
1729    *
1730    * There are 32 states per scanline and 875 scanlines per frame.
1731    *
1732    * @param arg the current m_disp_a63 PROM address
1733    * @return next state of the display state machine
1734    */
1735   UINT8 display_state_machine(UINT8 arg);
1736
1737   //! branch on the evenfield flip-flop
1738   void f2_evenfield_1(void);
1739
1740   //! initialize the display context
1741   void init_disp();
1742   //! deinitialize the display context
1743   void exit_disp();
1744
1745   // ************************************************
1746   // memory stuff
1747   // ************************************************
1748
1749   enum {
1750      ALTO2_MEM_NONE,
1751      ALTO2_MEM_ODD   = (1 << 0),
1752      ALTO2_MEM_RAM   = (1 << 1),
1753      ALTO2_MEM_NIRVANA   = (1 << 2)
1754   };
1755
1756   struct {
1757      UINT32* ram;                  //!< main memory organized as double-words
1758      UINT8* hpb;                     //!< Hamming Code bits (6) and Parity bits (1) per double word
1759      UINT32 mar;                     //!< memory address register
1760      UINT32 rmdd;                  //!< read memory data double-word
1761      UINT32 wmdd;                  //!< write memory data double-word
1762      UINT16 md;                     //!< memory data register
1763      UINT64 cycle;                  //!< cycle when the memory address register was loaded
1764
1765      /**
1766       * @brief memory access under the way if non-zero
1767       * 0: no memory access (MEM_NONE)
1768       * 1: invalid
1769       * 2: memory access even word (MEM_RAM)
1770       * 3: memory access odd word (MEM_RAM | MEM_ODD)
1771       * 4: refresh even word (MEM_REFRESH)
1772       * 5: refresh odd word (MEM_REFRESH | MEM_ODD)
1773       */
1774      int access;
1775      int error;                     //!< non-zero after a memory error was detected
1776      int mear;                     //!< memory error address register
1777      UINT16 mesr;                  //!< memory error status register
1778      UINT16 mecr;                  //!< memory error control register
1779   }   m_mem;
1780
1781   /**
1782    * @brief check if memory address register load is yet possible
1783    * suspend if accessing RAM and previous MAR<- was less than 5 cycles ago
1784    *
1785    * 1.  MAR<- ANY
1786    * 2.  REQUIRED
1787    * 3.  MD<- whatever
1788    * 4.  SUSPEND
1789    * 5.  SUSPEND
1790    * 6.  MAR<- ANY
1791    *
1792    * @result returns 0, if memory address can be loaded
1793    */
1794   inline bool check_mem_load_mar_stall(UINT8 rsel) {
1795      return (ALTO2_MEM_NONE == m_mem.access ? false : cycle() < m_mem.cycle+5);
1796   }
1797
1798   /**
1799    * @brief check if memory read is yet possible
1800    * MAR<- = cycle #1, earliest read at cycle #5, i.e. + 4
1801    *
1802    * 1.  MAR<- ANY
1803    * 2.  REQUIRED
1804    * 3.  SUSPEND
1805    * 4.  SUSPEND
1806    * 5.  whereever <-MD
1807    *
1808    * @result returns 0, if memory can be read without wait cycle
1809    */
1810   inline bool check_mem_read_stall() {
1811      return (ALTO2_MEM_NONE == m_mem.access ? false : cycle() < m_mem.cycle+4);
1812   }
1813
1814   /**
1815    * @brief check if memory write is yet possible
1816    * MAR<- = cycle #1, earliest write at cycle #3, i.e. + 2
1817    *
1818    * 1.  MAR<- ANY
1819    * 2.  REQUIRED
1820    * 3.  OPTIONAL
1821    * 4.  MD<- whatever
1822    *
1823    * @result returns 0, if memory can be written without wait cycle
1824    */
1825   inline bool check_mem_write_stall() {
1826      return (ALTO2_MEM_NONE == m_mem.access ? false : cycle() < m_mem.cycle+2);
1827   }
1828
1829   //! memory error address register read
1830   DECLARE_READ16_MEMBER( mear_r );
1831
1832   //! memory error status register read
1833   DECLARE_READ16_MEMBER( mesr_r );
1834
1835   //! memory error status register write (clear)
1836   DECLARE_WRITE16_MEMBER( mesr_w );
1837
1838   //! memory error control register read
1839   DECLARE_READ16_MEMBER( mecr_r );
1840
1841   //! memory error control register write
1842   DECLARE_WRITE16_MEMBER( mecr_w );
1843
1844   //! read or write a memory double-word and caluclate its Hamming code
1845   UINT32 hamming_code(int write, UINT32 dw_addr, UINT32 dw_data);
1846
1847   //! load the memory address register with some value
1848   void load_mar(UINT8 rsel, UINT32 addr);
1849
1850   //! read memory or memory mapped I/O from the address in mar to md
1851   UINT16 read_mem();
1852
1853   //! write memory or memory mapped I/O from md to the address in mar
1854   void write_mem(UINT16 data);
1855
1856   //! debugger interface to read memory
1857   UINT16 debug_read_mem(UINT32 addr);
1858
1859   //! debugger interface to write memory
1860   void debug_write_mem(UINT32 addr, UINT16 data);
1861
1862#if   ALTO2_DEBUG
1863   void watch_write(UINT32 addr, UINT32 data);
1864   void watch_read(UINT32 addr, UINT32 data);
1865#endif
1866   void init_memory();                        //!< initialize the memory system
1867   void exit_memory();                        //!< deinitialize the memory system
1868
1869   // ************************************************
1870   // emulator task
1871   // ************************************************
1872   struct {
1873      UINT16 ir;                           //!< emulator instruction register
1874      UINT8 skip;                           //!< emulator skip
1875      UINT8 cy;                           //!< emulator carry
1876   }   m_emu;
1877   void bs_emu_disp_0();                     //!< bs_emu_disp early: drive bus by IR[8-15], possibly sign extended
1878   void f1_emu_block_0();                     //!< f1_block early: block task
1879   void f1_emu_load_rmr_1();                  //!< f1_load_rmr late: load the reset mode register
1880   void f1_emu_load_esrb_1();                  //!< f1_load_esrb late: load the extended S register bank from BUS[12-14]
1881   void f1_rsnf_0();                        //!< f1_rsnf early: drive the bus from the Ethernet node ID
1882   void f1_startf_0();                        //!< f1_startf early: defines commands for for I/O hardware, including Ethernet
1883   void f2_busodd_1();                        //!< f2_busodd late: branch on odd bus
1884   void f2_magic_1();                        //!< f2_magic late: shift and use T
1885   void f2_load_dns_0();                     //!< f2_load_dns early: modify RESELECT with DstAC = (3 - IR[3-4])
1886   void f2_load_dns_1();                     //!< f2_load_dns late: do novel shifts
1887   void f2_acdest_0();                        //!< f2_acdest early: modify RSELECT with DstAC = (3 - IR[3-4])
1888   void bitblt_info();                        //!< debug bitblt opcode
1889   void f2_load_ir_1();                     //!< f2_load_ir late: load instruction register IR and branch on IR[0,5-7]
1890   void f2_idisp_1();                        //!< f2_idisp late: branch on: arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
1891   void f2_acsource_0();                     //!< f2_acsource early: modify RSELECT with SrcAC = (3 - IR[1-2])
1892   void f2_acsource_1();                     //!< f2_acsource late: branch on arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
1893   void init_emu(int task);                  //!< 000 initialize emulator task
1894   void exit_emu();                        //!< deinitialize emulator task
1895
1896   // ************************************************
1897   // ksec task
1898   // ************************************************
1899   void f1_ksec_block_0(void);
1900   void init_ksec(int task);                  //!< 004 initialize disk sector task
1901   void exit_ksec();
1902
1903   // ************************************************
1904   // ethernet task
1905   // ************************************************
1906   /**
1907    * @brief BPROMs P3601-1; 256x4; enet.a41 "PE1" and enet.a42 "PE2"
1908    *
1909    * Phase encoder
1910    *
1911    * a41: P3601-1; 256x4; "PE1"
1912    * a42: P3601-1; 256x4; "PE2"
1913    *
1914    * PE1/PE2 inputs
1915    * ----------------
1916    * A0  (5) OUTGO
1917    * A1  (6) XDATA
1918    * A2  (7) OSDATAG
1919    * A3  (4) XCLOCK
1920    * A4  (3) OCNTR0
1921    * A5  (2) OCNTR1
1922    * A6  (1) OCNTR2
1923    * A7 (15) OCNTR3
1924    *
1925    * PE1 outputs
1926    * ----------------
1927    * D0 (12) OCNTR0
1928    * D1 (11) OCNTR1
1929    * D2 (10) OCNTR2
1930    * D3  (9) OCNTR3
1931    *
1932    * PE2 outputs
1933    * ----------------
1934    * D0 (12) n.c.
1935    * D1 (11) to OSLOAD flip flop J and K'
1936    * D2 (10) XDATA
1937    * D3  (9) XCLOCK
1938    */
1939   UINT8* m_ether_a41;
1940   UINT8* m_ether_a42;
1941
1942   /**
1943    * @brief BPROM; P3601-1; 265x4 enet.a49 "AFIFO"
1944    *
1945    * Perhaps try with the contents of the display FIFO, as it is
1946    * the same type and the display FIFO has the same size.
1947    *
1948    * FIFO control
1949    *
1950    * a49: P3601-1; 256x4; "AFIFO"
1951    *
1952    * inputs
1953    * ----------------
1954    * A0  (5) fifo_wr[0]
1955    * A1  (6) fifo_wr[1]
1956    * A2  (7) fifo_wr[2]
1957    * A3  (4) fifo_wr[3]
1958    * A4  (3) fifo_rd[0]
1959    * A5  (2) fifo_rd[1]
1960    * A6  (1) fifo_rd[2]
1961    * A7 (15) fifo_rd[3]
1962    *
1963    * outputs active low
1964    * ----------------------------
1965    * D0 (12) BE'    (buffer empty)
1966    * D1 (11) BNE'   (buffer next empty ?)
1967    * D2 (10) BNNE'  (buffer next next empty ?)
1968    * D3  (9) BF'    (buffer full)
1969    *
1970    * Data from enet.a49 after address line reversal:
1971    * 000: 010 007 017 017 017 017 017 017 017 017 017 017 017 017 013 011
1972    * 020: 011 010 007 017 017 017 017 017 017 017 017 017 017 017 017 013
1973    * 040: 013 011 010 007 017 017 017 017 017 017 017 017 017 017 017 017
1974    * 060: 017 013 011 010 007 017 017 017 017 017 017 017 017 017 017 017
1975    * 100: 017 017 013 011 010 007 017 017 017 017 017 017 017 017 017 017
1976    * 120: 017 017 017 013 011 010 007 017 017 017 017 017 017 017 017 017
1977    * 140: 017 017 017 017 013 011 010 007 017 017 017 017 017 017 017 017
1978    * 160: 017 017 017 017 017 013 011 010 007 017 017 017 017 017 017 017
1979    * 200: 017 017 017 017 017 017 013 011 010 007 017 017 017 017 017 017
1980    * 220: 017 017 017 017 017 017 017 013 011 010 007 017 017 017 017 017
1981    * 240: 017 017 017 017 017 017 017 017 013 011 010 007 017 017 017 017
1982    * 260: 017 017 017 017 017 017 017 017 017 013 011 010 007 017 017 017
1983    * 300: 017 017 017 017 017 017 017 017 017 017 013 011 010 007 017 017
1984    * 320: 017 017 017 017 017 017 017 017 017 017 017 013 011 010 007 017
1985    * 340: 017 017 017 017 017 017 017 017 017 017 017 017 013 011 010 007
1986    * 360: 007 017 017 017 017 017 017 017 017 017 017 017 017 013 011 010
1987    */
1988   UINT8* m_ether_a49;
1989
1990   static const int m_duckbreath_sec = 15;         //!< send duckbreath every 15 seconds
1991
1992   struct {
1993      UINT16 fifo[ALTO2_ETHER_FIFO_SIZE];         //!< FIFO buffer
1994      UINT16 fifo_rd;                        //!< FIFO input pointer
1995      UINT16 fifo_wr;                        //!< FIFO output pointer
1996      UINT16 status;                        //!< status word
1997      UINT32 rx_crc;                        //!< receiver CRC
1998      UINT32 tx_crc;                        //!< transmitter CRC
1999      UINT32 rx_count;                     //!< received words count
2000      UINT32 tx_count;                     //!< transmitted words count
2001      emu_timer* tx_timer;                  //!< transmitter timer
2002      int duckbreath;                        //!< if non-zero, interval in seconds at which to broadcast the duckbreath
2003   }   m_eth;
2004
2005   TIMER_CALLBACK_MEMBER( rx_duckbreath );         //!< HACK: pull the next word from the duckbreath in the fifo
2006   TIMER_CALLBACK_MEMBER( tx_packet );            //!< transmit data from the FIFO to <nirvana for now>
2007   void eth_wakeup();                        //!< check for the various reasons to wakeup the Ethernet task
2008   void eth_startf();                        //!< start input or output depending on m_bus
2009   void bs_eidfct_0();                        //!< bs_eidfct early: Ethernet input data function
2010   void f1_eth_block_0();                     //!< f1_eth_block early: block the Ether task
2011   void f1_eilfct_0();                        //!< f1_eilfct early: Ethernet input look function
2012   void f1_epfct_0();                        //!< f1_epfct early: Ethernet post function
2013   void f1_ewfct_1();                        //!< f1_ewfct late: Ethernet countdown wakeup function
2014   void f2_eodfct_1();                        //!< f2_eodfct late: Ethernet output data function
2015   void f2_eosfct_1();                        //!< f2_eosfct late: Ethernet output start function
2016   void f2_erbfct_1();                        //!< f2_erbfct late: Ethernet reset branch function
2017   void f2_eefct_1();                        //!< f2_eefct late: Ethernet end of transmission function
2018   void f2_ebfct_1();                        //!< f2_ebfct late: Ethernet branch function
2019   void f2_ecbfct_1();                        //!< f2_ecbfct late: Ethernet countdown branch function
2020   void f2_eisfct_1();                        //!< f2_eisfct late: Ethernet input start function
2021   void activate_eth();                     //!< called by the CPU when the Ethernet task becomes active
2022   void init_ether(int task);                  //!< 007 initialize ethernet task
2023   void exit_ether();                        //!< deinitialize ethernet task
2024
2025   // ************************************************
2026   // memory refresh task
2027   // ************************************************
2028   void f1_mrt_block_0();                     //!< f1_mrt_block early: block the display word task
2029   void activate_mrt();                     //!< called by the CPU when MRT becomes active
2030   void init_mrt(int task);                  //!< 010 initialize memory refresh task
2031   void exit_mrt();                        //!< deinitialize memory refresh task
2032
2033   // ************************************************
2034   // display word task
2035   // ************************************************
2036   void f1_dwt_block_0();                     //!< f1_dwt_block early: block the display word task
2037   void f2_dwt_load_ddr_1();                  //!< f2_dwt_load_ddr late: load the display data register
2038   void init_dwt(int task);                  //!< 011 initialize display word task
2039   void exit_dwt();                        //!< deinitialize display word task
2040
2041   // ************************************************
2042   // cursor task
2043   // ************************************************
2044   void f1_curt_block_0();                     //!< f1_curt_block early: disable the cursor task and set the curt_blocks flag
2045   void f2_load_xpreg_1();                     //!< f2_load_xpreg late: load the x position register from BUS[6-15]
2046   void f2_load_csr_1();                     //!< f2_load_csr late: load the cursor shift register from BUS[0-15]
2047   void activate_curt();                     //!< curt_activate: called by the CPU when the cursor task becomes active
2048   void init_curt(int task);                   //!< 012 initialize cursor task
2049   void exit_curt();                        //!< deinitialize cursor task
2050
2051   // ************************************************
2052   // display horizontal task
2053   // ************************************************
2054   void f1_dht_block_0();                     //!< f1_dht_block early: disable the display word task
2055   void f2_dht_setmode_1();                  //!< f2_dht_setmode late: set the next scanline's mode inverse and half clock and branch
2056   void activate_dht();                     //!< called by the CPU when the display horizontal task becomes active
2057   void init_dht(int task);                  //!< 013 initialize display horizontal task
2058   void exit_dht();                        //!< deinitialize display horizontal task
2059
2060   // ************************************************
2061   // display vertical task
2062   // ************************************************
2063   void f1_dvt_block_0();                     //!< f1_dvt_block early: disable the display word task
2064   void activate_dvt();                     //!< called by the CPU when the display vertical task becomes active
2065   void init_dvt(int task);                  //!< 014 initialize display vertical task
2066   void exit_dvt();                        //!< deinitialize display vertical task
2067
2068   // ************************************************
2069   // parity task
2070   // ************************************************
2071   void activate_part();
2072   void init_part(int task);                  //!< 015 initialize parity task
2073   void exit_part();                        //!< deinitialize parity task
2074
2075   // ************************************************
2076   // disk word task
2077   // ************************************************
2078   void f1_kwd_block_0(void);
2079   void init_kwd(int task);                  //!< 016 initialize disk word task
2080   void exit_kwd();                        //!< deinitialize disk word task
2081};
2082
2083extern const device_type ALTO2;
2084
2085
2086#endif /* _CPU_ALTO2_H_ */
branches/alto2/src/emu/cpu/alto2/alto2.c
r26286r26287
1/*****************************************************************************
2 *
3 *   Portable Xerox AltoII CPU core
4 *
5 *   Copyright: Juergen Buchmueller <pullmoll@t-online.de>
6 *
7 *   Licenses: MAME, GPLv2
8 *
9 *****************************************************************************/
10#include "alto2.h"
11#include "a2roms.h"
12
13#define   DEBUG_UCODE_CONST_DATA   0   //!< define to 1 to dump decoded micro code and constants
14
15//**************************************************************************
16//  DEVICE DEFINITIONS
17//**************************************************************************
18
19const device_type ALTO2 = &device_creator<alto2_cpu_device>;
20//**************************************************************************
21//  LIVE DEVICE
22//**************************************************************************
23
24DEVICE_ADDRESS_MAP_START( ucode_map, 32, alto2_cpu_device )
25   AM_RANGE(0,                          ALTO2_UCODE_RAM_BASE - 1)          AM_READ     ( crom_r )
26   AM_RANGE(ALTO2_UCODE_RAM_BASE,       ALTO2_UCODE_SIZE - 1)              AM_READWRITE( cram_r, cram_w )
27ADDRESS_MAP_END
28
29DEVICE_ADDRESS_MAP_START( const_map, 16, alto2_cpu_device )
30   AM_RANGE(0,                          ALTO2_CONST_SIZE - 1)              AM_READ     ( const_r )
31ADDRESS_MAP_END
32
33DEVICE_ADDRESS_MAP_START( iomem_map, 16, alto2_cpu_device )
34   AM_RANGE(0,                          ALTO2_IO_PAGE_BASE - 1)            AM_READWRITE( ioram_r, ioram_w )
35   // page 0376
36   AM_RANGE(0177000,                    0177015)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
37   AM_RANGE(0177016,                    0177016)                           AM_READWRITE( utilout_r, utilout_w )    // UTILOUT register
38   AM_RANGE(0177017,                    0177017)                           AM_READWRITE( noop_r, noop_w )          // unused range
39   AM_RANGE(0177020,                    0177023)                           AM_READWRITE( xbus_r,  xbus_w )         // XBUS[0-3] registers
40   AM_RANGE(0177024,                    0177024)                           AM_READ     ( mear_r )                  // MEAR (memory error address register)
41   AM_RANGE(0177025,                    0177025)                           AM_READWRITE( mesr_r,  mesr_w  )        // MESR (memory error status register)
42   AM_RANGE(0177026,                    0177026)                           AM_READWRITE( mecr_r,  mecr_w  )        // MECR (memory error control register)
43   AM_RANGE(0177027,                    0177027)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
44   AM_RANGE(0177030,                    0177033)                           AM_READ     ( utilin_r )                // UTILIN register
45   AM_RANGE(0177034,                    0177037)                           AM_READ     ( kbd_ad_r )                // KBD_AD[0-3] matrix
46   AM_RANGE(0177040,                    0177057)                           AM_READWRITE( bank_reg_r, bank_reg_w )  // BANK[0-17] registers (4 bit)
47   AM_RANGE(0177060,                    0177077)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
48   AM_RANGE(0177100,                    0177101)                           AM_READWRITE( noop_r, noop_w )          // { Summagraphics tablet X, Y }
49   AM_RANGE(0177102,                    0177137)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
50   AM_RANGE(0177140,                    0177157)                           AM_READWRITE( noop_r, noop_w )          // { Organ keyboard }
51   AM_RANGE(0177160,                    0177177)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
52   AM_RANGE(0177200,                    0177204)                           AM_READWRITE( noop_r, noop_w )          // { PROM programmer }
53   AM_RANGE(0177205,                    0177233)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
54   AM_RANGE(0177234,                    0177237)                           AM_READWRITE( noop_r, noop_w )          // { Experimental cursor control }
55   AM_RANGE(0177240,                    0177257)                           AM_READWRITE( noop_r, noop_w )          // { Alto-II debugger }
56//  AM_RANGE(0177244,                    0177247)                           AM_READWRITE( noop_r, noop_w )          // { Graphics keyboard }
57   AM_RANGE(0177260,                    0177377)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
58   // page 0377
59//   AM_RANGE(0177400,                    0177405)                           AM_READWRITE( noop_r, noop_w )          // { Maxc2 maintenance interface }
60   AM_RANGE(0177400,                    0177400)                           AM_READWRITE( noop_r, noop_w )          // { Alto DLS input }
61   AM_RANGE(0177401,                    0177417)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
62   AM_RANGE(0177420,                    0177420)                           AM_READWRITE( noop_r, noop_w )          // { "" }
63   AM_RANGE(0177421,                    0177437)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
64   AM_RANGE(0177440,                    0177440)                           AM_READWRITE( noop_r, noop_w )          // { "" }
65   AM_RANGE(0177441,                    0177457)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
66   AM_RANGE(0177460,                    0177460)                           AM_READWRITE( noop_r, noop_w )          // { "" }
67   AM_RANGE(0177461,                    0177577)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
68   AM_RANGE(0177600,                    0177677)                           AM_READWRITE( noop_r, noop_w )          // { Alto DLS output }
69   AM_RANGE(0177700,                    0177700)                           AM_READWRITE( noop_r, noop_w )          // { EIA interface output bit }
70   AM_RANGE(0177701,                    0177701)                           AM_READWRITE( noop_r, noop_w )          // { EIA interface input bit }
71   AM_RANGE(0177702,                    0177717)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
72   AM_RANGE(0177720,                    0177737)                           AM_READWRITE( noop_r, noop_w )          // { TV camera interface }
73   AM_RANGE(0177740,                    0177763)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
74   AM_RANGE(0177764,                    0177773)                           AM_READWRITE( noop_r, noop_w )          // { Redactron tape drive }
75   AM_RANGE(0177774,                    0177775)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
76   AM_RANGE(0177776,                    0177776)                           AM_READWRITE( noop_r, noop_w )          // { Digital-Analog Converter, Joystick }
77   AM_RANGE(0177777,                    0177777)                           AM_READWRITE( noop_r, noop_w )          // { Digital-Analog Converter, Joystick }
78
79   AM_RANGE(0200000,                    0377777)                           AM_READWRITE( ioram_r, ioram_w )
80ADDRESS_MAP_END
81
82//-------------------------------------------------
83//  alto2_cpu_device - constructor
84//-------------------------------------------------
85
86alto2_cpu_device::alto2_cpu_device(const machine_config& mconfig, const char* tag, device_t* owner, UINT32 clock) :
87   cpu_device(mconfig, ALTO2, "Xerox Alto-II", tag, owner, clock, "alto2", __FILE__),
88#if   ALTO2_DEBUG
89   m_log_types(LOG_DISPL),
90   m_log_level(8),
91   m_log_newline(true),
92#endif
93   m_ucode_config("ucode", ENDIANNESS_BIG, 32, 12, -2 ),
94   m_const_config("const", ENDIANNESS_BIG, 16,  8, -1 ),
95   m_iomem_config("iomem", ENDIANNESS_BIG, 16, 17, -1 ),
96   m_ucode_crom(0),
97   m_const_data(0),
98   m_icount(0),
99   m_task_mpc(),
100   m_task_next2(),
101   m_ntime(),
102   m_task(0),
103   m_next_task(0),
104   m_next2_task(0),
105   m_mpc(0),
106   m_mir(0),
107   m_rsel(0),
108   m_next(0),
109   m_next2(0),
110   m_r(),
111   m_s(),
112   m_bus(0),
113   m_t(0),
114   m_alu(0),
115   m_aluc0(0),
116   m_l(0),
117   m_shifter(0),
118   m_laluc0(0),
119   m_m(0),
120   m_cram_addr(0),
121   m_task_wakeup(0),
122   m_active_callback(),
123   m_reset_mode(0xffff),
124   m_rdram_flag(false),
125   m_wrtram_flag(false),
126   m_s_reg_bank(),
127   m_bank_reg(),
128   m_ether_enable(false),
129   m_ewfct(false),
130   m_dsp_time(0),
131   m_dsp_state(0),
132   m_unload_time(0),
133   m_unload_word(0),
134   m_bitclk_time(0),
135   m_bitclk_index(0),
136   m_ctl2k_u3(0),
137   m_ctl2k_u38(0),
138   m_ctl2k_u76(0),
139   m_cram3k_a37(0),
140   m_madr_a64(0),
141   m_madr_a65(0),
142   m_madr_a90(0),
143   m_madr_a91(0),
144   m_bs(),
145   m_f1(),
146   m_f2(),
147   m_ram_related(),
148   m_cycle(0),
149   m_hw(),
150   m_mouse(),
151   m_drive(),
152   m_dsk(),
153   m_sysclka0(),
154   m_sysclka1(),
155   m_sysclkb0(),
156   m_sysclkb1(),
157   m_dsp(),
158   m_disp_a38(0),
159   m_disp_a63(0),
160   m_disp_a66(0),
161   m_displ_bitmap(0),
162   m_mem(),
163   m_emu(),
164   m_ether_a41(0),
165   m_ether_a42(0),
166   m_ether_a49(0),
167   m_eth()
168{
169   m_is_octal = true;
170}
171
172alto2_cpu_device::~alto2_cpu_device()
173{
174   // call all subdevice's exit code
175   exit_kwd();
176   exit_part();
177   exit_dvt();
178   exit_dht();
179   exit_curt();
180   exit_dwt();
181   exit_mrt();
182   exit_ether();
183   exit_ksec();
184   exit_emu();
185   exit_hw();
186   exit_mouse();
187   exit_kbd();
188   exit_disp();
189   exit_disk();
190   exit_memory();
191}
192
193#if   ALTO2_DEBUG
194// FIXME: define types (sections) and print the section like [emu] [kwd] ...
195// FIXME: use the level to suppress messages if logging is less verbose than level
196void alto2_cpu_device::logprintf(int type, int level, const char* format, ...)
197{
198   static const char* type_name[] = {
199      "[CPU]",
200      "[EMU]",
201      "[T01]",
202      "[T02]",
203      "[T03]",
204      "[KSEC]",
205      "[T05]",
206      "[T06]",
207      "[ETH]",
208      "[MRT]",
209      "[DWT]",
210      "[CURT]",
211      "[DHT]",
212      "[DVT]",
213      "[PART]",
214      "[KWD]",
215      "[T17]",
216      "[MEM]",
217      "[RAM]",
218      "[DRIVE]",
219      "[DISK]",
220      "[DISPL]",
221      "[MOUSE]",
222      "[HW]",
223      "[KBD]"
224   };
225   if (!(m_log_types & type))
226      return;
227   if (level > m_log_level)
228      return;
229   if (m_log_newline) {
230      // last line had a \n - print type name
231      for (int i = 0; i < sizeof(type_name)/sizeof(type_name[0]); i++)
232         if (type & (1 << i))
233            logerror("%-7s %11lld ", type_name[i], cycle());
234   }
235   va_list ap;
236   va_start(ap, format);
237   vlogerror(format, ap);
238   va_end(ap);
239   m_log_newline = format[strlen(format) - 1] == '\n';
240}
241#endif
242
243//-------------------------------------------------
244// driver interface to set diablo_hd_device
245//-------------------------------------------------
246
247void alto2_cpu_device::set_diablo(int unit, diablo_hd_device* ptr)
248{
249   m_drive[unit] = ptr;
250}
251
252//-------------------------------------------------
253//  device_rom_region - device-specific (P)ROMs
254//-------------------------------------------------
255
256ROM_START( alto2_cpu )
257   ROM_REGION( 16 * 02000, "ucode_proms", 0 )
258   ROM_LOAD( "55x.3",     0*02000, 0x400, CRC(de870d75) SHA1(2b98cc769d8302cb39948711424d987d94e4159b) )   //!< 00000-01777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
259   ROM_LOAD( "64x.3",     1*02000, 0x400, CRC(51b444c0) SHA1(8756e51f7f3253a55d75886465beb7ee1be6e1c4) )   //!< 00000-01777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
260   ROM_LOAD( "65x.3",     2*02000, 0x400, CRC(741d1437) SHA1(01f7cf07c2173ac93799b2475180bfbbe7e0149b) )   //!< 00000-01777 ALUF(3)',BS(0)',BS(1)',BS(2)'
261   ROM_LOAD( "63x.3",     3*02000, 0x400, CRC(f22d5028) SHA1(c65a42baef702d4aff2d9ad8e363daec27de6801) )   //!< 00000-01777 F1(0),F1(1)',F1(2)',F1(3)'
262   ROM_LOAD( "53x.3",     4*02000, 0x400, CRC(3c89a740) SHA1(95d812d489b2bde03884b2f126f961caa6c8ec45) )   //!< 00000-01777 F2(0),F2(1)',F2(2)',F2(3)'
263   ROM_LOAD( "60x.3",     5*02000, 0x400, CRC(a35de0bf) SHA1(7fa4aead44dcf5393bbfd1706c0ada24aa6fd3ac) )   //!< 00000-01777 LOADT',LOADL,NEXT(0)',NEXT(1)'
264   ROM_LOAD( "61x.3",     6*02000, 0x400, CRC(f25bcb2d) SHA1(acb57f3104a8dc4ba750dd1bf22ccc81cce9f084) )   //!< 00000-01777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
265   ROM_LOAD( "62x.3",     7*02000, 0x400, CRC(1b20a63f) SHA1(41dc86438e91c12b0fe42ffcce6b2ac2eb9e714a) )   //!< 00000-01777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
266
267   // extended memory Mesa 5.1 micro code PROMs, 8 x 4bit
268   ROM_LOAD( "xm51.u54",  8*02000, 02000, CRC(11086ae9) SHA1(c394e3fadbfb91801ddc1a70cb25dc6f606c4f76) )   //!< 00000-01777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
269   ROM_LOAD( "xm51.u74",  9*02000, 02000, CRC(be8224f2) SHA1(ea9abcc3832b26a094319796901237e1e3f238b6) )   //!< 00000-01777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
270   ROM_LOAD( "xm51.u75", 10*02000, 02000, CRC(dfe3e3ac) SHA1(246fd29f92150a5d5d7627fbb4f2504c7b6cd5ec) )   //!< 00000-01777 ALUF(3)',BS(0)',BS(1)',BS(2)'
271   ROM_LOAD( "xm51.u73", 11*02000, 02000, CRC(6c20fa46) SHA1(a054330c65048011f12209aaed5c6da73d95f029) )   //!< 00000-01777 F1(0),F1(1)',F1(2)',F1(3)'
272   ROM_LOAD( "xm51.u52", 12*02000, 02000, CRC(0a31eec8) SHA1(4e2ad5daa5e6a6f2143ee4de00c7b625d096fb02) )   //!< 00000-01777 F2(0),F2(1)',F2(2)',F2(3)'
273   ROM_LOAD( "xm51.u70", 13*02000, 02000, CRC(5c64ee54) SHA1(0eb16d1b5e5967be7c1bf8c8ef6efdf0518a752c) )   //!< 00000-01777 LOADT',LOADL,NEXT(0)',NEXT(1)'
274   ROM_LOAD( "xm51.u71", 14*02000, 02000, CRC(7283bf71) SHA1(819fdcc407ed0acdd8f12b02db6efbcab7bec19a) )   //!< 00000-01777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
275   ROM_LOAD( "xm51.u72", 15*02000, 02000, CRC(a28e5251) SHA1(44dd8ad4ad56541b5394d30ce3521b4d1d561394) )   //!< 00000-01777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
276
277   // constant PROMs, 4 x 4bit
278   // UINT16 src = BITS(addr, 3,2,1,4,5,6,7,0);
279   ROM_REGION( 4 * 0400, "const_proms", 0 )
280   ROM_LOAD( "madr.a6",   0*00400, 00400, CRC(c2c196b2) SHA1(8b2a599ac839ec2a070dbfef2f1626e645c858ca) )   //!< 0000-0377 C(00)',C(01)',C(02)',C(03)'
281   ROM_LOAD( "madr.a5",   1*00400, 00400, CRC(42336101) SHA1(c77819cf40f063af3abf66ea43f17cc1a62e928b) )   //!< 0000-0377 C(04)',C(05)',C(06)',C(07)'
282   ROM_LOAD( "madr.a4",   2*00400, 00400, CRC(b957e490) SHA1(c72660ad3ada4ca0ed8697c6bb6275a4fe703184) )   //!< 0000-0377 C(08)',C(09)',C(10)',C(11)'
283   ROM_LOAD( "madr.a3",   3*00400, 00400, CRC(e0992757) SHA1(5c45ea824970663cb9ee672dc50861539c860249) )   //!< 0000-0377 C(12)',C(13)',C(14)',C(15)'
284
285   // extended memory Mesa 4.1 (?) micro code PROMs, 8 x 4bit (unused)
286   ROM_REGION( 8 * 02000, "xm_mesa_4.1", 0 )
287   ROM_LOAD( "xm654.41",  0*02000, 02000, CRC(beace302) SHA1(0002fea03a0261f57365095c4b87385d833f7063) )   //!< 00000-01777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
288   ROM_LOAD( "xm674.41",  1*02000, 02000, CRC(7db5c097) SHA1(364bc41951baa3ad274031bd49abec1cf5b7a980) )   //!< 00000-01777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
289   ROM_LOAD( "xm675.41",  2*02000, 02000, CRC(26eac1e7) SHA1(9220a1386afae8de96bdb2cf084afbadeeb61d42) )   //!< 00000-01777 ALUF(3)',BS(0)',BS(1)',BS(2)'
290   ROM_LOAD( "xm673.41",  3*02000, 02000, CRC(8173d7e3) SHA1(7fbacf6dccb60dfe9cef88a248c3a1660efddcf4) )   //!< 00000-01777 F1(0),F1(1)',F1(2)',F1(3)'
291   ROM_LOAD( "xm652.41",  4*02000, 02000, CRC(ddfa94bb) SHA1(38625e269400aaf38cd07b5dbf36c0087a0f1b92) )   //!< 00000-01777 F2(0),F2(1)',F2(2)',F2(3)'
292   ROM_LOAD( "xm670.41",  5*02000, 02000, CRC(1cd187f3) SHA1(0fd5eff7c6b5c2383aa20148a795b80286554675) )   //!< 00000-01777 LOADT',LOADL,NEXT(0)',NEXT(1)'
293   ROM_LOAD( "xm671.41",  6*02000, 02000, CRC(f21b1ad7) SHA1(1e18bdb35de7802892ac373c128f900786d40886) )   //!< 00000-01777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
294   ROM_LOAD( "xm672.41",  7*02000, 02000, CRC(110ee075) SHA1(bb72fceba5ce9e5e8c8a0024915006bdd011a3f3) )   //!< 00000-01777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
295
296   ROM_REGION( 0400, "2kctl_u3", 0 )
297   ROM_LOAD( "2kctl.u3",   00000, 00400, CRC(5f8d89e8) SHA1(487cd944ab074290aea73425e81ef4900d92e250) )   //!< 3601-1 256x4 BPROM; Emulator address modifier
298
299   ROM_REGION( 0400, "2kctl_u38", 0 )
300   ROM_LOAD( "2kctl.u38",  00000, 00040, CRC(fc51b1d1) SHA1(e36c2a12a5da377394264899b5ae504e2ffda46e) )   //!< 82S23 32x8 BPROM; task priority and initial address
301
302   ROM_REGION( 0400, "2kctl_u76", 0 )
303   ROM_LOAD( "2kctl.u76",  00000, 00400, CRC(1edef867) SHA1(928b8a15ac515a99109f32672441832173883b81) )   //!< 3601-1 256x4 BPROM; 2KCTL replacement for u51 (1KCTL)
304
305   ROM_REGION( 0040, "alu_a10", 0 )
306   ROM_LOAD( "alu.a10",    00000, 00040, CRC(e0857892) SHA1(dcd389767139f0acc1f87cf074459115abc5b90b) )
307
308   ROM_REGION( 0400, "3kcram_a37", 0 )
309   ROM_LOAD( "3kcram.a37", 00000, 00400, CRC(9417360d) SHA1(bfcdbc56ee4ffafd0f2f672c0c869a55d6dd194b) )
310
311   ROM_REGION( 0400, "madr_a32", 0 )
312   ROM_LOAD( "madr.a32",   00000, 00400, CRC(a0e3b4a7) SHA1(24e50afdeb637a6a8588f8d3a3493c9188b8da2c) )   //! P3601 256x4 BPROM; mouse motion signals MX1, MX2, MY1, MY2
313
314   ROM_REGION( 0400, "madr_a64", 0 )
315   ROM_LOAD( "madr.a64",   00000, 00400, CRC(a66b0eda) SHA1(4d9088f592caa3299e90966b17765be74e523144) )   //! P3601 256x4 BPROM; memory addressing
316
317   ROM_REGION( 0400, "madr_a65", 0 )
318   ROM_LOAD( "madr.a65",   00000, 00400, CRC(ba37febd) SHA1(82e9db1cb65f451755295f0d179e6f8fe3349d4d) )   //! P3601 256x4 BPROM; memory addressing
319
320   ROM_REGION( 0400, "madr_a90", 0 )
321   ROM_LOAD( "madr.a90",   00000, 00400, CRC(7a2d8799) SHA1(c3760dba147740729d33b9b88e59088a4cc7437a) )
322
323   ROM_REGION( 0400, "madr_a91", 0 )
324   ROM_LOAD( "madr.a91",   00000, 00400, CRC(dd556aeb) SHA1(900f333a091e3ccde0843019c25f25fba62e6023) )
325
326   ROM_REGION( 0400, "displ_a38", 0 )
327   ROM_LOAD( "displ.a38",  00000, 00400, CRC(fd30beb7) SHA1(65e4a19ba4ff748d525122128c514abedd55d866) )   //!< P3601 256x4 BPROM; display FIFO control: STOPWAKE, MBEMPTY
328
329   ROM_REGION( 0040, "displ_a63", 0 )
330   ROM_LOAD( "displ.a63",  00000, 00040, CRC(82a20d60) SHA1(39d90703568be5419ada950e112d99227873fdea) )   //!< 82S23 32x8 BPROM; display HBLANK, HSYNC, SCANEND, HLCGATE ...
331
332   ROM_REGION( 0400, "displ_a66", 0 )
333   ROM_LOAD( "displ.a66",  00000, 00400, CRC(9f91aad9) SHA1(69b1d4c71f4e18103112e8601850c2654e9265cf) )   //!< P3601 256x4 BPROM; display VSYNC and VBLANK
334
335   ROM_REGION( 0400, "ether_a41", 0 )
336   ROM_LOAD( "enet.a41",   00000, 00400, CRC(d5de8d86) SHA1(c134a4c898c73863124361a9b0218f7a7f00082a) )
337
338   ROM_REGION( 0400, "ether_a42", 0 )
339   ROM_LOAD( "enet.a42",   00000, 00400, CRC(9d5c81bd) SHA1(ac7e63332a3dad0bef7cd0349b24e156a96a4bf0) )
340
341   ROM_REGION( 0400, "ether_a49", 0 )
342   ROM_LOAD( "enet.a49",   00000, 00400, CRC(4d2dcdb2) SHA1(583327a7d70cd02702c941c0e43c1e9408ff7fd0) )
343ROM_END
344
345const rom_entry *alto2_cpu_device::device_rom_region() const
346{
347   return ROM_NAME( alto2_cpu );
348}
349
350//-------------------------------------------------
351// device_memory_interface overrides
352//-------------------------------------------------
353
354const address_space_config*alto2_cpu_device::memory_space_config(address_spacenum spacenum) const
355{
356   if (AS_0 == spacenum)
357      return &m_ucode_config;
358   if (AS_1 == spacenum)
359      return &m_const_config;
360   if (AS_2 == spacenum)
361      return &m_iomem_config;
362   return NULL;
363}
364
365/**
366 * @brief list of microcode PROM loading options
367 */
368static const prom_load_t pl_ucode[] = {
369   {   // 0000-01777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
370      "55x.3",
371      0,
372      "de870d75",
373      "2b98cc769d8302cb39948711424d987d94e4159b",
374/* size */   ALTO2_UCODE_PAGE_SIZE,
375/* amap */   AMAP_DEFAULT,
376/* axor */   ALTO2_UCODE_PAGE_MASK,
377/* dxor */   017,                  // invert D0-D3
378/* width */   4,
379/* shift */   28,
380/* dmap */   DMAP_DEFAULT,
381/* dand */   ZERO,
382/* type */   sizeof(UINT32)
383   },
384   {   // 0000-01777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
385      "64x.3",
386      0,
387      "51b444c0",
388      "8756e51f7f3253a55d75886465beb7ee1be6e1c4",
389/* size */   ALTO2_UCODE_PAGE_SIZE,
390/* amap */   AMAP_DEFAULT,
391/* axor */   ALTO2_UCODE_PAGE_MASK,
392/* dxor */   017,                  // invert D0-D3
393/* width */   4,
394/* shift */   24,
395/* dmap */   DMAP_DEFAULT,
396/* dand */   KEEP,
397/* type */   sizeof(UINT32)
398   },
399   {   // 0000-01777 ALUF(3)',BS(0)',BS(1)',BS(2)'
400      "65x.3",
401      0,
402      "741d1437",
403      "01f7cf07c2173ac93799b2475180bfbbe7e0149b",
404/* size */   ALTO2_UCODE_PAGE_SIZE,
405/* amap */   AMAP_DEFAULT,
406/* axor */   ALTO2_UCODE_PAGE_MASK,
407/* dxor */   017,                  // invert D0-D3
408/* width */   4,
409/* shift */   20,
410/* dmap */   DMAP_DEFAULT,
411/* dand */   KEEP,
412/* type */   sizeof(UINT32)
413   },
414   {   // 0000-01777 F1(0),F1(1)',F1(2)',F1(3)'
415      "63x.3",
416      0,
417      "f22d5028",
418      "c65a42baef702d4aff2d9ad8e363daec27de6801",
419/* size */   ALTO2_UCODE_PAGE_SIZE,
420/* amap */   AMAP_DEFAULT,
421/* axor */   ALTO2_UCODE_PAGE_MASK,
422/* dxor */   007,                  // keep D0, invert D1-D3
423/* width */   4,
424/* shift */   16,
425/* dmap */   DMAP_DEFAULT,
426/* dand */   KEEP,
427/* type */   sizeof(UINT32)
428   },
429   {   // 0000-01777 F2(0),F2(1)',F2(2)',F2(3)'
430      "53x.3",
431      0,
432      "3c89a740",
433      "95d812d489b2bde03884b2f126f961caa6c8ec45",
434/* size */   ALTO2_UCODE_PAGE_SIZE,
435/* amap */   AMAP_DEFAULT,
436/* axor */   ALTO2_UCODE_PAGE_MASK,
437/* dxor */   007,                  // keep D0, invert D1-D3
438/* width */   4,
439/* shift */   12,
440/* dmap */   DMAP_DEFAULT,
441/* dand */   KEEP,
442/* type */   sizeof(UINT32)
443   },
444   {   // 0000-01777 LOADT',LOADL,NEXT(0)',NEXT(1)'
445      "60x.3",
446      0,
447      "a35de0bf",
448      "7fa4aead44dcf5393bbfd1706c0ada24aa6fd3ac",
449/* size */   ALTO2_UCODE_PAGE_SIZE,
450/* amap */   AMAP_DEFAULT,
451/* axor */   ALTO2_UCODE_PAGE_MASK,
452/* dxor */   013,                  // invert D0 and D2-D3
453/* width */   4,
454/* shift */   8,
455/* dmap */   DMAP_DEFAULT,
456/* dand */   KEEP,
457/* type */   sizeof(UINT32)
458   },
459   {   // 0000-01777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
460      "61x.3",
461      0,
462      "f25bcb2d",
463      "acb57f3104a8dc4ba750dd1bf22ccc81cce9f084",
464/* size */   ALTO2_UCODE_PAGE_SIZE,
465/* amap */   AMAP_DEFAULT,
466/* axor */   ALTO2_UCODE_PAGE_MASK,
467/* dxor */   017,                  // invert D0-D3
468/* width */   4,
469/* shift */   4,
470/* dmap */   DMAP_DEFAULT,
471/* dand */   KEEP,
472/* type */   sizeof(UINT32)
473   },
474   {   // 0000-01777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
475      "62x.3",
476      0,
477      "1b20a63f",
478      "41dc86438e91c12b0fe42ffcce6b2ac2eb9e714a",
479/* size */   ALTO2_UCODE_PAGE_SIZE,
480/* amap */   AMAP_DEFAULT,
481/* axor */   ALTO2_UCODE_PAGE_MASK,
482/* dxor */   017,                  // invert D0-D3
483/* width */   4,
484/* shift */   0,
485/* dmap */   DMAP_DEFAULT,
486/* dand */   KEEP,
487/* type */   sizeof(UINT32)
488   }
489
490#if   (ALTO2_UCODE_ROM_PAGES > 1)
491   ,
492   {   // 02000-03777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
493      "xm51.u54",
494      0,
495      "11086ae9",
496      "c394e3fadbfb91801ddc1a70cb25dc6f606c4f76",
497/* size */   ALTO2_UCODE_PAGE_SIZE,
498/* amap */   AMAP_DEFAULT,
499/* axor */   ALTO2_UCODE_PAGE_MASK,
500/* dxor */   017,                  // invert D0-D3
501/* width */   4,
502/* shift */   28,
503/* dmap */   DMAP_DEFAULT,
504/* dand */   ZERO,
505/* type */   sizeof(UINT32)
506   },
507   {   // 02000-03777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
508      "xm51.u74",
509      0,
510      "be8224f2",
511      "ea9abcc3832b26a094319796901237e1e3f238b6",
512/* size */   ALTO2_UCODE_PAGE_SIZE,
513/* amap */   AMAP_DEFAULT,
514/* axor */   ALTO2_UCODE_PAGE_MASK,
515/* dxor */   017,                  // invert D0-D3
516/* width */   4,
517/* shift */   24,
518/* dmap */   DMAP_DEFAULT,
519/* dand */   KEEP,
520/* type */   sizeof(UINT32)
521   },
522   {   // 02000-03777 ALUF(3)',BS(0)',BS(1)',BS(2)'
523      "xm51.u75",
524      0,
525      "dfe3e3ac",
526      "246fd29f92150a5d5d7627fbb4f2504c7b6cd5ec",
527/* size */   ALTO2_UCODE_PAGE_SIZE,
528/* amap */   AMAP_DEFAULT,
529/* axor */   ALTO2_UCODE_PAGE_MASK,
530/* dxor */   017,                  // invert D0-D3
531/* width */   4,
532/* shift */   20,
533/* dmap */   DMAP_DEFAULT,
534/* dand */   KEEP,
535/* type */   sizeof(UINT32)
536   },
537   {   // 02000-03777 F1(0),F1(1)',F1(2)',F1(3)'
538      "xm51.u73",
539      0,
540      "6c20fa46",
541      "a054330c65048011f12209aaed5c6da73d95f029",
542/* size */   ALTO2_UCODE_PAGE_SIZE,
543/* amap */   AMAP_DEFAULT,
544/* axor */   ALTO2_UCODE_PAGE_MASK,
545/* dxor */   007,                  // keep D0, invert D1-D3
546/* width */   4,
547/* shift */   16,
548/* dmap */   DMAP_DEFAULT,
549/* dand */   KEEP,
550/* type */   sizeof(UINT32)
551   },
552   {   // 02000-03777 F2(0),F2(1)',F2(2)',F2(3)'
553      "xm51.u52",
554      0,
555      "0a31eec8",
556      "4e2ad5daa5e6a6f2143ee4de00c7b625d096fb02",
557/* size */   ALTO2_UCODE_PAGE_SIZE,
558/* amap */   AMAP_DEFAULT,
559/* axor */   ALTO2_UCODE_PAGE_MASK,
560/* dxor */   007,                  // keep D0, invert D1-D3
561/* width */   4,
562/* shift */   12,
563/* dmap */   DMAP_DEFAULT,
564/* dand */   KEEP,
565/* type */   sizeof(UINT32)
566   },
567   {   // 02000-03777 LOADT',LOADL,NEXT(0)',NEXT(1)'
568      "xm51.u70",
569      0,
570      "5c64ee54",
571      "0eb16d1b5e5967be7c1bf8c8ef6efdf0518a752c",
572/* size */   ALTO2_UCODE_PAGE_SIZE,
573/* amap */   AMAP_DEFAULT,
574/* axor */   ALTO2_UCODE_PAGE_MASK,
575/* dxor */   013,                  // invert D0 and D2-D3
576/* width */   4,
577/* shift */   8,
578/* dmap */   DMAP_DEFAULT,
579/* dand */   KEEP,
580/* type */   sizeof(UINT32)
581   },
582   {   // 02000-03777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
583      "xm51.u71",
584      0,
585      "7283bf71",
586      "819fdcc407ed0acdd8f12b02db6efbcab7bec19a",
587/* size */   ALTO2_UCODE_PAGE_SIZE,
588/* amap */   AMAP_DEFAULT,
589/* axor */   ALTO2_UCODE_PAGE_MASK,
590/* dxor */   017,                  // invert D0-D3
591/* width */   4,
592/* shift */   4,
593/* dmap */   DMAP_DEFAULT,
594/* dand */   KEEP,
595/* type */   sizeof(UINT32)
596   },
597   {   // 02000-03777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
598      "xm51.u72",
599      0,
600      "a28e5251",
601      "44dd8ad4ad56541b5394d30ce3521b4d1d561394",
602/* size */   ALTO2_UCODE_PAGE_SIZE,
603/* amap */   AMAP_DEFAULT,
604/* axor */   ALTO2_UCODE_PAGE_MASK,
605/* dxor */   017,                  // invert D0-D3
606/* width */   4,
607/* shift */   0,
608/* dmap */   DMAP_DEFAULT,
609/* dand */   KEEP,
610/* type */   sizeof(UINT32)
611    }
612#endif   // (UCODE_ROM_PAGES > 1)
613};
614
615/**
616 * @brief list of constant PROM loading options
617 */
618static const prom_load_t pl_const[] = {
619   {   // constant prom D0-D3
620      "madr.a6",
621      "c3.3",
622      "c2c196b2",
623      "8b2a599ac839ec2a070dbfef2f1626e645c858ca",
624/* size */   ALTO2_CONST_SIZE,
625/* amap */   AMAP_CONST_PROM,         // descramble constant address
626/* axor */   0,
627/* dxor */   017,                  // invert D0-D3
628/* width */   4,
629/* shift */   0,
630/* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
631/* dand */   ZERO,
632/* type */   sizeof(UINT16)
633   },
634   {   // constant prom D4-D7
635      "madr.a5",
636      "c2.3",
637      "42336101",
638      "c77819cf40f063af3abf66ea43f17cc1a62e928b",
639/* size */   ALTO2_CONST_SIZE,
640/* amap */   AMAP_CONST_PROM,         // descramble constant address
641/* axor */   0,
642/* dxor */   017,                  // invert D0-D3
643/* width */   4,
644/* shift */   4,
645/* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
646/* dand */   KEEP,
647/* type */   sizeof(UINT16)
648   },
649   {   // constant prom D8-D11
650      "madr.a4",
651      "c1.3",
652      "b957e490",
653      "c72660ad3ada4ca0ed8697c6bb6275a4fe703184",
654/* size */   ALTO2_CONST_SIZE,
655/* amap */   AMAP_CONST_PROM,         // descramble constant address
656/* axor */   0,
657/* dxor */   017,                  // invert D0-D3
658/* width */   4,
659/* shift */   8,
660/* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
661/* dand */   KEEP,
662/* type */   sizeof(UINT16)
663   },
664   {   // constant PROM D12-D15
665      "madr.a3",
666      "c0.3",
667      "e0992757",
668      "5c45ea824970663cb9ee672dc50861539c860249",
669/* size */   ALTO2_CONST_SIZE,
670/* amap */   AMAP_CONST_PROM,         // descramble constant address
671/* axor */   0,
672/* dxor */   017,                  // invert D0-D3
673/* width */   4,
674/* shift */   12,
675/* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
676/* dand */   KEEP,
677/* type */   sizeof(UINT16)
678   }
679};
680
681//! 82S23 32x8 BPROM; display HBLANK, HSYNC, SCANEND, HLCGATE ...
682static const prom_load_t pl_displ_a63 =
683{
684   "displ.a63",
685   0,
686   "82a20d60",
687   "39d90703568be5419ada950e112d99227873fdea",
688   /* size */   0040,
689   /* amap */   AMAP_DEFAULT,
690   /* axor */   0,
691   /* dxor */   0,
692   /* width */   8,
693   /* shift */   0,
694   /* dmap */   DMAP_DEFAULT,
695   /* dand */   ZERO,
696   /* type */   sizeof(UINT8)
697};
698
699//! P3601 256x4 BPROM; display FIFO control: STOPWAKE, MBEMPTY
700static const prom_load_t pl_displ_a38 =
701{
702   "displ.a38",
703   0,
704   "fd30beb7",
705   "65e4a19ba4ff748d525122128c514abedd55d866",
706   /* size */   0400,
707   /* amap */   AMAP_REVERSE_0_7,         // reverse address lines A0-A7
708   /* axor */   0,
709   /* dxor */   0,
710   /* width */   4,
711   /* shift */   0,
712   /* dmap */   DMAP_DEFAULT,
713   /* dand */   ZERO,
714   /* type */   sizeof(UINT8)
715};
716
717//! P3601 256x4 BPROM; display VSYNC and VBLANK
718static const prom_load_t pl_displ_a66 =
719{
720   "displ.a66",
721   0,
722   "9f91aad9",
723   "69b1d4c71f4e18103112e8601850c2654e9265cf",
724   /* size */   0400,
725   /* amap */   AMAP_DEFAULT,
726   /* axor */   0,
727   /* dxor */   0,
728   /* width */   4,
729   /* shift */   0,
730   /* dmap */   DMAP_DEFAULT,
731   /* dand */   ZERO,
732   /* type */   sizeof(UINT8)
733};
734
735//! 3601-1 256x4 BPROM; Emulator address modifier
736static const prom_load_t pl_2kctl_u3 =
737{
738   "2kctl.u3",
739   0,
740   "5f8d89e8",
741   "487cd944ab074290aea73425e81ef4900d92e250",
742   /* size */   0400,
743   /* amap */   AMAP_REVERSE_0_7,         // reverse address lines A0-A7
744   /* axor */   0377,                  // invert address lines A0-A7
745   /* dxor */   017,                  // invert data lines D0-D3
746   /* width */   4,
747   /* shift */   0,
748   /* dmap */   DMAP_DEFAULT,
749   /* dand */   ZERO,
750   /* type */   sizeof(UINT8)
751};
752
753//! 82S23 32x8 BPROM; task priority and initial address
754static const prom_load_t pl_2kctl_u38 =
755{
756   "2kctl.u38",
757   0,
758   "fc51b1d1",
759   "e36c2a12a5da377394264899b5ae504e2ffda46e",
760   /* size */   0040,
761   /* amap */   AMAP_DEFAULT,
762   /* axor */   0,
763   /* dxor */   0,
764   /* width */   8,
765   /* shift */   0,
766   /* dmap */   DMAP_DEFAULT,
767   /* dand */   ZERO,
768   /* type */   sizeof(UINT8)
769};
770
771//! 3601-1 256x4 BPROM; 2KCTL replacement for u51 (1KCTL)
772static const prom_load_t pl_2kctl_u76 =
773{
774   "2kctl.u76",
775   0,
776   "1edef867",
777   "928b8a15ac515a99109f32672441832173883b81",
778   /* size */   0400,
779   /* amap */   AMAP_DEFAULT,
780   /* axor */   0077,                  // invert address lines A0-A5
781   /* dxor */   0,
782   /* width */   4,
783   /* shift */   0,
784   /* dmap */   DMAP_DEFAULT,
785   /* dand */   ZERO,
786   /* type */   sizeof(UINT8)
787};
788
789//! ALUF to ALU 741818 functions and carry in mapper
790static const prom_load_t pl_alu_a10 =
791{
792   "alu.a10",
793   0,
794   "e0857892",
795   "dcd389767139f0acc1f87cf074459115abc5b90b",
796   /* size */   0040,
797   /* amap */   AMAP_DEFAULT,
798   /* axor */   0,
799   /* dxor */   0372,                  // invert D7-D3 and D1
800   /* width */   8,
801   /* shift */   0,
802   /* dmap */   DMAP_DEFAULT,
803   /* dand */   ZERO,
804   /* type */   sizeof(UINT8)
805};
806
807static const prom_load_t pl_3kcram_a37 =
808{
809   "3kcram.a37",
810   0,
811   "9417360d",
812   "bfcdbc56ee4ffafd0f2f672c0c869a55d6dd194b",
813   /* size */   0400,
814   /* amap */   AMAP_DEFAULT,
815   /* axor */   0,
816   /* dxor */   017,                  // invert D0-D3
817   /* width */   4,
818   /* shift */   0,
819   /* dmap */   DMAP_DEFAULT,
820   /* dand */   ZERO,
821   /* type */   sizeof(UINT8)
822};
823
824static const prom_load_t pl_madr_a32 =
825{
826   "madr.a32",
827   0,
828   "a0e3b4a7",
829   "24e50afdeb637a6a8588f8d3a3493c9188b8da2c",
830   /* size */   0400,
831   /* amap */   AMAP_DEFAULT,
832   /* axor */   0,
833   /* dxor */   017,                  // invert D0-D3
834   /* width */   4,
835   /* shift */   0,
836   /* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
837   /* dand */   ZERO,
838   /* type */   sizeof(UINT8)
839};
840
841static const prom_load_t pl_madr_a64 =
842{
843   "madr.a64",
844   0,
845   "a66b0eda",
846   "4d9088f592caa3299e90966b17765be74e523144",
847   /* size */   0400,
848   /* amap */   AMAP_DEFAULT,
849   /* axor */   0,
850   /* dxor */   017,                  // invert D0-D3
851   /* width */   4,
852   /* shift */   0,
853   /* dmap */   DMAP_DEFAULT,
854   /* dand */   ZERO,
855   /* type */   sizeof(UINT8)
856};
857
858static const prom_load_t pl_madr_a65 =
859{
860   "madr.a65",
861   0,
862   "ba37febd",
863   "82e9db1cb65f451755295f0d179e6f8fe3349d4d",
864   /* size */   0400,
865   /* amap */   AMAP_DEFAULT,
866   /* axor */   0,
867   /* dxor */   017,                  // invert D0-D3
868   /* width */   4,
869   /* shift */   0,
870   /* dmap */   DMAP_DEFAULT,
871   /* dand */   ZERO,
872   /* type */   sizeof(UINT8)
873};
874
875static const prom_load_t pl_madr_a90 =
876{
877   "madr.a90",
878   0,
879   "7a2d8799",
880   "c3760dba147740729d33b9b88e59088a4cc7437a",
881   /* size */   0400,
882   /* amap */   AMAP_DEFAULT,
883   /* axor */   0,
884   /* dxor */   017,                  // invert D0-D3
885   /* width */   4,
886   /* shift */   0,
887   /* dmap */   DMAP_DEFAULT,
888   /* dand */   ZERO,
889   /* type */   sizeof(UINT8)
890};
891
892static const prom_load_t pl_madr_a91 =
893{
894   "madr.a91",
895   0,
896   "dd556aeb",
897   "900f333a091e3ccde0843019c25f25fba62e6023",
898   /* size */   0400,
899   /* amap */   AMAP_DEFAULT,
900   /* axor */   0,
901   /* dxor */   017,                  // invert D0-D3
902   /* width */   4,
903   /* shift */   0,
904   /* dmap */   DMAP_DEFAULT,
905   /* dand */   ZERO,
906   /* type */   sizeof(UINT8)
907};
908
909static const prom_load_t pl_enet_a41 =
910{   /* P3601 256x4 BPROM; Ethernet phase encoder 1 "PE1" */
911   "enet.a41",
912   0,
913   "d5de8d86",
914   "c134a4c898c73863124361a9b0218f7a7f00082a",
915   /* size */   0400,
916   /* amap */   AMAP_DEFAULT,
917   /* axor */   0,
918   /* dxor */   0,
919   /* width */   4,
920   /* shift */   0,
921   /* dmap */   DMAP_DEFAULT,
922   /* dand */   ZERO,
923   /* type */   sizeof(UINT8)
924};
925
926static const prom_load_t pl_enet_a42 =
927{   /* P3601 256x4 BPROM; Ethernet phase encoder 2 "PE2" */
928   "enet.a42",
929   0,
930   "9d5c81bd",
931   "ac7e63332a3dad0bef7cd0349b24e156a96a4bf0",
932   /* size */   0400,
933   /* amap */   AMAP_DEFAULT,
934   /* axor */   0,
935   /* dxor */   0,
936   /* width */   4,
937   /* shift */   0,
938   /* dmap */   DMAP_DEFAULT,
939   /* dand */   ZERO,
940   /* type */   sizeof(UINT8)
941};
942
943static const prom_load_t pl_enet_a49 =
944{   /* P3601 256x4 BPROM; Ethernet FIFO control "AFIFO" */
945   "enet.a49",
946   0,
947   "4d2dcdb2",
948   "583327a7d70cd02702c941c0e43c1e9408ff7fd0",
949   /* size */   0400,
950   /* amap */   AMAP_REVERSE_0_7,            // reverse address lines A0-A7
951   /* axor */   0,
952   /* dxor */   0,
953   /* width */   4,
954   /* shift */   0,
955   /* dmap */   DMAP_DEFAULT,
956   /* dand */   ZERO,
957   /* type */   sizeof(UINT8)
958};
959
960//-------------------------------------------------
961//  device_start - device-specific startup
962//-------------------------------------------------
963
964// FIXME
965void alto2_cpu_device::device_start()
966{
967   // get a pointer to the IO address space
968   m_iomem = &space(AS_2);
969
970   // decode micro code PROMs to CROM
971   m_ucode_crom = prom_load(machine(), pl_ucode, memregion("ucode_proms")->base(), ALTO2_UCODE_ROM_PAGES, 8);
972
973   // allocate micro code CRAM
974   m_ucode_cram = auto_alloc_array(machine(), UINT8, sizeof(UINT32) * ALTO2_UCODE_RAM_PAGES * ALTO2_UCODE_PAGE_SIZE);
975   // fill with inverted bits value
976   for (offs_t offset = 0; offset < ALTO2_UCODE_RAM_PAGES * ALTO2_UCODE_PAGE_SIZE; offset++)
977      *reinterpret_cast<UINT32 *>(m_ucode_cram + offset * 4) = ALTO2_UCODE_INVERTED;
978
979   // decode constant PROMs to const data
980   m_const_data = prom_load(machine(), pl_const, memregion("const_proms")->base(), 1, 4);
981
982   m_disp_a38 = prom_load(machine(), &pl_displ_a38, memregion("displ_a38")->base());
983   m_disp_a63 = prom_load(machine(), &pl_displ_a63, memregion("displ_a63")->base());
984   m_disp_a66 = prom_load(machine(), &pl_displ_a66, memregion("displ_a66")->base());
985   m_ctl2k_u3 = prom_load(machine(), &pl_2kctl_u3, memregion("2kctl_u3")->base());
986   m_ctl2k_u38 = prom_load(machine(), &pl_2kctl_u38, memregion("2kctl_u38")->base());
987   m_ctl2k_u76 = prom_load(machine(), &pl_2kctl_u76, memregion("2kctl_u76")->base());
988   m_alu_a10 = prom_load(machine(), &pl_alu_a10, memregion("alu_a10")->base());
989   m_cram3k_a37 = prom_load(machine(), &pl_3kcram_a37, memregion("3kcram_a37")->base());
990   m_madr_a32 = prom_load(machine(), &pl_madr_a32, memregion("madr_a32")->base());
991   m_madr_a64 = prom_load(machine(), &pl_madr_a64, memregion("madr_a64")->base());
992   m_madr_a65 = prom_load(machine(), &pl_madr_a65, memregion("madr_a65")->base());
993   m_madr_a90 = prom_load(machine(), &pl_madr_a90, memregion("madr_a90")->base());
994   m_madr_a91 = prom_load(machine(), &pl_madr_a91, memregion("madr_a91")->base());
995   m_ether_a41 = prom_load(machine(), &pl_enet_a41, memregion("ether_a41")->base());
996   m_ether_a42 = prom_load(machine(), &pl_enet_a42, memregion("ether_a42")->base());
997   m_ether_a49 = prom_load(machine(), &pl_enet_a49, memregion("ether_a49")->base());
998
999#if   0   // dump ALU a10 PROM after loading
1000   for (UINT8 i = 0; i < 32; i++) {
1001      UINT8 a = m_alu_a10[i];
1002      printf("%03o: S3-S0:%u%u%u%u M:%u CI:%u T:%u ?:%u\n",
1003            i, (a >> 7) & 1, (a >> 6) & 1, (a >> 5) & 1, (a >> 4) & 1,
1004            (a >> 3) & 1, (a >> 2) & 1, (a >> 1) & 1, (a >> 0) & 1);
1005   }
1006#endif
1007   save_item(NAME(m_task_mpc));
1008   save_item(NAME(m_task_next2));
1009   save_item(NAME(m_ntime));
1010   save_item(NAME(m_task));
1011   save_item(NAME(m_next_task));
1012   save_item(NAME(m_next2_task));
1013   save_item(NAME(m_mpc));
1014   save_item(NAME(m_mir));
1015   save_item(NAME(m_rsel));
1016   save_item(NAME(m_next));
1017   save_item(NAME(m_next2));
1018   save_item(NAME(m_r));
1019   save_item(NAME(m_s));
1020   save_item(NAME(m_bus));
1021   save_item(NAME(m_t));
1022   save_item(NAME(m_alu));
1023   save_item(NAME(m_aluc0));
1024   save_item(NAME(m_l));
1025   save_item(NAME(m_shifter));
1026   save_item(NAME(m_laluc0));
1027   save_item(NAME(m_m));
1028   save_item(NAME(m_cram_addr));
1029   save_item(NAME(m_task_wakeup));
1030   save_item(NAME(m_reset_mode));
1031   save_item(NAME(m_rdram_flag));
1032   save_item(NAME(m_wrtram_flag));
1033   save_item(NAME(m_s_reg_bank));
1034   save_item(NAME(m_bank_reg));
1035   save_item(NAME(m_ether_enable));
1036   save_item(NAME(m_ewfct));
1037   save_item(NAME(m_dsp_time));
1038   save_item(NAME(m_dsp_state));
1039   save_item(NAME(m_unload_time));
1040   save_item(NAME(m_unload_word));
1041#if   (USE_BITCLK_TIMER == 0)
1042   save_item(NAME(m_bitclk_time));
1043   save_item(NAME(m_bitclk_index));
1044#endif
1045   save_item(NAME(m_mouse.x));
1046   save_item(NAME(m_mouse.y));
1047   save_item(NAME(m_mouse.dx));
1048   save_item(NAME(m_mouse.dy));
1049   save_item(NAME(m_mouse.latch));
1050   save_item(NAME(m_dsk.drive));
1051   save_item(NAME(m_dsk.kaddr));
1052   save_item(NAME(m_dsk.kadr));
1053   save_item(NAME(m_dsk.kstat));
1054   save_item(NAME(m_dsk.kcom));
1055   save_item(NAME(m_dsk.krecno));
1056   save_item(NAME(m_dsk.shiftin));
1057   save_item(NAME(m_dsk.shiftout));
1058   save_item(NAME(m_dsk.datain));
1059   save_item(NAME(m_dsk.dataout));
1060   save_item(NAME(m_dsk.krwc));
1061   save_item(NAME(m_dsk.kfer));
1062   save_item(NAME(m_dsk.wdtskena));
1063   save_item(NAME(m_dsk.wdinit0));
1064   save_item(NAME(m_dsk.wdinit));
1065   save_item(NAME(m_dsk.strobe));
1066   save_item(NAME(m_dsk.bitclk));
1067   save_item(NAME(m_dsk.datin));
1068   save_item(NAME(m_dsk.bitcount));
1069   save_item(NAME(m_dsk.carry));
1070   save_item(NAME(m_dsk.seclate));
1071   save_item(NAME(m_dsk.seekok));
1072   save_item(NAME(m_dsk.ok_to_run));
1073   save_item(NAME(m_dsk.ready_mf31a));
1074   save_item(NAME(m_dsk.seclate_mf31b));
1075#if   0
1076   save_item(NAME(m_dsk.ff_21a));
1077   save_item(NAME(m_dsk.ff_21a_old));
1078   save_item(NAME(m_dsk.ff_21b));
1079   save_item(NAME(m_dsk.ff_22a));
1080   save_item(NAME(m_dsk.ff_22b));
1081   save_item(NAME(m_dsk.ff_43b));
1082   save_item(NAME(m_dsk.ff_53a));
1083   save_item(NAME(m_dsk.ff_43a));
1084   save_item(NAME(m_dsk.ff_53b));
1085   save_item(NAME(m_dsk.ff_44a));
1086   save_item(NAME(m_dsk.ff_44b));
1087   save_item(NAME(m_dsk.ff_45a));
1088   save_item(NAME(m_dsk.ff_45b));
1089#endif
1090   save_item(NAME(m_dsp.hlc));
1091   save_item(NAME(m_dsp.a63));
1092   save_item(NAME(m_dsp.a66));
1093   save_item(NAME(m_dsp.setmode));
1094   save_item(NAME(m_dsp.inverse));
1095   save_item(NAME(m_dsp.halfclock));
1096   save_item(NAME(m_dsp.clr));
1097   save_item(NAME(m_dsp.fifo));
1098   save_item(NAME(m_dsp.fifo_wr));
1099   save_item(NAME(m_dsp.fifo_rd));
1100   save_item(NAME(m_dsp.dht_blocks));
1101   save_item(NAME(m_dsp.dwt_blocks));
1102   save_item(NAME(m_dsp.curt_blocks));
1103   save_item(NAME(m_dsp.curt_wakeup));
1104   save_item(NAME(m_dsp.vblank));
1105   save_item(NAME(m_dsp.xpreg));
1106   save_item(NAME(m_dsp.csr));
1107   save_item(NAME(m_dsp.curword));
1108   save_item(NAME(m_dsp.curdata));
1109   save_item(NAME(m_mem.mar));
1110   save_item(NAME(m_mem.rmdd));
1111   save_item(NAME(m_mem.wmdd));
1112   save_item(NAME(m_mem.md));
1113   save_item(NAME(m_mem.cycle));
1114   save_item(NAME(m_mem.access));
1115   save_item(NAME(m_mem.error));
1116   save_item(NAME(m_mem.mear));
1117   save_item(NAME(m_mem.mecr));
1118   save_item(NAME(m_emu.ir));
1119   save_item(NAME(m_emu.skip));
1120   save_item(NAME(m_emu.cy));
1121   save_item(NAME(m_eth.fifo));
1122   save_item(NAME(m_eth.fifo_rd));
1123   save_item(NAME(m_eth.fifo_wr));
1124   save_item(NAME(m_eth.status));
1125   save_item(NAME(m_eth.rx_crc));
1126   save_item(NAME(m_eth.tx_crc));
1127   save_item(NAME(m_eth.rx_count));
1128   save_item(NAME(m_eth.tx_count));
1129   save_item(NAME(m_eth.duckbreath));
1130
1131   state_add( A2_DRIVE,   "DRIVE",   m_dsk.drive).formatstr("%1u");
1132   state_add( A2_KADDR,   "KADDR",   m_dsk.kaddr).formatstr("%06O");
1133   state_add( A2_KADR,    "KADR",    m_dsk.kadr).formatstr("%06O");
1134   state_add( A2_KSTAT,   "KSTAT",   m_dsk.kstat).formatstr("%06O");
1135   state_add( A2_KCOM,    "KCOM",    m_dsk.kcom).formatstr("%06O");
1136   state_add( A2_KRECNO,  "KRECNO",  m_dsk.krecno).formatstr("%02O");
1137   state_add( A2_SHIFTIN, "SHIFTIN", m_dsk.shiftin).formatstr("%06O");
1138   state_add( A2_SHIFTOUT,"SHIFTOUT",m_dsk.shiftout).formatstr("%06O");
1139   state_add( A2_DATAIN,  "DATAIN",  m_dsk.datain).formatstr("%06O");
1140   state_add( A2_DATAOUT, "DATAOUT", m_dsk.dataout).formatstr("%06O");
1141   state_add( A2_KRWC,    "KRWC",    m_dsk.krwc).formatstr("%1u");
1142   state_add( A2_KFER,    "KFER",    m_dsk.kfer).formatstr("%1u");
1143   state_add( A2_WDTSKENA,"WDTSKENA",m_dsk.wdtskena).formatstr("%1u");
1144   state_add( A2_WDINIT0, "WDINIT0", m_dsk.wdinit0).formatstr("%1u");
1145   state_add( A2_WDINIT,  "WDINIT",  m_dsk.wdinit).formatstr("%1u");
1146   state_add( A2_STROBE,  "STROBE",  m_dsk.strobe).formatstr("%1u");
1147   state_add( A2_BITCLK,  "BITCLK",  m_dsk.bitclk).formatstr("%1u");
1148   state_add( A2_DATIN,   "DATIN",   m_dsk.datin).formatstr("%06O");
1149   state_add( A2_BITCNT,  "BITCNT",  m_dsk.bitcount).formatstr("%02O");
1150   state_add( A2_CARRY,   "CARRY",   m_dsk.carry).formatstr("%1u");
1151   state_add( A2_SECLATE, "SECLATE", m_dsk.seclate).formatstr("%1u");
1152   state_add( A2_SEEKOK,  "SEEKOK",  m_dsk.seekok).formatstr("%1u");
1153   state_add( A2_OKTORUN, "OKTORUN", m_dsk.ok_to_run).formatstr("%1u");
1154   state_add( A2_READY,   "READY",   m_dsk.kstat).formatstr("%1u");
1155   state_add_divider(-1);
1156   state_add( A2_TASK,    "TASK",    m_task).formatstr("%03O");
1157   state_add( A2_MPC,     "MPC",     m_mpc).formatstr("%06O");
1158   state_add( A2_NEXT,    "NEXT",    m_next).formatstr("%06O");
1159   state_add( A2_NEXT2,   "NEXT2",   m_next2).formatstr("%06O");
1160   state_add( A2_BUS,     "BUS",     m_bus).formatstr("%06O");
1161   state_add( A2_T,       "T",       m_t).formatstr("%06O");
1162   state_add( A2_ALU,     "ALU",     m_alu).formatstr("%06O");
1163   state_add( A2_ALUC0,   "ALUC0",   m_aluc0).formatstr("%1u");
1164   state_add( A2_L,       "L",       m_l).formatstr("%06O");
1165   state_add( A2_SHIFTER, "SHIFTER", m_shifter).formatstr("%06O");
1166   state_add( A2_LALUC0,  "LALUC0",  m_laluc0).formatstr("%1u");
1167   state_add( A2_M,       "M",       m_m).formatstr("%06O");
1168   state_add_divider(-1);
1169   state_add( A2_AC3,     "AC(3)",   m_r[000]).formatstr("%06O");
1170   state_add( A2_AC2,     "AC(2)",   m_r[001]).formatstr("%06O");
1171   state_add( A2_AC1,     "AC(1)",   m_r[002]).formatstr("%06O");
1172   state_add( A2_AC0,     "AC(0)",   m_r[003]).formatstr("%06O");
1173   state_add( A2_R04,     "R04",     m_r[004]).formatstr("%06O");
1174   state_add( A2_R05,     "R05",     m_r[005]).formatstr("%06O");
1175   state_add( A2_PC,      "PC",      m_r[006]).formatstr("%06O");
1176   state_add( A2_R07,     "R07",     m_r[007]).formatstr("%06O");
1177   state_add( A2_R10,     "R10",     m_r[010]).formatstr("%06O");
1178   state_add( A2_R11,     "R11",     m_r[011]).formatstr("%06O");
1179   state_add( A2_R12,     "R12",     m_r[012]).formatstr("%06O");
1180   state_add( A2_R13,     "R13",     m_r[013]).formatstr("%06O");
1181   state_add( A2_R14,     "R14",     m_r[014]).formatstr("%06O");
1182   state_add( A2_R15,     "R15",     m_r[015]).formatstr("%06O");
1183   state_add( A2_R16,     "R16",     m_r[016]).formatstr("%06O");
1184   state_add( A2_R17,     "R17",     m_r[017]).formatstr("%06O");
1185   state_add( A2_R20,     "R20",     m_r[020]).formatstr("%06O");
1186   state_add( A2_R21,     "R21",     m_r[021]).formatstr("%06O");
1187   state_add( A2_R22,     "R22",     m_r[022]).formatstr("%06O");
1188   state_add( A2_R23,     "R23",     m_r[023]).formatstr("%06O");
1189   state_add( A2_R24,     "R24",     m_r[024]).formatstr("%06O");
1190   state_add( A2_R25,     "R25",     m_r[025]).formatstr("%06O");
1191   state_add( A2_R26,     "R26",     m_r[026]).formatstr("%06O");
1192   state_add( A2_R27,     "R27",     m_r[027]).formatstr("%06O");
1193   state_add( A2_R30,     "R30",     m_r[030]).formatstr("%06O");
1194   state_add( A2_R31,     "R31",     m_r[031]).formatstr("%06O");
1195   state_add( A2_R32,     "R32",     m_r[032]).formatstr("%06O");
1196   state_add( A2_R33,     "R33",     m_r[033]).formatstr("%06O");
1197   state_add( A2_R34,     "R34",     m_r[034]).formatstr("%06O");
1198   state_add( A2_R35,     "R35",     m_r[035]).formatstr("%06O");
1199   state_add( A2_R36,     "R36",     m_r[036]).formatstr("%06O");
1200   state_add( A2_R37,     "R37",     m_r[037]).formatstr("%06O");
1201   state_add_divider(-1);
1202   state_add( A2_S00,     "S00",     m_s[0][000]).formatstr("%06O");
1203   state_add( A2_S01,     "S01",     m_s[0][001]).formatstr("%06O");
1204   state_add( A2_S02,     "S02",     m_s[0][002]).formatstr("%06O");
1205   state_add( A2_S03,     "S03",     m_s[0][003]).formatstr("%06O");
1206   state_add( A2_S04,     "S04",     m_s[0][004]).formatstr("%06O");
1207   state_add( A2_S05,     "S05",     m_s[0][005]).formatstr("%06O");
1208   state_add( A2_S06,     "S06",     m_s[0][006]).formatstr("%06O");
1209   state_add( A2_S07,     "S07",     m_s[0][007]).formatstr("%06O");
1210   state_add( A2_S10,     "S10",     m_s[0][010]).formatstr("%06O");
1211   state_add( A2_S11,     "S11",     m_s[0][011]).formatstr("%06O");
1212   state_add( A2_S12,     "S12",     m_s[0][012]).formatstr("%06O");
1213   state_add( A2_S13,     "S13",     m_s[0][013]).formatstr("%06O");
1214   state_add( A2_S14,     "S14",     m_s[0][014]).formatstr("%06O");
1215   state_add( A2_S15,     "S15",     m_s[0][015]).formatstr("%06O");
1216   state_add( A2_S16,     "S16",     m_s[0][016]).formatstr("%06O");
1217   state_add( A2_S17,     "S17",     m_s[0][017]).formatstr("%06O");
1218   state_add( A2_S20,     "S20",     m_s[0][020]).formatstr("%06O");
1219   state_add( A2_S21,     "S21",     m_s[0][021]).formatstr("%06O");
1220   state_add( A2_S22,     "S22",     m_s[0][022]).formatstr("%06O");
1221   state_add( A2_S23,     "S23",     m_s[0][023]).formatstr("%06O");
1222   state_add( A2_S24,     "S24",     m_s[0][024]).formatstr("%06O");
1223   state_add( A2_S25,     "S25",     m_s[0][025]).formatstr("%06O");
1224   state_add( A2_S26,     "S26",     m_s[0][026]).formatstr("%06O");
1225   state_add( A2_S27,     "S27",     m_s[0][027]).formatstr("%06O");
1226   state_add( A2_S30,     "S30",     m_s[0][030]).formatstr("%06O");
1227   state_add( A2_S31,     "S31",     m_s[0][031]).formatstr("%06O");
1228   state_add( A2_S32,     "S32",     m_s[0][032]).formatstr("%06O");
1229   state_add( A2_S33,     "S33",     m_s[0][033]).formatstr("%06O");
1230   state_add( A2_S34,     "S34",     m_s[0][034]).formatstr("%06O");
1231   state_add( A2_S35,     "S35",     m_s[0][035]).formatstr("%06O");
1232   state_add( A2_S36,     "S36",     m_s[0][036]).formatstr("%06O");
1233   state_add( A2_S37,     "S37",     m_s[0][037]).formatstr("%06O");
1234
1235   state_add(STATE_GENPC, "curpc", m_mpc).formatstr("%03X").noshow();
1236   state_add(STATE_GENFLAGS, "GENFLAGS", m_aluc0).formatstr("%5s").noshow();
1237
1238   m_icountptr = &m_icount;
1239
1240   hard_reset();
1241}
1242
1243//! read microcode CROM
1244READ32_MEMBER ( alto2_cpu_device::crom_r )
1245{
1246   return *reinterpret_cast<UINT32 *>(m_ucode_crom + offset * 4);
1247}
1248
1249//! read microcode CRAM
1250READ32_MEMBER ( alto2_cpu_device::cram_r )
1251{
1252   return *reinterpret_cast<UINT32 *>(m_ucode_cram + offset * 4);
1253}
1254
1255//! write microcode CRAM
1256WRITE32_MEMBER( alto2_cpu_device::cram_w )
1257{
1258   *reinterpret_cast<UINT32 *>(m_ucode_cram + offset * 4) = data;
1259}
1260
1261//! direct read access to the microcode CROM
1262#define   RD_CROM(addr) (*reinterpret_cast<UINT32 *>(m_ucode_crom + addr * 4))
1263//! direct read access to the microcode CRAM
1264#define   RD_CRAM(addr) (*reinterpret_cast<UINT32 *>(m_ucode_cram + addr * 4))
1265//! direct write access to the microcode CRAM
1266#define   WR_CRAM(addr,data) do { \
1267   *reinterpret_cast<UINT32 *>(m_ucode_cram + addr * 4) = data; \
1268} while (0)
1269
1270//! read constants PROM
1271READ16_MEMBER ( alto2_cpu_device::const_r )
1272{
1273   return *reinterpret_cast<UINT16 *>(m_const_data + offset * 2);
1274}
1275
1276#define   PUT_EVEN(dword,word)         A2_PUT32(dword,32, 0,15,word)
1277#define   GET_EVEN(dword)               A2_GET32(dword,32, 0,15)
1278#define   PUT_ODD(dword,word)            A2_PUT32(dword,32,16,31,word)
1279#define   GET_ODD(dword)               A2_GET32(dword,32,16,31)
1280
1281//! read i/o space RAM
1282READ16_MEMBER ( alto2_cpu_device::ioram_r )
1283{
1284   offs_t dword_addr = offset / 2;
1285   return static_cast<UINT16>(offset & 1 ? GET_ODD(m_mem.ram[dword_addr]) : GET_EVEN(m_mem.ram[dword_addr]));
1286}
1287
1288//! write i/o space RAM
1289WRITE16_MEMBER( alto2_cpu_device::ioram_w )
1290{
1291   offs_t dword_addr = offset / 2;
1292   if (offset & 1)
1293      PUT_ODD(m_mem.ram[dword_addr], data);
1294   else
1295      PUT_EVEN(m_mem.ram[dword_addr], data);
1296}
1297
1298//-------------------------------------------------
1299//  device_reset - device-specific reset
1300//-------------------------------------------------
1301
1302// FIXME
1303void alto2_cpu_device::device_reset()
1304{
1305    soft_reset();
1306}
1307
1308/**
1309 * @brief callback is called by the drive timer whenever a new sector starts
1310 *
1311 * @param unit the unit number
1312 */
1313static void disk_sector_start(void* cookie, int unit)
1314{
1315   alto2_cpu_device* cpu = reinterpret_cast<alto2_cpu_device *>(cookie);
1316   cpu->next_sector(unit);
1317}
1318
1319void alto2_cpu_device::interface_post_reset()
1320{
1321
1322   // set the disk unit sector callbacks
1323   for (int unit = 0; unit < diablo_hd_device::DIABLO_UNIT_MAX; unit++) {
1324      diablo_hd_device* dhd = m_drive[unit];
1325      dhd->set_sector_callback(this, &disk_sector_start);
1326   }
1327}
1328
1329//-------------------------------------------------
1330//  execute_set_input - act on a changed input/
1331//  interrupt line
1332//-------------------------------------------------
1333
1334// FIXME
1335void alto2_cpu_device::execute_set_input(int inputnum, int state)
1336{
1337}
1338
1339//-------------------------------------------------
1340//  state_string_export - export state as a string
1341//  for the debugger
1342//-------------------------------------------------
1343
1344void alto2_cpu_device::state_string_export(const device_state_entry &entry, astring &string)
1345{
1346   switch (entry.index())
1347   {
1348   case STATE_GENFLAGS:
1349      string.printf("%s%s%s%s",
1350                 m_aluc0 ? "C":"-",
1351                 m_laluc0 ? "c":"-",
1352                 m_shifter == 0 ? "0":"-",
1353                 static_cast<INT16>(m_shifter) < 0 ? "<":"-");
1354      break;
1355   }
1356}
1357
1358void alto2_cpu_device::fatal(int exitcode, const char *format, ...)
1359{
1360   va_list ap;
1361   va_start(ap, format);
1362   emu_fatalerror error(exitcode, format, ap);
1363   va_end(ap);
1364}
1365
1366/** @brief task names */
1367const char* alto2_cpu_device::task_name(int task)
1368{
1369   switch (task) {
1370   case 000: return "emu";
1371   case 001: return "task01";
1372   case 002: return "task02";
1373   case 003: return "task03";
1374   case 004: return "ksec";
1375   case 005: return "task05";
1376   case 006: return "task06";
1377   case 007: return "ether";
1378   case 010: return "mrt";
1379   case 011: return "dwt";
1380   case 012: return "curt";
1381   case 013: return "dht";
1382   case 014: return "dvt";
1383   case 015: return "part";
1384   case 016: return "kwd";
1385   case 017: return "task17";
1386   }
1387   return "???";
1388}
1389
1390/** @brief register names (as used by the microcode) */
1391const char* alto2_cpu_device::r_name(UINT8 reg)
1392{
1393   switch (reg) {
1394   case 000: return "ac(3)";
1395   case 001: return "ac(2)";
1396   case 002: return "ac(1)";
1397   case 003: return "ac(0)";
1398   case 004: return "nww";
1399   case 005: return "r05";
1400   case 006: return "pc";
1401   case 007: return "r07";
1402   case 010: return "xh";
1403   case 011: return "r11";
1404   case 012: return "ecntr";
1405   case 013: return "epntr";
1406   case 014: return "r14";
1407   case 015: return "r15";
1408   case 016: return "r16";
1409   case 017: return "r17";
1410   case 020: return "curx";
1411   case 021: return "curdata";
1412   case 022: return "cba";
1413   case 023: return "aecl";
1414   case 024: return "slc";
1415   case 025: return "mtemp";
1416   case 026: return "htab";
1417   case 027: return "ypos";
1418   case 030: return "dwa";
1419   case 031: return "kwdctw";
1420   case 032: return "cksumrw";
1421   case 033: return "knmarw";
1422   case 034: return "dcbr";
1423   case 035: return "dwax";
1424   case 036: return "mask";
1425   case 037: return "r37";
1426   }
1427   return "???";
1428}
1429
1430/** @brief ALU function names */
1431const char* alto2_cpu_device::aluf_name(UINT8 aluf)
1432{
1433   switch (aluf) {
1434   case 000: return "bus";
1435   case 001: return "t";
1436   case 002: return "bus or t";
1437   case 003: return "bus and t";
1438   case 004: return "bus xor t";
1439   case 005: return "bus + 1";
1440   case 006: return "bus - 1";
1441   case 007: return "bus + t";
1442   case 010: return "bus - t";
1443   case 011: return "bus - t - 1";
1444   case 012: return "bus + t + 1";
1445   case 013: return "bus + skip";
1446   case 014: return "bus, t";
1447   case 015: return "bus and not t";
1448   case 016: return "0 (undef)";
1449   case 017: return "0 (undef)";
1450   }
1451   return "???";
1452}
1453
1454/** @brief BUS source names */
1455const char* alto2_cpu_device::bs_name(UINT8 bs)
1456{
1457   switch (bs) {
1458   case 000: return "read_r";
1459   case 001: return "load_r";
1460   case 002: return "no_source";
1461   case 003: return "task_3";
1462   case 004: return "task_4";
1463   case 005: return "read_md";
1464   case 006: return "mouse";
1465   case 007: return "disp";
1466   }
1467   return "???";
1468}
1469
1470/** @brief F1 function names */
1471const char* alto2_cpu_device::f1_name(UINT8 f1)
1472{
1473   switch (f1) {
1474   case 000: return "nop";
1475   case 001: return "load_mar";
1476   case 002: return "task";
1477   case 003: return "block";
1478   case 004: return "l_lsh_1";
1479   case 005: return "l_rsh_1";
1480   case 006: return "l_lcy_8";
1481   case 007: return "const";
1482   case 010: return "task_10";
1483   case 011: return "task_11";
1484   case 012: return "task_12";
1485   case 013: return "task_13";
1486   case 014: return "task_14";
1487   case 015: return "task_15";
1488   case 016: return "task_16";
1489   case 017: return "task_17";
1490   }
1491   return "???";
1492}
1493
1494/** @brief F2 function names */
1495const char* alto2_cpu_device::f2_name(UINT8 f2)
1496{
1497   switch (f2) {
1498   case 000: return "nop";
1499   case 001: return "bus=0";
1500   case 002: return "shifter<0";
1501   case 003: return "shifter=0";
1502   case 004: return "bus";
1503   case 005: return "alucy";
1504   case 006: return "load_md";
1505   case 007: return "const";
1506   case 010: return "task_10";
1507   case 011: return "task_11";
1508   case 012: return "task_12";
1509   case 013: return "task_13";
1510   case 014: return "task_14";
1511   case 015: return "task_15";
1512   case 016: return "task_16";
1513   case 017: return "task_17";
1514   }
1515   return "???";
1516}
1517
1518#if   ALTO2_DEBUG
1519void alto2_cpu_device::watch_read(UINT32 addr, UINT32 data)
1520{
1521   LOG((LOG_MEM,0,"mem: rd[%06o] = %06o\n", addr, data));
1522}
1523
1524void alto2_cpu_device::watch_write(UINT32 addr, UINT32 data)
1525{
1526   LOG((LOG_MEM,0,"mem: wr[%06o] = %06o\n", addr, data));
1527}
1528#endif
1529
1530/** @brief fatal exit on unitialized dynamic phase BUS source */
1531void alto2_cpu_device::fn_bs_bad_0()
1532{
1533   fatal(9,"fatal: bad early bus source pointer for task %s, mpc:%05o bs:%s\n",
1534      task_name(m_task), m_mpc, bs_name(MIR_BS(m_mir)));
1535}
1536
1537/** @brief fatal exit on unitialized latching phase BUS source */
1538void alto2_cpu_device::fn_bs_bad_1()
1539{
1540   fatal(9,"fatal: bad late bus source pointer for task %s, mpc:%05o bs: %s\n",
1541      task_name(m_task), m_mpc, bs_name(MIR_BS(m_mir)));
1542}
1543
1544/** @brief fatal exit on unitialized dynamic phase F1 function */
1545void alto2_cpu_device::fn_f1_bad_0()
1546{
1547   fatal(9,"fatal: bad early f1 function pointer for task %s, mpc:%05o f1: %s\n",
1548      task_name(m_task), m_mpc, f1_name(MIR_F1(m_mir)));
1549}
1550
1551/** @brief fatal exit on unitialized latching phase F1 function */
1552void alto2_cpu_device::fn_f1_bad_1()
1553{
1554   fatal(9,"fatal: bad late f1 function pointer for task %s, mpc:%05o f1: %s\n",
1555      task_name(m_task), m_mpc, f1_name(MIR_F1(m_mir)));
1556}
1557
1558/** @brief fatal exit on unitialized dynamic phase F2 function */
1559void alto2_cpu_device::fn_f2_bad_0()
1560{
1561   fatal(9,"fatal: bad early f2 function pointer for task %s, mpc:%05o f2: %s\n",
1562      task_name(m_task), m_mpc, f2_name(MIR_F2(m_mir)));
1563}
1564
1565/** @brief fatal exit on unitialized latching phase F2 function */
1566void alto2_cpu_device::fn_f2_bad_1()
1567{
1568   fatal(9,"fatal: bad late f2 function pointer for task %s, mpc:%05o f2: %s\n",
1569        task_name(m_task), m_mpc, f2_name(MIR_F2(m_mir)));
1570}
1571
1572#if   ALTO2_DEBUG
1573typedef struct {
1574   UINT16 first, last;
1575   const char* name;
1576}   memory_range_name_t;
1577
1578memory_range_name_t memory_range_name_table[] = {
1579   {0177016, 0177017,   "UTILOUT    Printer output (Std. Hardware)"},
1580   {0177020, 0177023,   "XBUS       Utility input bus (Alto II Std. Hardware)"},
1581   {0177024, 0177024,   "MEAR       Memory Error Address Register (Alto II Std. Hardware)"},
1582   {0177025, 0177025,   "MESR       Memory error status register (Alto II Std. Hardware)"},
1583   {0177026, 0177026,   "MECR       Memory error control register (Alto II Std. Hardware)"},
1584   {0177030, 0177033,   "UTILIN     Printer status, mouse, keyset (all 4 locations return same thing)"},
1585   {0177034, 0177037,   "KBDAD      Undecoded keyboard (Std. Hardware)"},
1586   {0177740, 0177757,   "BANKREGS   Extended memory option bank registers"},
1587   {0177100, 0177100,   "-          Sumagraphics tablet X"},
1588   {0177101, 0177101,   "-          Sumagraphics tablet Y"},
1589   {0177140, 0177157,   "-          Organ keyboard"},
1590   {0177200, 0177204,   "-          PROM programmer"},
1591   {0177234, 0177237,   "-          Experimental ursor control"},
1592   {0177240, 0177257,   "-          Alto II debugger"},
1593   {0177244, 0177247,   "-          Graphics keyboard"},
1594   {0177400, 0177405,   "-          Maxc2 maintenance interface"},
1595   {0177400, 0177400,   "-          Alto DLS input (0)"},
1596   {0177420, 0177420,   "-          Alto DLS input (1)"},
1597   {0177440, 0177440,   "-          Alto DLS input (2)"},
1598   {0177460, 0177460,   "-          Alto DLS input (3)"},
1599   {0177600, 0177677,   "-          Alto DLS output"},
1600   {0177700, 0177700,   "-          EIA interface output bit"},
1601   {0177701, 0177701,   "EIALOC     EIA interface input bit"},
1602   {0177720, 0177737,   "-          TV Camera Interface"},
1603   {0177764, 0177773,   "-          Redactron tape drive"},
1604   {0177776, 0177776,   "-          Digital-Analog Converter, Joystick"},
1605   {0177777, 0177777,   "-          Digital-Analog Converter, Joystick"}
1606};
1607
1608static const char* memory_range_name(offs_t offset)
1609{
1610   int _min = 0;
1611   int _max = sizeof(memory_range_name_table) / sizeof(memory_range_name_table[0]) - 1;
1612   int _mid;
1613
1614   offset %= ALTO2_IO_PAGE_SIZE;
1615   offset += ALTO2_IO_PAGE_BASE;
1616
1617   /* binary search in table of memory ranges */
1618   while (_max >= _min)
1619   {
1620      _mid = (_min + _max) / 2;
1621      if (memory_range_name_table[_mid].last < offset)
1622         _min = _mid + 1;
1623      else if (memory_range_name_table[_mid].first > offset)
1624         _max = _mid - 1;
1625      else if (memory_range_name_table[_mid].first <= offset &&
1626             memory_range_name_table[_mid].last >= offset)
1627         return memory_range_name_table[_mid].name;
1628   }
1629   return "-          UNUSED";
1630}
1631
1632#endif
1633
1634/**
1635 * @brief read the open bus for unused MMIO range
1636 */
1637READ16_MEMBER( alto2_cpu_device::noop_r )
1638{
1639   LOG((LOG_CPU,0,"   MMIO rd %s\n", memory_range_name(offset)));
1640   return 0177777;
1641}
1642
1643/**
1644 * @brief write nowhere for unused MMIO range
1645 */
1646WRITE16_MEMBER( alto2_cpu_device::noop_w )
1647{
1648    LOG((LOG_CPU,0,"   MMIO wr %s\n", memory_range_name(offset)));
1649}
1650
1651/**
1652 * @brief read bank register in memory mapped I/O range
1653 *
1654 * The bank registers are stored in a 16x4-bit RAM 74S189.
1655 */
1656READ16_MEMBER( alto2_cpu_device::bank_reg_r )
1657{
1658   int task = offset & 017;
1659   int bank = m_bank_reg[task] | 0177760;
1660   return bank;
1661}
1662
1663/**
1664 * @brief write bank register in memory mapped I/O range
1665 *
1666 * The bank registers are stored in a 16x4-bit RAM 74S189.
1667 */
1668WRITE16_MEMBER( alto2_cpu_device::bank_reg_w )
1669{
1670   int task = offset & 017;
1671   m_bank_reg[task] = data & 017;
1672   LOG((LOG_CPU,0,"   write bank[%02o]=%#o normal:%o extended:%o (%s)\n",
1673      task, data,
1674      GET_BANK_NORMAL(data),
1675      GET_BANK_EXTENDED(data),
1676      task_name(task)));
1677}
1678
1679/**
1680 * @brief bs_read_r early: drive bus by R register
1681 */
1682void alto2_cpu_device::bs_read_r_0()
1683{
1684   UINT16 r = m_r[m_rsel];
1685   LOG((LOG_CPU,2,"   ←R%02o; %s (%#o)\n", m_rsel, r_name(m_rsel), r));
1686   m_bus &= r;
1687}
1688
1689/**
1690 * @brief bs_load_r early: load R places 0 on the BUS
1691 */
1692void alto2_cpu_device::bs_load_r_0()
1693{
1694   UINT16 r = 0;
1695   LOG((LOG_CPU,2,"   R%02o←; %s (BUS&=0)\n", m_rsel, r_name(m_rsel)));
1696   m_bus &= r;
1697}
1698
1699/**
1700 * @brief bs_load_r late: load R from SHIFTER
1701 */
1702void alto2_cpu_device::bs_load_r_1()
1703{
1704   if (MIR_F2(m_mir) != f2_emu_load_dns) {
1705      m_r[m_rsel] = m_shifter;
1706      LOG((LOG_CPU,2,"   R%02o←; %s = SHIFTER (%#o)\n", m_rsel, r_name(m_rsel), m_shifter));
1707      /* HACK: programs writing r37 with xxx3 make the cursor
1708       * display go nuts. Until I found the real reason for this
1709       * obviously buggy display, I just clear the two
1710       * least significant bits of r37 if they are set at once.
1711       */
1712      if (m_rsel == 037 && ((m_shifter & 3) == 3)) {
1713         printf("writing r37 = %#o\n", m_shifter);
1714         m_r[037] &= ~3;
1715      }
1716   }
1717}
1718
1719/**
1720 * @brief bs_read_md early: drive BUS from read memory data
1721 */
1722void alto2_cpu_device::bs_read_md_0()
1723{
1724#if   ALTO2_DEBUG
1725   UINT32 mar = m_mem.mar;
1726#endif
1727   UINT16 md = read_mem();
1728   LOG((LOG_CPU,2,"   ←MD; BUS&=MD (%#o=[%#o])\n", md, mar));
1729   m_bus &= md;
1730}
1731
1732/**
1733 * @brief bs_mouse early: drive bus by mouse
1734 */
1735void alto2_cpu_device::bs_mouse_0()
1736{
1737   UINT16 r = mouse_read();
1738   LOG((LOG_CPU,2,"   ←MOUSE; BUS&=MOUSE (%#o)\n", r));
1739   m_bus &= r;
1740}
1741
1742/**
1743 * @brief bs_disp early: drive bus by displacement (which?)
1744 */
1745void alto2_cpu_device::bs_disp_0()
1746{
1747   UINT16 r = 0177777;
1748   LOG((LOG_CPU,0,"BS ←DISP not handled by task %s mpc:%04x\n", task_name(m_task), m_mpc));
1749   LOG((LOG_CPU,2,"   ←DISP; BUS&=DISP ?? (%#o)\n", r));
1750   m_bus &= r;
1751}
1752
1753/**
1754 * @brief f1_load_mar late: load memory address register
1755 *
1756 * Load memory address register from the ALU output;
1757 * start main memory reference (see section 2.3).
1758 */
1759void alto2_cpu_device::f1_load_mar_1()
1760{
1761   UINT8 bank = m_bank_reg[m_task];
1762   UINT32 msb;
1763   if (MIR_F2(m_mir) == f2_load_md) {
1764      msb = GET_BANK_EXTENDED(bank) << 16;
1765      LOG((LOG_CPU,7, "   XMAR %#o\n", msb | m_alu));
1766   } else {
1767      msb = GET_BANK_NORMAL(bank) << 16;
1768
1769   }
1770   load_mar(m_rsel, msb | m_alu);
1771}
1772
1773#if   USE_PRIO_F9318
1774/** @brief F9318 input lines */
1775typedef enum {
1776   PRIO_IN_EI = (1<<8),
1777   PRIO_IN_I7 = (1<<7),
1778   PRIO_IN_I6 = (1<<6),
1779   PRIO_IN_I5 = (1<<5),
1780   PRIO_IN_I4 = (1<<4),
1781   PRIO_IN_I3 = (1<<3),
1782   PRIO_IN_I2 = (1<<2),
1783   PRIO_IN_I1 = (1<<1),
1784   PRIO_IN_I0 = (1<<0),
1785   /* masks */
1786   PRIO_I7 = PRIO_IN_I7,
1787   PRIO_I6_I7 = (PRIO_IN_I6 | PRIO_IN_I7),
1788   PRIO_I5_I7 = (PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1789   PRIO_I4_I7 = (PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1790   PRIO_I3_I7 = (PRIO_IN_I3 | PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1791   PRIO_I2_I7 = (PRIO_IN_I2 | PRIO_IN_I3 | PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1792   PRIO_I1_I7 = (PRIO_IN_I1 | PRIO_IN_I2 | PRIO_IN_I3 | PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1793   PRIO_I0_I7 = (PRIO_IN_I0 | PRIO_IN_I1 | PRIO_IN_I2 | PRIO_IN_I3 | PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1794}   f9318_in_t;
1795
1796/** @brief F9318 output lines */
1797typedef enum {
1798   PRIO_OUT_Q0 = (1<<0),
1799   PRIO_OUT_Q1 = (1<<1),
1800   PRIO_OUT_Q2 = (1<<2),
1801   PRIO_OUT_EO = (1<<3),
1802   PRIO_OUT_GS = (1<<4),
1803   /* masks */
1804   PRIO_OUT_QZ = (PRIO_OUT_Q0 | PRIO_OUT_Q1 | PRIO_OUT_Q2)
1805}   f9318_out_t;
1806
1807/**
1808 * @brief F9318 priority encoder 8 to 3-bit
1809 *
1810 * Emulation of the F9318 chip (pin compatible with 74348).
1811 *
1812 * <PRE>
1813 *            F9318
1814 *         +---+-+---+
1815 *         |   +-+   |         +---------------------------------+----------------+
1816 *    I4' -|1      16|-  Vcc   |              input              |     output     |
1817 *         |         |         +---------------------------------+----------------+
1818 *    I5' -|2      15|-  EO'   |      EI I0 I1 I2 I3 I4 I5 I6 I7 | GS Q0 Q1 Q2 EO |
1819 *         |         |         +---------------------------------+----------------+
1820 *    I6' -|3      14|-  GS'   | (a)  H  x  x  x  x  x  x  x  x  | H  H  H  H  H  |
1821 *         |         |         | (b)  L  H  H  H  H  H  H  H  H  | H  H  H  H  L  |
1822 *    I7' -|4      13|-  I3'   +---------------------------------+----------------+
1823 *         |         |         | (c)  L  x  x  x  x  x  x  x  L  | L  L  L  L  H  |
1824 *    EI' -|5      12|-  I2'   | (d)  L  x  x  x  x  x  x  L  H  | L  H  L  L  H  |
1825 *         |         |         | (e)  L  x  x  x  x  x  L  H  H  | L  L  H  L  H  |
1826 *    Q2' -|6      11|-  I1'   | (f)  L  x  x  x  x  L  H  H  H  | L  H  H  L  H  |
1827 *         |         |         | (g)  L  x  x  x  L  H  H  H  H  | L  L  L  H  H  |
1828 *    Q1' -|7      10|-  I0'   | (h)  L  x  x  L  H  H  H  H  H  | L  H  L  H  H  |
1829 *         |         |         | (i)  L  x  L  H  H  H  H  H  H  | L  L  H  H  H  |
1830 *   GND  -|8       9|-  Q0'   | (j)  L  L  H  H  H  H  H  H  H  | L  H  H  H  H  |
1831 *         |         |         +---------------------------------+----------------+
1832 *         +---------+
1833 * </PRE>
1834 */
1835static __inline f9318_out_t f9318(f9318_in_t in)
1836{
1837   f9318_out_t out;
1838
1839   if (in & PRIO_IN_EI) {
1840      out = PRIO_OUT_EO | PRIO_OUT_GS | PRIO_OUT_QZ;
1841      LOG((LOG_CPU,2,"   f9318 case (a) in:%#o out:%#o\n", in, out));
1842      return out;
1843   }
1844
1845   if (0 == (in & PRIO_I7)) {
1846      out = PRIO_OUT_EO;
1847      LOG((LOG_CPU,2,"   f9318 case (c) in:%#o out:%#o\n", in, out));
1848      return out;
1849   }
1850
1851   if (PRIO_I7 == (in & PRIO_I6_I7)) {
1852      out = PRIO_OUT_EO | PRIO_OUT_Q0;
1853      LOG((LOG_CPU,2,"   f9318 case (d) in:%#o out:%#o\n", in, out));
1854      return out;
1855   }
1856
1857   if (PRIO_I6_I7 == (in & PRIO_I5_I7)) {
1858      out = PRIO_OUT_EO | PRIO_OUT_Q1;
1859      LOG((LOG_CPU,2,"   f9318 case (e) in:%#o out:%#o\n", in, out));
1860      return out;
1861   }
1862
1863   if (PRIO_I5_I7 == (in & PRIO_I4_I7)) {
1864      out = PRIO_OUT_EO | PRIO_OUT_Q0 | PRIO_OUT_Q1;
1865      LOG((LOG_CPU,2,"   f9318 case (f) in:%#o out:%#o\n", in, out));
1866      return out;
1867   }
1868
1869   if (PRIO_I4_I7 == (in & PRIO_I3_I7)) {
1870      out = PRIO_OUT_EO | PRIO_OUT_Q2;
1871      LOG((LOG_CPU,2,"   f9318 case (g) in:%#o out:%#o\n", in, out));
1872      return out;
1873   }
1874
1875   if (PRIO_I3_I7 == (in & PRIO_I2_I7)) {
1876      out = PRIO_OUT_EO | PRIO_OUT_Q0 | PRIO_OUT_Q2;
1877      LOG((LOG_CPU,2,"   f9318 case (h) in:%#o out:%#o\n", in, out));
1878      return out;
1879   }
1880
1881   if (PRIO_I2_I7 == (in & PRIO_I1_I7)) {
1882      out = PRIO_OUT_EO | PRIO_OUT_Q1 | PRIO_OUT_Q2;
1883      LOG((LOG_CPU,2,"   f9318 case (i) in:%#o out:%#o\n", in, out));
1884      return out;
1885   }
1886
1887   if (PRIO_I1_I7 == (in & PRIO_I0_I7)) {
1888      out = PRIO_OUT_EO | PRIO_OUT_Q0 | PRIO_OUT_Q1 | PRIO_OUT_Q2;
1889      LOG((LOG_CPU,2,"   f9318 case (j) in:%#o out:%#o\n", in, out));
1890      return out;
1891   }
1892
1893   out = PRIO_OUT_QZ | PRIO_OUT_GS;
1894   LOG((LOG_CPU,2,"   f9318 case (b) in:%#o out:%#o\n", in, out));
1895   return out;
1896}
1897#endif
1898
1899/**
1900 * @brief f1_task early: task switch
1901 *
1902 * The priority encoder finds the highest task requesting service
1903 * and switches the task number after the next cycle.
1904 *
1905 * <PRE>
1906 *   CT       PROM    NEXT'     RDCT'
1907 *   1 2 4 8  DATA   6 7 8 9   1 2 4 8
1908 *   ---------------------------------
1909 *   0 0 0 0  0367   1 1 1 1   0 1 1 1
1910 *   1 0 0 0  0353   1 1 1 0   1 0 1 1
1911 *   0 1 0 0  0323   1 1 0 1   0 0 1 1
1912 *   1 1 0 0  0315   1 1 0 0   1 1 0 1
1913 *   0 0 1 0  0265   1 0 1 1   0 1 0 1
1914 *   1 0 1 0  0251   1 0 1 0   1 0 0 1
1915 *   0 1 1 0  0221   1 0 0 1   0 0 0 1
1916 *   1 1 1 0  0216   1 0 0 0   1 1 1 0
1917 *   0 0 0 1  0166   0 1 1 1   0 1 1 0
1918 *   1 0 0 1  0152   0 1 1 0   1 0 1 0
1919 *   0 1 0 1  0122   0 1 0 1   0 0 1 0
1920 *   1 1 0 1  0114   0 1 0 0   1 1 0 0
1921 *   0 0 1 1  0064   0 0 1 1   0 1 0 0
1922 *   1 0 1 1  0050   0 0 1 0   1 0 0 0
1923 *   0 1 1 1  0020   0 0 0 1   0 0 0 0
1924 *   1 1 1 1  0017   0 0 0 0   1 1 1 1
1925 *
1926 * The various task wakeups are encoded using two 8:3-bit priority encoders F9318,
1927 * which are pin-compatible to the 74348 (inverted inputs and outputs).
1928 * Their part numbers are U1 and U2.
1929 * The two encoders are chained (EO of U1 goes to EI of U2):
1930 *
1931 * The outputs are fed into some NAND gates (74H10 and 74H00) to decode
1932 * the task number to latch (CT1-CT4) after a F1 TASK. The case where all
1933 * of RDCT1' to RDCT8' are high (1) is decoded as RESET'.
1934 *
1935 * signal   function
1936 * --------------------------------------------------
1937 * CT1      (U1.Q0' & U2.Q0' & RDCT1')'
1938 * CT2      (U1.Q1' & U2.Q1' & RDCT2')'
1939 * CT4      (U1.Q2' & U2.Q2' & RDCT4')'
1940 * CT8      (U1.GS' & RDCT8')'
1941 * RESET'   RDCT1' & RDCT2' & RDCT4' & RDCT8'
1942 *
1943 * In the tables below "x" is RDCTx' of current task
1944 *
1945 * signal          input   output, if first 0        CT1  CT2  CT4  CT8
1946 * ----------------------------------------------------------------------------------------
1947 * WAKE17' (T19?)   4 I7   Q2:0 Q1:0 Q0:0 GS:0 EO:1  1    1    1    1
1948 * WAKEKWDT'        3 I6   Q2:0 Q1:0 Q0:1 GS:0 EO:1  x    1    1    1
1949 * WAKEPART'        2 I5   Q2:0 Q1:1 Q0:0 GS:0 EO:1  1    x    1    1
1950 * WAKEDVT'         1 I4   Q2:0 Q1:1 Q0:1 GS:0 EO:1  x    x    1    1
1951 * WAKEDHT'        13 I3   Q2:1 Q1:0 Q0:0 GS:0 EO:1  1    1    x    1
1952 * WAKECURT'       12 I2   Q2:1 Q1:0 Q0:1 GS:0 EO:1  x    1    x    1
1953 * WAKEDWT'        11 I1   Q2:1 Q1:1 Q0:0 GS:0 EO:1  1    x    x    1
1954 * WAKEMRT'        10 I0   Q2:1 Q1:1 Q0:1 GS:0 EO:1  x    x    x    1
1955 * otherwise               Q2:1 Q1:1 Q0:1 GS:1 EO:0  x    x    x    x
1956 *
1957 * signal          input   output, if first 0
1958 * ----------------------------------------------------------------------------------------
1959 * WAKEET'          4 I7   Q2:0 Q1:0 Q0:0 GS:0 EO:1  1    1    1    x
1960 * WAKE6'           3 I6   Q2:0 Q1:0 Q0:1 GS:0 EO:1  x    1    1    x
1961 * WAKE5'           2 I5   Q2:0 Q1:1 Q0:0 GS:0 EO:1  1    x    1    x
1962 * WAKEKST'         1 I4   Q2:0 Q1:1 Q0:1 GS:0 EO:1  x    x    1    x
1963 * WAKE3' (T23?)   13 I3   Q2:1 Q1:0 Q0:0 GS:0 EO:1  1    1    x    x
1964 * WAKE2'          12 I2   Q2:1 Q1:0 Q0:1 GS:0 EO:1  x    1    x    x
1965 * WAKE1'          11 I1   Q2:1 Q1:1 Q0:0 GS:0 EO:1  1    x    x    x
1966 * 0 (GND)         10 I0   Q2:1 Q1:1 Q0:1 GS:0 EO:1  x    x    x    x
1967 * </PRE>
1968 */
1969void alto2_cpu_device::f1_task_0()
1970{
1971#if   USE_PRIO_F9318
1972   /* Doesn't work yet */
1973   register f9318_in_t wakeup_hi;
1974   register f9318_out_t u1;
1975   register f9318_in_t wakeup_lo;
1976   register f9318_out_t u2;
1977   register int addr = 017;
1978   register int rdct1, rdct2, rdct4, rdct8;
1979   register int ct1, ct2, ct4, ct8;
1980   register int wakeup, ct;
1981
1982   LOG((LOG_CPU,2, "   TASK %02o:%s\n", m_task, task_name(m_task)));
1983
1984   if (m_task > task_emu && (m_task_wakeup & (1 << m_task)))
1985      addr = m_task;
1986   LOG((LOG_CPU,2,"   ctl2k_u38[%02o] = %04o\n", addr, ctl2k_u38[addr] & 017));
1987
1988   rdct1 = (ctl2k_u38[addr] >> U38_RDCT1) & 1;
1989   rdct2 = (ctl2k_u38[addr] >> U38_RDCT2) & 1;
1990   rdct4 = (ctl2k_u38[addr] >> U38_RDCT4) & 1;
1991   rdct8 = (ctl2k_u38[addr] >> U38_RDCT8) & 1;
1992
1993   /* wakeup signals are active low */
1994   wakeup = ~m_task_wakeup;
1995
1996   /* U1
1997    * task wakeups 017 to 010 on I7 to I0
1998    * EI is 0 (would be 1 at reset)
1999    */
2000   wakeup_hi = (wakeup >> 8) & PRIO_I0_I7;
2001   u1 = f9318(wakeup_hi);
2002
2003   /* U2
2004    * task wakeups 007 to 001 on I7 to I1, I0 is 0
2005    * EO of U1 chained to EI
2006    */
2007   wakeup_lo = wakeup & PRIO_I0_I7;
2008   if (u1 & PRIO_OUT_EO)
2009      wakeup_lo |= PRIO_IN_EI;
2010   u2 = f9318(wakeup_lo);
2011
2012   /* CT1 = (U1.Q0' & U2.Q0' & RDCT1')' */
2013   ct1 = !((u1 & PRIO_OUT_Q0) && (u2 & PRIO_OUT_Q0) && rdct1);
2014   LOG((LOG_CPU,2,"     CT1:%o U1.Q0':%o U2.Q0':%o RDCT1':%o\n",
2015      ct1, (u1 & PRIO_OUT_Q0)?1:0, (u2 & PRIO_OUT_Q0)?1:0, rdct1));
2016   /* CT2 = (U1.Q1' & U2.Q1' & RDCT2')' */
2017   ct2 = !((u1 & PRIO_OUT_Q1) && (u2 & PRIO_OUT_Q1) && rdct2);
2018   LOG((LOG_CPU,2,"     CT2:%o U1.Q1':%o U2.Q1':%o RDCT2':%o\n",
2019      ct2, (u1 & PRIO_OUT_Q1)?1:0, (u2 & PRIO_OUT_Q1)?1:0, rdct2));
2020   /* CT4 = (U1.Q2' & U2.Q2' & RDCT4')' */
2021   ct4 = !((u1 & PRIO_OUT_Q2) && (u2 & PRIO_OUT_Q2) && rdct4);
2022   LOG((LOG_CPU,2,"     CT4:%o U1.Q2':%o U2.Q2':%o RDCT4':%o\n",
2023      ct4, (u1 & PRIO_OUT_Q2)?1:0, (u2 & PRIO_OUT_Q2)?1:0, rdct4));
2024   /* CT8 */
2025   ct8 = !((u1 & PRIO_OUT_GS) && rdct8);
2026   LOG((LOG_CPU,2,"     CT8:%o U1.GS':%o RDCT8':%o\n",
2027      ct8, (u1 & PRIO_OUT_GS)?1:0, rdct8));
2028
2029   ct = 8*ct8 + 4*ct4 + 2*ct2 + ct1;
2030
2031   if (ct != m_next_task) {
2032      LOG((LOG_CPU,2, "      switch to %02o\n", ct));
2033      m_next2_task = ct;
2034   } else {
2035      LOG((LOG_CPU,2, "      no switch\n"));
2036   }
2037#else   /* USE_PRIO_F9318 */
2038   int i;
2039
2040   LOG((LOG_CPU,2, "   TASK %02o:%s", m_task, task_name(m_task)));
2041   for (i = 15; i >= 0; i--) {
2042      if (m_task_wakeup & (1 << i)) {
2043         m_next2_task = i;
2044         if (m_next2_task != m_next_task) {
2045            LOG((LOG_CPU,2, " switch to %02o:%s\n", m_next2_task, task_name(m_next2_task)));
2046         } else {
2047            LOG((LOG_CPU,2, " no switch\n"));
2048         }
2049         return;
2050      }
2051   }
2052   fatal(3, "no tasks requesting service\n");
2053#endif   /* !USE_PRIO_F9318 */
2054}
2055
2056#ifdef   f1_block0_unused
2057/**
2058 * @brief f1_block early: block task
2059 *
2060 * The task request for the active task is cleared
2061 */
2062void alto2_cpu_device::f1_block_0()
2063{
2064   CPU_CLR_TASK_WAKEUP(m_task);
2065   LOG((LOG_CPU,2, "   BLOCK %02o:%s\n", m_task, task_name(m_task)));
2066}
2067#endif
2068
2069/**
2070 * @brief f2_bus_eq_zero late: branch on bus equals zero
2071 */
2072void alto2_cpu_device::f2_bus_eq_zero_1()
2073{
2074   UINT16 r = m_bus == 0 ? 1 : 0;
2075   LOG((LOG_CPU,2, "   BUS=0; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2076   m_next2 |= r;
2077}
2078
2079/**
2080 * @brief f2_shifter_lt_zero late: branch on shifter less than zero
2081 */
2082void alto2_cpu_device::f2_shifter_lt_zero_1()
2083{
2084   UINT16 r = (m_shifter & 0100000) ? 1 : 0;
2085   LOG((LOG_CPU,2, "   SH<0; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2086   m_next2 |= r;
2087}
2088
2089/**
2090 * @brief f2_shifter_eq_zero late: branch on shifter equals zero
2091 */
2092void alto2_cpu_device::f2_shifter_eq_zero_1()
2093{
2094   UINT16 r = m_shifter == 0 ? 1 : 0;
2095   LOG((LOG_CPU,2, "   SH=0; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2096   m_next2 |= r;
2097}
2098
2099/**
2100 * @brief f2_bus late: branch on bus bits BUS[6-15]
2101 */
2102void alto2_cpu_device::f2_bus_1()
2103{
2104   UINT16 r = A2_GET16(m_bus,16,6,15);
2105   LOG((LOG_CPU,2, "   BUS; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2106   m_next2 |= r;
2107}
2108
2109/**
2110 * @brief f2_alucy late: branch on latched ALU carry
2111 */
2112void alto2_cpu_device::f2_alucy_1()
2113{
2114   UINT16 r = m_laluc0;
2115   LOG((LOG_CPU,2, "   ALUCY; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2116   m_next2 |= r;
2117}
2118
2119/**
2120 * @brief f2_load_md late: load memory data
2121 *
2122 * Deliver BUS data to memory.
2123 */
2124void alto2_cpu_device::f2_load_md_1()
2125{
2126#if   ALTO2_DEBUG
2127   UINT16 mar = m_mem.mar;
2128#endif
2129   if (MIR_F1(m_mir) == f1_load_mar) {
2130      /* part of an XMAR */
2131      LOG((LOG_CPU,2, "   XMAR %#o (%#o)\n", mar, m_bus));
2132   } else {
2133      write_mem(m_bus);
2134      LOG((LOG_CPU,2, "   MD← BUS ([%#o]=%#o)\n", mar, m_bus));
2135   }
2136}
2137
2138/**
2139 * @brief read the microcode ROM/RAM halfword
2140 *
2141 * Note: HALFSEL is selecting the even (0) or odd (1) half of the
2142 * microcode RAM 32-bit word. Here's how the demultiplexers (74298)
2143 * u8, u18, u28 and u38 select the bits:
2144 *
2145 *           SN74298
2146 *         +---+-+---+
2147 *         |   +-+   |
2148 *    B2  -|1      16|-  Vcc
2149 *         |         |
2150 *    A2  -|2      15|-  QA
2151 *         |         |
2152 *    A1  -|3      14|-  QB
2153 *         |         |
2154 *    B1  -|4      13|-  QC
2155 *         |         |
2156 *    C2  -|5      12|-  QD
2157 *         |         |
2158 *    D2  -|6      11|-  CLK
2159 *         |         |
2160 *    D1  -|7      10|-  SEL
2161 *         |         |
2162 *   GND  -|8       9|-  C1
2163 *         |         |
2164 *         +---------+
2165 *
2166 *   chip  out pin  BUS in   pin HSEL=0      in   pin HSEL=1
2167 *   --------------------------------------------------------------
2168 *  u8    QA  15   0   A1   3   DRSEL(0)'   A2   2   DF2(0)
2169 *  u8    QB  14   1   B1   4   DRSEL(1)'   B2   1   DF2(1)'
2170 *  u8    QC  13   2   C1   9   DRSEL(2)'   C2   5   DF2(2)'
2171 *  u8    QD  12   3   D1   7   DRSEL(3)'   D2   6   DF2(3)'
2172 *
2173 *  u18   QA  15   4   A1   3   DRSEL(4)'   A2   2   LOADT'
2174 *  u18   QB  14   5   B1   4   DALUF(0)'   B2   1   LOADL
2175 *  u18   QC  13   6   C1   9   DALUF(1)'   C2   5   NEXT(00)'
2176 *  u18   QD  12   7   D1   7   DALUF(2)'   D2   6   NEXT(01)'
2177 *
2178 *  u28   QA  15   8   A1   3   DALUF(3)'   A2   2   NEXT(02)'
2179 *  u28   QB  14   9   B1   4   DBS(0)'     B2   1   NEXT(03)'
2180 *  u28   QC  13   10  C1   9   DBS(1)'     C2   5   NEXT(04)'
2181 *  u28   QD  12   11  D1   7   DBS(2)'     D2   6   NEXT(05)'
2182 *
2183 *  u38   QA  15   12  A1   3   DF1(0)      A2   2   NEXT(06)'
2184 *  u38   QB  14   13  B1   4   DF1(1)'     B2   1   NEXT(07)'
2185 *  u38   QC  13   14  C1   9   DF1(2)'     C2   5   NEXT(08)'
2186 *  u38   QD  12   15  D1   7   DF1(3)'     D2   6   NEXT(09)'
2187 *
2188 * The HALFSEL signal to the demultiplexers is the inverted bit BUS(5):
2189 * BUS(5)=1, HALFSEL=0, A1,B1,C1,D1 inputs, upper half of the 32-bit word
2190 * BUS(5)=0, HALFSEL=1, A2,B2,C2,D2 inputs, lower half of the 32-bit word
2191 */
2192void alto2_cpu_device::rdram()
2193{
2194   UINT32 addr, val;
2195   UINT32 bank = GET_CRAM_BANKSEL(m_cram_addr) % ALTO2_UCODE_RAM_PAGES;
2196   UINT32 wordaddr = GET_CRAM_WORDADDR(m_cram_addr);
2197
2198   m_rdram_flag = false;
2199   if (GET_CRAM_RAMROM(m_cram_addr)) {
2200      /* read ROM 0 at current mpc */
2201      addr = m_mpc & 01777;
2202      LOG((LOG_CPU,0,"   rdram: ROM [%05o] ", addr));
2203   } else {
2204      /* read RAM 0,1,2 */
2205      addr = bank * ALTO2_UCODE_PAGE_SIZE + wordaddr;
2206      LOG((LOG_CPU,0,"   rdram: RAM%d [%04o] ", bank, wordaddr));
2207   }
2208
2209   if (ALTO2_UCODE_RAM_BASE + addr >= ALTO2_UCODE_SIZE) {
2210      val = 0177777;   /* ??? */
2211      LOG((LOG_CPU,0,"invalid address (%06o)\n", val));
2212      return;
2213   }
2214   val = RD_CRAM(addr) ^ ALTO2_UCODE_INVERTED;
2215   if (GET_CRAM_HALFSEL(m_cram_addr)) {
2216      val = val >> 16;
2217      LOG((LOG_CPU,0,"upper:%06o\n", val));
2218   } else {
2219      val = val & 0177777;
2220      LOG((LOG_CPU,0,"lower:%06o\n", val));
2221   }
2222   m_bus &= val;
2223}
2224
2225/**
2226 * @brief write the microcode RAM from M register and ALU
2227 *
2228 * Note: M is a latch (MYL, i.e. memory L) on the CRAM board that latches
2229 * the ALU whenever LOADL and GOODTASK are met. GOODTASK is the Emulator
2230 * task and something I have not yet found out about: TASKA' and TASKB'.
2231 *
2232 * There's also an undumped PROM u21 which is addressed by GOODTASK and
2233 * 7 other signals...
2234 */
2235void alto2_cpu_device::wrtram()
2236{
2237   UINT32 addr;
2238   UINT32 bank = GET_CRAM_BANKSEL(m_cram_addr) % ALTO2_UCODE_RAM_PAGES;
2239   UINT32 wordaddr = GET_CRAM_WORDADDR(m_cram_addr);
2240
2241   m_wrtram_flag = false;
2242
2243   /* write RAM 0,1,2 */
2244   addr = bank * ALTO2_UCODE_PAGE_SIZE + wordaddr;
2245   LOG((LOG_CPU,0,"   wrtram: RAM%d [%04o] upper:%06o lower:%06o", bank, wordaddr, m_m, m_alu));
2246   if (ALTO2_UCODE_RAM_BASE + addr >= ALTO2_UCODE_SIZE) {
2247      LOG((LOG_CPU,0," invalid address\n"));
2248      return;
2249   }
2250   LOG((LOG_CPU,0,"\n"));
2251   WR_CRAM(addr, ((m_m << 16) | m_alu) ^ ALTO2_UCODE_INVERTED);
2252}
2253
2254#if   USE_ALU_74181
2255/**
2256 * <PRE>
2257 * Functional description of the 4-bit ALU 74181
2258 *
2259 * The 74181 is a 4-bit high speed parallel Arithmetic Logic Unit (ALU).
2260 * Controlled by four Function Select inputs (S0-S3) and the Mode Control
2261 * input (M), it can perform all the 16 possible logic operations or 16
2262 * different arithmetic operations on active HIGH or active LOW operands.
2263 * The Function Table lists these operations.
2264 *
2265 * When the Mode Control input (M) is HIGH, all internal carries are
2266 * inhibited and the device performs logic operations on the individual
2267 * bits as listed. When the Mode Control input is LOW, the carries are
2268 * enabled and the device performs arithmetic operations on the two 4-bit
2269 * words. The device incorporates full internal carry lookahead and
2270 * provides for either ripple carry between devices using the Cn+4 output,
2271 * or for carry lookahead between packages using the signals P' (Carry
2272 * Propagate) and G' (Carry Generate). In the ADD mode, P' indicates that
2273 * F' is 15 or more, while G' indicates that F' is 16 or more. In the
2274 * SUBTRACT mode, P' indicates that F' is zero or less, while G' indicates
2275 * that F' is less than zero. P' and G' are not affected by carry in.
2276 * When speed requirements are not stringent, it can be used in a simple
2277 * ripple carry mode by connecting the Carry output (Cn+4) signal to the
2278 * Carry input (Cn) of the next unit. For high speed operation the device
2279 * is used in conjunction with the 74182 carry lookahead circuit. One
2280 * carry lookahead package is required for each group of four 74181 devices.
2281 * Carry lookahead can be provided at various levels and offers high speed
2282 * capability over extremely long word lengths.
2283 *
2284 * The A=B output from the device goes HIGH when all four F' outputs are
2285 * HIGH and can be used to indicate logic equivalence over four bits when
2286 * the unit is in the subtract mode. The A=B output is open collector and
2287 * can be wired-AND with other A=B outputs to give a comparison for more
2288 * than four bits. The A=B signal can also be used with the Cn+4 signal
2289 * to indicated A>B and A<B.
2290 *
2291 * The Function Table lists the arithmetic operations that are performed
2292 * without a carry in. An incoming carry adds a one to each operation.
2293 * Thus, select code 0110 generates A minus B minus 1 (2's complement
2294 * notation) without a carry in and generates A minus B when a carry is
2295 * applied. Because subtraction is actually performed by the complementary
2296 * addition (1's complement), a carry out means borrow; thus a carry is
2297 * generated when there is no underflow and no carry is generated when
2298 * there is underflow. As indicated, this device can be used with either
2299 * active LOW inputs producing active LOW outputs or with active HIGH
2300 * inputs producing active HIGH outputs. For either case the table lists
2301 * the operations that are performed to the operands labeled inside the
2302 * logic symbol.
2303 *
2304 * The AltoI/II use four 74181s and a 74182 carry lookahead circuit,
2305 * and the inputs and outputs are all active HIGH.
2306 *
2307 * Active HIGH operands:
2308 *
2309 * +-------------------+-------------+------------------------+------------------------+
2310 * |    Mode Select    |   Logic     | Arithmetic w/o carry   | Arithmetic w/ carry    |
2311 * |      Inputs       |             |                        |                        |
2312 * |  S3  S2  S1  S0   |   (M=1)     | (M=0) (Cn=1)           | (M=0) (Cn=0)           |
2313 * +-------------------+-------------+------------------------+------------------------+
2314 * |   0   0   0   0   | A'          | A                      | A + 1                  |
2315 * +-------------------+-------------+------------------------+------------------------+
2316 * |   0   0   0   1   | A' | B'     | A | B                  | (A | B) + 1            |
2317 * +-------------------+-------------+------------------------+------------------------+
2318 * |   0   0   1   0   | A' & B      | A | B'                 | (A | B') + 1           |
2319 * +-------------------+-------------+------------------------+------------------------+
2320 * |   0   0   1   1   | logic 0     | - 1                    | -1 + 1                 |
2321 * +-------------------+-------------+------------------------+------------------------+
2322 * |   0   1   0   0   | (A & B)'    | A + (A & B')           | A + (A & B') + 1       |
2323 * +-------------------+-------------+------------------------+------------------------+
2324 * |   0   1   0   1   | B'          | (A | B) + (A & B')     | (A | B) + (A & B') + 1 |
2325 * +-------------------+-------------+------------------------+------------------------+
2326 * |   0   1   1   0   | A ^ B       | A - B - 1              | A - B - 1 + 1          |
2327 * +-------------------+-------------+------------------------+------------------------+
2328 * |   0   1   1   1   | A & B'      | (A & B) - 1            | (A & B) - 1 + 1        |
2329 * +-------------------+-------------+------------------------+------------------------+
2330 * |   1   0   0   0   | A' | B      | A + (A & B)            | A + (A & B) + 1        |
2331 * +-------------------+-------------+------------------------+------------------------+
2332 * |   1   0   0   1   | A' ^ B'     | A + B                  | A + B + 1              |
2333 * +-------------------+-------------+------------------------+------------------------+
2334 * |   1   0   1   0   | B           | (A | B') + (A & B)     | (A | B') + (A & B) + 1 |
2335 * +-------------------+-------------+------------------------+------------------------+
2336 * |   1   0   1   1   | A & B       | (A & B) - 1            | (A & B) - 1 + 1        |
2337 * +-------------------+-------------+------------------------+------------------------+
2338 * |   1   1   0   0   | logic 1     | A + A                  | A + A + 1              |
2339 * +-------------------+-------------+------------------------+------------------------+
2340 * |   1   1   0   1   | A | B'      | (A | B) + A            | (A | B) + A + 1        |
2341 * +-------------------+-------------+------------------------+------------------------+
2342 * |   1   1   1   0   | A | B       | (A | B') + A           | (A | B') + A + 1       |
2343 * +-------------------+-------------+------------------------+------------------------+
2344 * |   1   1   1   1   | A           | A - 1                  | A - 1 + 1              |
2345 * +-------------------+-------------+------------------------+------------------------+
2346 * </PRE>
2347 */
2348
2349enum {
2350    A10_UNUSED  = (1 << 0),
2351    A10_TSELECT = (1 << 1),
2352    A10_ALUCI   = (1 << 2),
2353    A10_ALUM    = (1 << 3),
2354    A10_ALUS0   = (1 << 4),
2355    A10_ALUS1   = (1 << 5),
2356    A10_ALUS2   = (1 << 6),
2357    A10_ALUS3   = (1 << 7),
2358    A10_ALUIN   = (A10_ALUM|A10_ALUCI|A10_ALUS0|A10_ALUS1|A10_ALUS2|A10_ALUS3)
2359};
2360
2361//! S function, M flag and C carry in
2362#define   SMC(s3,s2,s1,s0,m,ci) (s3*A10_ALUS3 + s2*A10_ALUS2 + s1*A10_ALUS1 + s0*A10_ALUS0 + m*A10_ALUM + ci*A10_ALUCI)
2363
2364/**
2365 * @brief Compute the 74181 ALU operation smc for inputs a and b
2366 *
2367 * The function, arithmetic / logic flag and carry in define the
2368 * ALU operation. The carry in is irrelevant for the logic operations.
2369 * The result is 17 bit, where bit #16 is the carry out.
2370 *
2371 * @param smc S function [0-15], M arithmetic/logic flag, C carry
2372 * @return resulting ALU output
2373 */
2374UINT32 alto2_cpu_device::alu_74181(UINT32 a, UINT32 b, UINT8 smc)
2375{
2376   register UINT32 f;
2377   register const UINT32 cout = 1 << 16;
2378
2379   switch (smc & A10_ALUIN) {
2380   case SMC(0,0,0,0, 0, 0): // 0000: A + 1
2381      f = a + 1;
2382      break;
2383
2384   case SMC(0,0,0,0, 0, 1): // 0000: A
2385      f = a;
2386      break;
2387
2388   case SMC(0,0,0,0, 1, 0): // 0000: A'
2389   case SMC(0,0,0,0, 1, 1):
2390      f = (~a) | cout;
2391      break;
2392
2393   case SMC(0,0,0,1, 0, 0): // 0001: (A | B) + 1
2394      f = (a | b) + 1;
2395      break;
2396
2397   case SMC(0,0,0,1, 0, 1): // 0001: A | B
2398      f = a | b;
2399      break;
2400
2401   case SMC(0,0,0,1, 1, 0): // 0001: A' | B'
2402   case SMC(0,0,0,1, 1, 1):
2403      f = (~a | ~b) | cout;
2404      break;
2405
2406   case SMC(0,0,1,0, 0, 0): // 0010: (A | B') + 1
2407      f = (a | ~b) + 1;
2408      break;
2409
2410   case SMC(0,0,1,0, 0, 1): // 0010: A | B'
2411      f = a | ~b;
2412      break;
2413
2414   case SMC(0,0,1,0, 1, 0): // 0010: A' & B
2415   case SMC(0,0,1,0, 1, 1):
2416      f = (~a & b) | cout;
2417      break;
2418
2419   case SMC(0,0,1,1, 0, 0): // 0011: -1 + 1
2420      f = (-1 + 1) | cout;
2421      break;
2422
2423   case SMC(0,0,1,1, 0, 1): // 0011: -1
2424      f = (-1) | cout;
2425      break;
2426
2427   case SMC(0,0,1,1, 1, 0): // 0011: logic 0
2428   case SMC(0,0,1,1, 1, 1):
2429      f = cout;
2430      break;
2431
2432   case SMC(0,1,0,0, 0, 0): // 0100: A + (A & B') + 1
2433      f = a + (a & ~b) + 1;
2434      break;
2435
2436   case SMC(0,1,0,0, 0, 1): // 0100: A + (A & B')
2437      f = a + (a & ~b);
2438      break;
2439
2440   case SMC(0,1,0,0, 1, 0): // 0100: (A & B)'
2441   case SMC(0,1,0,0, 1, 1):
2442      f = ~(a & b) | cout;
2443      break;
2444
2445   case SMC(0,1,0,1, 0, 0): // 0101: (A | B) + (A & B') + 1
2446      f = (a | b) + (a & ~b) + 1;
2447      break;
2448
2449   case SMC(0,1,0,1, 0, 1): // 0101: (A | B) + (A & B')
2450      f = (a | b) + (a & ~b);
2451      break;
2452
2453   case SMC(0,1,0,1, 1, 0): // 0101: B'
2454   case SMC(0,1,0,1, 1, 1):
2455      f = (~b) | cout;
2456      break;
2457
2458   case SMC(0,1,1,0, 0, 0): // 0110: A - B - 1 + 1
2459      f = (a - b - 1 + 1)  ^ cout;
2460      break;
2461
2462   case SMC(0,1,1,0, 0, 1): // 0110: A - B - 1
2463      f = (a - b - 1) ^ cout;
2464      break;
2465
2466   case SMC(0,1,1,0, 1, 0): // 0110: A ^ B
2467   case SMC(0,1,1,0, 1, 1):
2468      f = (a ^ b) | cout;
2469      break;
2470
2471   case SMC(0,1,1,1, 0, 0): // 0111: (A & B) - 1 + 1
2472      f = ((a & b) - 1 + 1) ^ cout;
2473      break;
2474
2475   case SMC(0,1,1,1, 0, 1): // 0111: (A & B) - 1
2476      f = ((a & b) - 1) ^ cout;
2477      break;
2478
2479   case SMC(0,1,1,1, 1, 0): // 0111: A & B'
2480   case SMC(0,1,1,1, 1, 1):
2481      f = (a & ~b) | cout;
2482      break;
2483
2484   case SMC(1,0,0,0, 0, 0): // 1000: A + (A & B) + 1
2485      f = a + (a & b) + 1;
2486      break;
2487
2488   case SMC(1,0,0,0, 0, 1): // 1000: A + (A & B)
2489      f = a + (a & b);
2490      break;
2491
2492   case SMC(1,0,0,0, 1, 0): // 1000: A' | B
2493   case SMC(1,0,0,0, 1, 1):
2494      f = (~a | b) | cout;
2495      break;
2496
2497   case SMC(1,0,0,1, 0, 0): // 1001: A + B + 1
2498      f = a + b + 1;
2499      break;
2500
2501   case SMC(1,0,0,1, 0, 1): // 1001: A + B
2502      f = a + b;
2503      break;
2504
2505   case SMC(1,0,0,1, 1, 0): // 1001: A' ^ B'
2506   case SMC(1,0,0,1, 1, 1):
2507      f = (~a ^ ~b) | cout;
2508      break;
2509
2510   case SMC(1,0,1,0, 0, 0): // 1010: (A | B') + (A & B) + 1
2511      f = (a | ~b) + (a & b) + 1;
2512      break;
2513
2514   case SMC(1,0,1,0, 0, 1): // 1010: (A | B') + (A & B)
2515      f = (a | ~b) + (a & b);
2516      break;
2517
2518   case SMC(1,0,1,0, 1, 0): // 1010: B
2519   case SMC(1,0,1,0, 1, 1):
2520      f = (b) | cout;
2521      break;
2522
2523   case SMC(1,0,1,1, 0, 0): // 1011: (A & B) - 1 + 1
2524      f = ((a & b) - 1 + 1) ^ cout;
2525      break;
2526
2527   case SMC(1,0,1,1, 0, 1): // 1011: (A & B) - 1
2528      f = ((a & b) - 1)  ^ cout;
2529      break;
2530
2531   case SMC(1,0,1,1, 1, 0): // 1011: A & B
2532   case SMC(1,0,1,1, 1, 1):
2533      f = (a & b) | cout;
2534      break;
2535
2536   case SMC(1,1,0,0, 0, 0): // 1100: A + A + 1
2537      f = a + a + 1;
2538      break;
2539
2540   case SMC(1,1,0,0, 0, 1): // 1100: A + A
2541      f = a + a;
2542      break;
2543
2544   case SMC(1,1,0,0, 1, 0): // 1100: logic 1
2545   case SMC(1,1,0,0, 1, 1):
2546      f = (~0) | cout;
2547      break;
2548
2549   case SMC(1,1,0,1, 0, 0): // 1101: (A | B) + A + 1
2550      f = (a | b) + a + 1;
2551      break;
2552
2553   case SMC(1,1,0,1, 0, 1): // 1101: (A | B) + A
2554      f = (a | b) + a;
2555      break;
2556
2557   case SMC(1,1,0,1, 1, 0): // 1101: A | B'
2558   case SMC(1,1,0,1, 1, 1):
2559      f = (a | ~b) | cout;
2560      break;
2561
2562   case SMC(1,1,1,0, 0, 0): // 1110: (A | B') + A + 1
2563      f = (a | ~b) + a + 1;
2564      break;
2565
2566   case SMC(1,1,1,0, 0, 1): // 1110: (A | B') + A
2567      f = (a | ~b) + a;
2568      break;
2569
2570   case SMC(1,1,1,0, 1, 0): // 1110: A | B
2571   case SMC(1,1,1,0, 1, 1):
2572      f = (a | b) | cout;
2573      break;
2574
2575   case SMC(1,1,1,1, 0, 0): // 1111: A - 1 + 1
2576      f = (a - 1 + 1) ^ cout;
2577      break;
2578
2579   case SMC(1,1,1,1, 0, 1): // 1111: A - 1
2580      f = (a - 1) ^ cout;
2581      break;
2582
2583   case SMC(1,1,1,1, 1, 0): // 1111: A
2584   case SMC(1,1,1,1, 1, 1):
2585      f = (a) | cout;
2586      break;
2587   }
2588   return f;
2589}
2590#endif
2591
2592/** @brief flag that tells whether to load the T register from BUS or ALU */
2593#define   TSELECT   A10_TSELECT
2594
2595/** @brief flag that tells wheter operation was 0: logic (M=1) or 1: arithmetic (M=0) */
2596#define   ALUM2   A10_ALUM
2597
2598/** @brief execute the CPU for at most nsecs nano seconds */
2599void alto2_cpu_device::execute_run()
2600{
2601   m_next = m_task_mpc[m_task];      // get current task's next mpc and address modifier
2602   m_next2 = m_task_next2[m_task];
2603
2604   do {
2605      int do_bs, flags;
2606
2607      /*
2608       * Subtract the microcycle time from the display time accu.
2609       * If it underflows, call the display state machine and add
2610       * the time for 24 pixel clocks to the accu.
2611       * This is very close to every seventh CPU cycle.
2612       */
2613      m_dsp_time -= ALTO2_UCYCLE;
2614      if (m_dsp_time < 0) {
2615         m_dsp_state = display_state_machine(m_dsp_state);
2616         m_dsp_time += ALTO2_DISPLAY_BITTIME(24);
2617      }
2618      if (m_unload_time >= 0) {
2619         /*
2620          * Subtract the microcycle time from the unload time accu.
2621          * If it underflows, call the unload word function which adds
2622          * the time for 16 or 32 pixel clocks to the accu, or ends
2623          * the unloading by leaving m_unload_time at -1.
2624          */
2625         m_unload_time -= ALTO2_UCYCLE;
2626         if (m_unload_time < 0) {
2627            m_unload_word = unload_word(m_unload_word);
2628         }
2629      }
2630#if   (USE_BITCLK_TIMER == 0)
2631      if (m_bitclk_time >= 0) {
2632         /*
2633          * Subtract the microcycle time from the bitclk time accu.
2634          * If it underflows, call the disk bitclk function which adds
2635          * the time for one bit as clocks to the accu, or ends
2636          * the bitclk sequence by leaving m_bitclk_time at -1.
2637          */
2638         m_bitclk_time -= ALTO2_UCYCLE;
2639         disk_bitclk(0, m_bitclk_index);
2640      }
2641#endif
2642
2643      m_cycle++;
2644      /* nano seconds per cycle */
2645      m_ntime[m_task] += ALTO2_UCYCLE;
2646
2647      /* next instruction's mpc */
2648      m_mpc = m_next;
2649      m_mir = RD_CROM(m_mpc);
2650      m_rsel = MIR_RSEL(m_mir);
2651      m_next = MIR_NEXT(m_mir) | m_next2;
2652      m_next2 = A2_GET32(RD_CROM(m_next), 32, NEXT0, NEXT9) | (m_next2 & ~ALTO2_UCODE_PAGE_MASK);
2653      UINT8 aluf = MIR_ALUF(m_mir);
2654      UINT8 bs = MIR_BS(m_mir);
2655      UINT8 f1 = MIR_F1(m_mir);
2656      UINT8 f2 = MIR_F2(m_mir);
2657      LOG((LOG_CPU,2,"%s-%04o: %011o r:%02o aluf:%02o bs:%02o f1:%02o f2:%02o t:%o l:%o next:%05o next2:%05o\n",
2658         task_name(m_task), m_mpc, m_mir, m_rsel, aluf, bs, f1, f2, MIR_T(m_mir), MIR_L(m_mir), m_next, m_next2));
2659      debugger_instruction_hook(this, m_mpc);
2660
2661      /*
2662       * This bus source decoding is not performed if f1 = 7 or f2 = 7.
2663       * These functions use the BS field to provide part of the address
2664       * to the constant ROM
2665       */
2666      do_bs = !(f1 == f1_const || f2 == f2_const);
2667
2668      if (f1 == f1_load_mar) {
2669         if (check_mem_load_mar_stall(m_rsel)) {
2670            LOG((LOG_CPU,3, "   MAR← stall\n"));
2671            m_next2 = m_next;
2672            m_next = m_mpc;
2673            continue;
2674         }
2675      } else if (f2 == f2_load_md) {
2676         if (check_mem_write_stall()) {
2677            LOG((LOG_CPU,3, "   MD← stall\n"));
2678            m_next2 = m_next;
2679            m_next = m_mpc;
2680            continue;
2681         }
2682      }
2683      if (do_bs && bs == bs_read_md) {
2684         if (check_mem_read_stall()) {
2685            LOG((LOG_CPU,3, "   ←MD stall\n"));
2686            m_next2 = m_next;
2687            m_next = m_mpc;
2688            continue;
2689         }
2690      }
2691
2692      m_bus = 0177777;
2693
2694      if (m_rdram_flag)
2695         rdram();
2696
2697      /*
2698       * The constant memory is gated to the bus by F1 = 7, F2 = 7, or BS >= 4
2699       */
2700      if (!do_bs || bs >= 4) {
2701         int addr = 8 * m_rsel + bs;
2702         // There is something going wrong with using:
2703         // m_const->read_word(m_const->address_to_byte(addr));
2704         // because for addr=0160 it returns const[0161] instead of const[0160]
2705         // For now fall back to reading the const data from the byte array
2706         UINT16 data = m_const_data[2*addr+0] | (m_const_data[2*addr+1] << 8);
2707         m_bus &= data;
2708         LOG((LOG_CPU,2,"   %#o; BUS &= %#o CONST[%03o]\n", m_bus, data, addr));
2709      }
2710
2711      /*
2712       * early f2 has to be done before early bs, because the
2713       * emulator f2 acsource or acdest may change rsel
2714       */
2715      ((*this).*m_f2[0][m_task][f2])();
2716
2717      /*
2718       * early bs can be done now
2719       */
2720      if (do_bs)
2721         ((*this).*m_bs[0][m_task][bs])();
2722
2723      /*
2724       * early f1
2725       */
2726      ((*this).*m_f1[0][m_task][f1])();
2727
2728#if   USE_ALU_74181
2729      // The ALU a10 PROM address lines are
2730      // A4:SKIP      A3:ALUF0     A2:ALUF1     A1:ALUF2     A0:ALUF3
2731      // The PROM output lines are
2732      // B0: unused   B1: TSELECT  B2: ALUCI'   B3: ALUM'
2733      // B4: ALUS0'   B5: ALUS1'   B6: ALUS2'   B7: ALUS3'
2734      // B1 and B3-B7 are inverted on loading the PROM
2735      UINT8 a10 = m_alu_a10[(m_emu.skip << 4) | aluf];
2736      UINT32 alu = alu_74181(m_bus, m_t, a10);
2737      m_aluc0 = (alu >> 16) & 1;
2738      flags = (a10 ^ ALUM2) & (TSELECT | ALUM2);
2739      m_alu = static_cast<UINT16>(alu);
2740#else
2741      UINT32 alu;
2742      /* compute the ALU function */
2743      switch (aluf) {
2744      /**
2745       * 00: ALU ← BUS
2746       * PROM data for S3-0:1111 M:1 C:0 T:0
2747       * 74181 function F=A
2748       * T source is BUS
2749       */
2750      case aluf_bus__alut:
2751         alu = m_bus;
2752         m_aluc0 = 1;
2753         flags = 0;
2754         LOG((LOG_CPU,2,"   ALU← BUS (%#o := %#o)\n", alu, m_bus));
2755         break;
2756
2757      /**
2758       * 01: ALU ← T
2759       * PROM data for S3-0:1010 M:1 C:0 T:0
2760       * 74181 function F=B
2761       * T source is BUS
2762       */
2763      case aluf_treg:
2764         alu = m_t;
2765         m_aluc0 = 1;
2766         flags = 0;
2767         LOG((LOG_CPU,2,"   ALU← T (%#o := %#o)\n", alu, m_t));
2768         break;
2769
2770      /**
2771       * 02: ALU ← BUS | T
2772       * PROM data for S3-0:1110 M:1 C:0 T:1
2773       * 74181 function F=A|B
2774       * T source is ALU
2775       */
2776      case aluf_bus_or_t__alut:
2777         alu = m_bus | m_t;
2778         m_aluc0 = 1;
2779         flags = TSELECT;
2780         LOG((LOG_CPU,2,"   ALU← BUS OR T (%#o := %#o | %#o)\n", alu, m_bus, m_t));
2781         break;
2782
2783      /**
2784       * 03: ALU ← BUS & T
2785       * PROM data for S3-0:1011 M:1 C:0 T:0
2786       * 74181 function F=A&B
2787       * T source is BUS
2788       */
2789      case aluf_bus_and_t:
2790         alu = m_bus & m_t;
2791         m_aluc0 = 1;
2792         flags = 0;
2793         LOG((LOG_CPU,2,"   ALU← BUS AND T (%#o := %#o & %#o)\n", alu, m_bus, m_t));
2794         break;
2795
2796      /**
2797       * 04: ALU ← BUS ^ T
2798       * PROM data for S3-0:0110 M:1 C:0 T:0
2799       * 74181 function F=A^B
2800       * T source is BUS
2801       */
2802      case aluf_bus_xor_t:
2803         alu = m_bus ^ m_t;
2804         m_aluc0 = 1;
2805         flags = 0;
2806         LOG((LOG_CPU,2,"   ALU← BUS XOR T (%#o := %#o ^ %#o)\n", alu, m_bus, m_t));
2807         break;
2808
2809      /**
2810       * 05: ALU ← BUS + 1
2811       * PROM data for S3-0:0000 M:0 C:0 T:1
2812       * 74181 function F=A+1
2813       * T source is ALU
2814       */
2815      case aluf_bus_plus_1__alut:
2816         alu = m_bus + 1;
2817         m_aluc0 = (alu >> 16) & 1;
2818         flags = ALUM2 | TSELECT;
2819         LOG((LOG_CPU,2,"   ALU← BUS + 1 (%#o := %#o + 1)\n", alu, m_bus));
2820         break;
2821
2822      /**
2823       * 06: ALU ← BUS - 1
2824       * PROM data for S3-0:1111 M:0 C:1 T:1
2825       * 74181 function F=A-1
2826       * T source is ALU
2827       */
2828      case aluf_bus_minus_1__alut:
2829         alu = m_bus + 0177777;
2830         m_aluc0 = (~alu >> 16) & 1;
2831         flags = ALUM2 | TSELECT;
2832         LOG((LOG_CPU,2,"   ALU← BUS - 1 (%#o := %#o - 1)\n", alu, m_bus));
2833         break;
2834
2835      /**
2836       * 07: ALU ← BUS + T
2837       * PROM data for S3-0:1001 M:0 C:1 T:0
2838       * 74181 function F=A+B
2839       * T source is BUS
2840       */
2841      case aluf_bus_plus_t:
2842         alu = m_bus + m_t;
2843         m_aluc0 = (alu >> 16) & 1;
2844         flags = ALUM2;
2845         LOG((LOG_CPU,2,"   ALU← BUS + T (%#o := %#o + %#o)\n", alu, m_bus, m_t));
2846         break;
2847
2848      /**
2849       * 10: ALU ← BUS - T
2850       * PROM data for S3-0:0110 M:0 C:0 T:0
2851       * 74181 function F=A-B
2852       * T source is BUS
2853       */
2854      case aluf_bus_minus_t:
2855         alu = m_bus + ~m_t + 1;
2856         m_aluc0 = (~alu >> 16) & 1;
2857         flags = ALUM2;
2858         LOG((LOG_CPU,2,"   ALU← BUS - T (%#o := %#o - %#o)\n", alu, m_bus, m_t));
2859         break;
2860
2861      /**
2862       * 11: ALU ← BUS - T - 1
2863       * PROM data for S3-0:0110 M:0 C:1 T:0
2864       * 74181 function F=A-B-1
2865       * T source is BUS
2866       */
2867      case aluf_bus_minus_t_minus_1:
2868         alu = m_bus + ~m_t;
2869         m_aluc0 = (~alu >> 16) & 1;
2870         flags = ALUM2;
2871         LOG((LOG_CPU,2,"   ALU← BUS - T - 1 (%#o := %#o - %#o - 1)\n", alu, m_bus, m_t));
2872         break;
2873
2874      /**
2875       * 12: ALU ← BUS + T + 1
2876       * PROM data for S3-0:1001 M:0 C:0 T:1
2877       * 74181 function F=A+B+1
2878       * T source is ALU
2879       */
2880      case aluf_bus_plus_t_plus_1__alut:
2881         alu = m_bus + m_t + 1;
2882         m_aluc0 = (alu >> 16) & 1;
2883         flags = ALUM2 | TSELECT;
2884         LOG((LOG_CPU,2,"   ALU← BUS + T + 1 (%#o := %#o + %#o + 1)\n", alu, m_bus, m_t));
2885         break;
2886
2887      /**
2888       * 13: ALU ← BUS + SKIP
2889       * PROM data for S3-0:0000 M:0 C:SKIP T:1
2890       * 74181 function F=A (SKIP=1) or F=A+1 (SKIP=0)
2891       * T source is ALU
2892       */
2893      case aluf_bus_plus_skip__alut:
2894         alu = m_bus + m_emu.skip;
2895         m_aluc0 = (alu >> 16) & 1;
2896         flags = ALUM2 | TSELECT;
2897         LOG((LOG_CPU,2,"   ALU← BUS + SKIP (%#o := %#o + %#o)\n", alu, m_bus, m_emu.skip));
2898         break;
2899
2900      /**
2901       * 14: ALU ← BUS,T
2902       * PROM data for S3-0:1011 M:1 C:0 T:1
2903       * 74181 function F=A&B
2904       * T source is ALU
2905       */
2906      case aluf_bus_and_t__alut:
2907         alu = m_bus & m_t;
2908         m_aluc0 = 1;
2909         flags = TSELECT;
2910         LOG((LOG_CPU,2,"   ALU← BUS,T (%#o := %#o & %#o)\n", alu, m_bus, m_t));
2911         break;
2912
2913      /**
2914       * 15: ALU ← BUS & ~T
2915       * PROM data for S3-0:0111 M:1 C:0 T:0
2916       * 74181 function F=A&~B
2917       * T source is BUS
2918       */
2919      case aluf_bus_and_not_t:
2920         alu = m_bus & ~m_t;
2921         m_aluc0 = 1;
2922         flags = 0;
2923         LOG((LOG_CPU,2,"   ALU← BUS AND NOT T (%#o := %#o & ~%#o)\n", alu, m_bus, m_t));
2924         break;
2925
2926      /**
2927       * 16: ALU ← BUS
2928       * PROM data for S3-0:1111 M:1 C:0 T:1
2929       * 74181 function F=A
2930       * T source is ALU
2931       */
2932      case aluf_undef_16:
2933         alu = m_bus;
2934         m_aluc0 = 1;
2935         flags = TSELECT;
2936         LOG((LOG_CPU,0,"   ALU← 0 (illegal aluf in task %s, mpc:%05o aluf:%02o)\n", task_name(m_task), m_mpc, aluf));
2937         break;
2938
2939      /**
2940       * 17: ALU ← BUS
2941       * PROM data for S3-0:1111 M:1 C:0 T:1
2942       * 74181 function F=A
2943       * T source is ALU
2944       */
2945      case aluf_undef_17:
2946      default:
2947         alu = m_bus;
2948         m_aluc0 = 1;
2949         flags = TSELECT;
2950         LOG((LOG_CPU,0,"   ALU← 0 (illegal aluf in task %s, mpc:%05o aluf:%02o)\n", task_name(m_task), m_mpc, aluf));
2951      }
2952      m_alu = static_cast<UINT16>(alu);
2953#endif
2954
2955      /* WRTRAM now, before L is changed */
2956      if (m_wrtram_flag)
2957         wrtram();
2958
2959      switch (f1) {
2960      case f1_l_lsh_1:
2961         if (m_task == task_emu) {
2962            if (f2 == f2_emu_magic) {
2963               m_shifter = ((m_l << 1) | (m_t >> 15)) & 0177777;
2964               LOG((LOG_CPU,2,"   SHIFTER ←L MLSH 1 (%#o := %#o<<1|%#o)\n", m_shifter, m_l, m_t >> 15));
2965               break;
2966            }
2967            if (f2 == f2_emu_load_dns) {
2968               /* shifter is done in F2 */
2969               break;
2970            }
2971         }
2972         m_shifter = (m_l << 1) & 0177777;
2973         LOG((LOG_CPU,2,"   SHIFTER ←L LSH 1 (%#o := %#o<<1)\n", m_shifter, m_l));
2974         break;
2975
2976      case f1_l_rsh_1:
2977         if (m_task == task_emu) {
2978            if (f2 == f2_emu_magic) {
2979               m_shifter = ((m_l >> 1) | (m_t << 15)) & 0177777;
2980               LOG((LOG_CPU,2,"   SHIFTER ←L MRSH 1 (%#o := %#o>>1|%#o)\n", m_shifter, m_l, (m_t << 15) & 0100000));
2981               break;
2982            }
2983            if (f2 == f2_emu_load_dns) {
2984               /* shifter is done in F2 */
2985               break;
2986            }
2987         }
2988         m_shifter = m_l >> 1;
2989         LOG((LOG_CPU,2,"   SHIFTER ←L RSH 1 (%#o := %#o>>1)\n", m_shifter, m_l));
2990         break;
2991
2992      case f1_l_lcy_8:
2993         m_shifter = ((m_l >> 8) | (m_l << 8)) & 0177777;
2994         LOG((LOG_CPU,2,"   SHIFTER ←L LCY 8 (%#o := bswap %#o)\n", m_shifter, m_l));
2995         break;
2996
2997      default:
2998         /* shifter passes L, if F1 is not one of L LSH 1, L RSH 1 or L LCY 8 */
2999         m_shifter = m_l;
3000      }
3001
3002      /* late F1 is done now, if any */
3003      ((*this).*m_f1[1][m_task][f1])();
3004
3005      /* late F2 is done now, if any */
3006      ((*this).*m_f2[1][m_task][f2])();
3007
3008      /* late BS is done now, if no constant was put on the bus */
3009      if (do_bs)
3010         ((*this).*m_bs[1][m_task][bs])();
3011
3012      /*
3013       * update L register and LALUC0, and also M register,
3014       * if a RAM related task is active
3015       */
3016      if (MIR_L(m_mir)) {
3017         /* load L from ALU */
3018         m_l = m_alu;
3019         if (flags & ALUM2) {
3020            m_laluc0 = m_aluc0;
3021            LOG((LOG_CPU,2, "   L← ALU (%#o); LALUC0← ALUC0 (%o)\n", m_alu, m_aluc0));
3022         } else {
3023            m_laluc0 = 0;
3024            LOG((LOG_CPU,2, "   L← ALU (%#o); LALUC0← %o\n", m_alu, 0));
3025         }
3026         if (m_ram_related[m_task]) {
3027            /* load M from ALU, if 'GOODTASK' */
3028            m_m = m_alu;
3029            /* also writes to S[bank][0], which can't be read */
3030            m_s[m_s_reg_bank[m_task]][0] = m_alu;
3031            LOG((LOG_CPU,2, "   M← ALU (%#o)\n", m_alu));
3032         }
3033      }
3034
3035      /* update T register, if LOADT is set */
3036      if (MIR_T(m_mir)) {
3037         m_cram_addr = m_alu;
3038         if (flags & TSELECT) {
3039            LOG((LOG_CPU,2, "   T← ALU (%#o)\n", m_alu));
3040            m_t = m_alu;
3041         } else {
3042            LOG((LOG_CPU,2, "   T← BUS (%#o)\n", m_bus));
3043            m_t = m_bus;
3044         }
3045      }
3046
3047      if (m_task != m_next2_task) {
3048         /* switch now? */
3049         if (m_task == m_next_task) {
3050            /* one more microinstruction */
3051            m_next_task = m_next2_task;
3052         } else {
3053            /* save this task's mpc */
3054            m_task_mpc[m_task] = m_next;
3055            m_task_next2[m_task] = m_next2;
3056            m_task = m_next_task;
3057            LOG((LOG_CPU,1, "task switch to %02o:%s (cycle %lld)\n", m_task, task_name(m_task), cycle()));
3058            /* get new task's mpc */
3059            m_next = m_task_mpc[m_task];
3060            /* get address modifier after task switch (?) */
3061            m_next2 = m_task_next2[m_task];
3062
3063            /*
3064             * let the task know it becomes active now
3065             * and (most probably) reset the wakeup
3066             */
3067            ((*this).*m_active_callback[m_task])();
3068         }
3069      }
3070   } while (m_icount-- > 0);
3071
3072   /* save this task's mpc and address modifier */
3073   m_task_mpc[m_task] = m_next;
3074   m_task_next2[m_task] = m_next2;
3075}
3076
3077/** @brief reset the various registers */
3078void alto2_cpu_device::hard_reset()
3079{
3080   /* all tasks start in ROM0 */
3081   m_reset_mode = 0xffff;
3082
3083   memset(&m_ram_related, 0, sizeof(m_ram_related));
3084
3085   // install standard handlers in all tasks
3086   for (int task = 0; task < ALTO2_TASKS; task++) {
3087
3088      // every task starts at mpc = task number, in either ROM0 or RAM0
3089      m_task_mpc[task] = (m_ctl2k_u38[task] >> 4) ^ 017;
3090      m_active_callback[task] = &alto2_cpu_device::noop;
3091      if (0 == (m_reset_mode & (1 << task)))
3092         m_task_mpc[task] |= ALTO2_UCODE_RAM_BASE;
3093
3094      set_bs(task, bs_read_r,         &alto2_cpu_device::bs_read_r_0,   0);
3095      set_bs(task, bs_load_r,         &alto2_cpu_device::bs_load_r_0,   &alto2_cpu_device::bs_load_r_1);
3096      set_bs(task, bs_no_source,      0, 0);
3097      set_bs(task, bs_task_3,         &alto2_cpu_device::fn_bs_bad_0,   &alto2_cpu_device::fn_bs_bad_1);   // task specific
3098      set_bs(task, bs_task_4,         &alto2_cpu_device::fn_bs_bad_0,   &alto2_cpu_device::fn_bs_bad_1);   // task specific
3099      set_bs(task, bs_read_md,      &alto2_cpu_device::bs_read_md_0, 0);
3100      set_bs(task, bs_mouse,         &alto2_cpu_device::bs_mouse_0, 0);
3101      set_bs(task, bs_disp,         &alto2_cpu_device::bs_disp_0, 0);
3102
3103      set_f1(task, f1_nop,         0, 0);
3104      set_f1(task, f1_load_mar,      0, &alto2_cpu_device::f1_load_mar_1);
3105      set_f1(task, f1_task,         &alto2_cpu_device::f1_task_0, 0);
3106      set_f1(task, f1_block,         &alto2_cpu_device::fn_f1_bad_0, &alto2_cpu_device::fn_f1_bad_1);   // not all tasks have the f1_block
3107      set_f1(task, f1_l_lsh_1,      0, 0);         // inlined in execute()
3108      set_f1(task, f1_l_rsh_1,      0, 0);         // inlined in execute()
3109      set_f1(task, f1_l_lcy_8,      0, 0);         // inlined in execute()
3110      set_f1(task, f1_const,         0, 0);
3111      set_f1(task, f1_task_10,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3112      set_f1(task, f1_task_11,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3113      set_f1(task, f1_task_12,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3114      set_f1(task, f1_task_13,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3115      set_f1(task, f1_task_14,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3116      set_f1(task, f1_task_15,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3117      set_f1(task, f1_task_16,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3118      set_f1(task, f1_task_17,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3119
3120      set_f2(task, f2_nop,         0, 0);
3121      set_f2(task, f2_bus_eq_zero,   0, &alto2_cpu_device::f2_bus_eq_zero_1);
3122      set_f2(task, f2_shifter_lt_zero,0, &alto2_cpu_device::f2_shifter_lt_zero_1);
3123      set_f2(task, f2_shifter_eq_zero,0, &alto2_cpu_device::f2_shifter_eq_zero_1);
3124      set_f2(task, f2_bus,         0, &alto2_cpu_device::f2_bus_1);
3125      set_f2(task, f2_alucy,         0, &alto2_cpu_device::f2_alucy_1);
3126      set_f2(task, f2_load_md,      0, &alto2_cpu_device::f2_load_md_1);
3127      set_f2(task, f2_const,         0, 0);
3128      set_f2(task, f2_task_10,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3129      set_f2(task, f2_task_11,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3130      set_f2(task, f2_task_12,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3131      set_f2(task, f2_task_13,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3132      set_f2(task, f2_task_14,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3133      set_f2(task, f2_task_15,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3134      set_f2(task, f2_task_16,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3135      set_f2(task, f2_task_17,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3136   }
3137
3138   init_memory();
3139   init_disk();
3140   init_disp();
3141   init_kbd();
3142   init_mouse();
3143   init_hw();
3144
3145   init_emu(task_emu);
3146   init_ksec(task_ksec);
3147   init_ether(task_ether);
3148   init_mrt(task_mrt);
3149   init_dwt(task_dwt);
3150   init_curt(task_curt);
3151   init_dht(task_dht);
3152   init_dvt(task_dvt);
3153   init_part(task_part);
3154   init_kwd(task_kwd);
3155
3156   m_dsp_time = 0;         // reset the display state machine values
3157   m_dsp_state = 020;
3158
3159   m_task = 0;                  // start with task 0
3160   m_task_wakeup |= 1 << 0;      // set wakeup flag
3161}
3162
3163/** @brief software initiated reset (STARTF) */
3164int alto2_cpu_device::soft_reset()
3165{
3166
3167   for (int task = 0; task < ALTO2_TASKS; task++) {
3168      // every task starts at mpc = task number, in either ROM0 or RAM0
3169      m_task_mpc[task] = (m_ctl2k_u38[task] >> 4) ^ 017;
3170      if (0 == (m_reset_mode & (1 << task)))
3171         m_task_mpc[task] |= ALTO2_UCODE_RAM_BASE;
3172   }
3173   m_next2_task = 0;      // switch to task 0
3174   m_reset_mode = 0xffff;   // all tasks start in ROM0 again
3175
3176   m_dsp_time = 0;         // reset the display state machine values
3177   m_dsp_state = 020;
3178
3179   return m_next_task;      // return next task (?)
3180}
branches/alto2/src/emu/cpu/alto2/alto2cpu.c
r0r26287
1/*****************************************************************************
2 *
3 *   Portable Xerox AltoII CPU core
4 *
5 *   Copyright: Juergen Buchmueller <pullmoll@t-online.de>
6 *
7 *   Licenses: MAME, GPLv2
8 *
9 *****************************************************************************/
10#include "alto2cpu.h"
11#include "a2roms.h"
12
13#define   DEBUG_UCODE_CONST_DATA   0   //!< define to 1 to dump decoded micro code and constants
14
15//**************************************************************************
16//  DEVICE DEFINITIONS
17//**************************************************************************
18
19const device_type ALTO2 = &device_creator<alto2_cpu_device>;
20//**************************************************************************
21//  LIVE DEVICE
22//**************************************************************************
23
24DEVICE_ADDRESS_MAP_START( ucode_map, 32, alto2_cpu_device )
25   AM_RANGE(0,                          ALTO2_UCODE_RAM_BASE - 1)          AM_READ     ( crom_r )
26   AM_RANGE(ALTO2_UCODE_RAM_BASE,       ALTO2_UCODE_SIZE - 1)              AM_READWRITE( cram_r, cram_w )
27ADDRESS_MAP_END
28
29DEVICE_ADDRESS_MAP_START( const_map, 16, alto2_cpu_device )
30   AM_RANGE(0,                          ALTO2_CONST_SIZE - 1)              AM_READ     ( const_r )
31ADDRESS_MAP_END
32
33DEVICE_ADDRESS_MAP_START( iomem_map, 16, alto2_cpu_device )
34   AM_RANGE(0,                          ALTO2_IO_PAGE_BASE - 1)            AM_READWRITE( ioram_r, ioram_w )
35   // page 0376
36   AM_RANGE(0177000,                    0177015)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
37   AM_RANGE(0177016,                    0177016)                           AM_READWRITE( utilout_r, utilout_w )    // UTILOUT register
38   AM_RANGE(0177017,                    0177017)                           AM_READWRITE( noop_r, noop_w )          // unused range
39   AM_RANGE(0177020,                    0177023)                           AM_READWRITE( xbus_r,  xbus_w )         // XBUS[0-3] registers
40   AM_RANGE(0177024,                    0177024)                           AM_READ     ( mear_r )                  // MEAR (memory error address register)
41   AM_RANGE(0177025,                    0177025)                           AM_READWRITE( mesr_r,  mesr_w  )        // MESR (memory error status register)
42   AM_RANGE(0177026,                    0177026)                           AM_READWRITE( mecr_r,  mecr_w  )        // MECR (memory error control register)
43   AM_RANGE(0177027,                    0177027)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
44   AM_RANGE(0177030,                    0177033)                           AM_READ     ( utilin_r )                // UTILIN register
45   AM_RANGE(0177034,                    0177037)                           AM_READ     ( kbd_ad_r )                // KBD_AD[0-3] matrix
46   AM_RANGE(0177040,                    0177057)                           AM_READWRITE( bank_reg_r, bank_reg_w )  // BANK[0-17] registers (4 bit)
47   AM_RANGE(0177060,                    0177077)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
48   AM_RANGE(0177100,                    0177101)                           AM_READWRITE( noop_r, noop_w )          // { Summagraphics tablet X, Y }
49   AM_RANGE(0177102,                    0177137)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
50   AM_RANGE(0177140,                    0177157)                           AM_READWRITE( noop_r, noop_w )          // { Organ keyboard }
51   AM_RANGE(0177160,                    0177177)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
52   AM_RANGE(0177200,                    0177204)                           AM_READWRITE( noop_r, noop_w )          // { PROM programmer }
53   AM_RANGE(0177205,                    0177233)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
54   AM_RANGE(0177234,                    0177237)                           AM_READWRITE( noop_r, noop_w )          // { Experimental cursor control }
55   AM_RANGE(0177240,                    0177257)                           AM_READWRITE( noop_r, noop_w )          // { Alto-II debugger }
56//  AM_RANGE(0177244,                    0177247)                           AM_READWRITE( noop_r, noop_w )          // { Graphics keyboard }
57   AM_RANGE(0177260,                    0177377)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
58   // page 0377
59//   AM_RANGE(0177400,                    0177405)                           AM_READWRITE( noop_r, noop_w )          // { Maxc2 maintenance interface }
60   AM_RANGE(0177400,                    0177400)                           AM_READWRITE( noop_r, noop_w )          // { Alto DLS input }
61   AM_RANGE(0177401,                    0177417)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
62   AM_RANGE(0177420,                    0177420)                           AM_READWRITE( noop_r, noop_w )          // { "" }
63   AM_RANGE(0177421,                    0177437)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
64   AM_RANGE(0177440,                    0177440)                           AM_READWRITE( noop_r, noop_w )          // { "" }
65   AM_RANGE(0177441,                    0177457)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
66   AM_RANGE(0177460,                    0177460)                           AM_READWRITE( noop_r, noop_w )          // { "" }
67   AM_RANGE(0177461,                    0177577)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
68   AM_RANGE(0177600,                    0177677)                           AM_READWRITE( noop_r, noop_w )          // { Alto DLS output }
69   AM_RANGE(0177700,                    0177700)                           AM_READWRITE( noop_r, noop_w )          // { EIA interface output bit }
70   AM_RANGE(0177701,                    0177701)                           AM_READWRITE( noop_r, noop_w )          // { EIA interface input bit }
71   AM_RANGE(0177702,                    0177717)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
72   AM_RANGE(0177720,                    0177737)                           AM_READWRITE( noop_r, noop_w )          // { TV camera interface }
73   AM_RANGE(0177740,                    0177763)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
74   AM_RANGE(0177764,                    0177773)                           AM_READWRITE( noop_r, noop_w )          // { Redactron tape drive }
75   AM_RANGE(0177774,                    0177775)                           AM_READWRITE( noop_r, noop_w )          // UNUSED RANGE
76   AM_RANGE(0177776,                    0177776)                           AM_READWRITE( noop_r, noop_w )          // { Digital-Analog Converter, Joystick }
77   AM_RANGE(0177777,                    0177777)                           AM_READWRITE( noop_r, noop_w )          // { Digital-Analog Converter, Joystick }
78
79   AM_RANGE(0200000,                    0377777)                           AM_READWRITE( ioram_r, ioram_w )
80ADDRESS_MAP_END
81
82//-------------------------------------------------
83//  alto2_cpu_device - constructor
84//-------------------------------------------------
85
86alto2_cpu_device::alto2_cpu_device(const machine_config& mconfig, const char* tag, device_t* owner, UINT32 clock) :
87   cpu_device(mconfig, ALTO2, "Xerox Alto-II", tag, owner, clock, "alto2", __FILE__),
88#if   ALTO2_DEBUG
89   m_log_types(LOG_DISPL),
90   m_log_level(8),
91   m_log_newline(true),
92#endif
93   m_ucode_config("ucode", ENDIANNESS_BIG, 32, 12, -2 ),
94   m_const_config("const", ENDIANNESS_BIG, 16,  8, -1 ),
95   m_iomem_config("iomem", ENDIANNESS_BIG, 16, 17, -1 ),
96   m_ucode_crom(0),
97   m_const_data(0),
98   m_icount(0),
99   m_task_mpc(),
100   m_task_next2(),
101   m_pico_time(),
102   m_task(0),
103   m_next_task(0),
104   m_next2_task(0),
105   m_mpc(0),
106   m_mir(0),
107   m_rsel(0),
108   m_next(0),
109   m_next2(0),
110   m_r(),
111   m_s(),
112   m_bus(0),
113   m_t(0),
114   m_alu(0),
115   m_aluc0(0),
116   m_l(0),
117   m_shifter(0),
118   m_laluc0(0),
119   m_m(0),
120   m_cram_addr(0),
121   m_task_wakeup(0),
122   m_active_callback(),
123   m_reset_mode(0xffff),
124   m_rdram_flag(false),
125   m_wrtram_flag(false),
126   m_s_reg_bank(),
127   m_bank_reg(),
128   m_ether_enable(false),
129   m_ewfct(false),
130   m_dsp_time(0),
131   m_dsp_state(0),
132   m_unload_time(0),
133   m_unload_word(0),
134   m_bitclk_time(0),
135   m_bitclk_index(0),
136   m_ctl2k_u3(0),
137   m_ctl2k_u38(0),
138   m_ctl2k_u76(0),
139   m_cram3k_a37(0),
140   m_madr_a64(0),
141   m_madr_a65(0),
142   m_madr_a90(0),
143   m_madr_a91(0),
144   m_bs(),
145   m_f1(),
146   m_f2(),
147   m_ram_related(),
148   m_cycle(0),
149   m_hw(),
150   m_mouse(),
151   m_drive(),
152   m_dsk(),
153   m_sysclka0(),
154   m_sysclka1(),
155   m_sysclkb0(),
156   m_sysclkb1(),
157   m_dsp(),
158   m_disp_a38(0),
159   m_disp_a63(0),
160   m_disp_a66(0),
161   m_displ_bitmap(0),
162   m_mem(),
163   m_emu(),
164   m_ether_a41(0),
165   m_ether_a42(0),
166   m_ether_a49(0),
167   m_eth()
168{
169   m_is_octal = true;
170}
171
172alto2_cpu_device::~alto2_cpu_device()
173{
174   // call all subdevice's exit code
175   exit_kwd();
176   exit_part();
177   exit_dvt();
178   exit_dht();
179   exit_curt();
180   exit_dwt();
181   exit_mrt();
182   exit_ether();
183   exit_ksec();
184   exit_emu();
185   exit_hw();
186   exit_mouse();
187   exit_kbd();
188   exit_disp();
189   exit_disk();
190   exit_memory();
191}
192
193#if   ALTO2_DEBUG
194// FIXME: define types (sections) and print the section like [emu] [kwd] ...
195// FIXME: use the level to suppress messages if logging is less verbose than level
196void alto2_cpu_device::logprintf(int type, int level, const char* format, ...)
197{
198   static const char* type_name[] = {
199      "[CPU]",
200      "[EMU]",
201      "[T01]",
202      "[T02]",
203      "[T03]",
204      "[KSEC]",
205      "[T05]",
206      "[T06]",
207      "[ETH]",
208      "[MRT]",
209      "[DWT]",
210      "[CURT]",
211      "[DHT]",
212      "[DVT]",
213      "[PART]",
214      "[KWD]",
215      "[T17]",
216      "[MEM]",
217      "[RAM]",
218      "[DRIVE]",
219      "[DISK]",
220      "[DISPL]",
221      "[MOUSE]",
222      "[HW]",
223      "[KBD]"
224   };
225   if (!(m_log_types & type))
226      return;
227   if (level > m_log_level)
228      return;
229   if (m_log_newline) {
230      // last line had a \n - print type name
231      for (int i = 0; i < sizeof(type_name)/sizeof(type_name[0]); i++)
232         if (type & (1 << i))
233            logerror("%-7s %11lld ", type_name[i], cycle());
234   }
235   va_list ap;
236   va_start(ap, format);
237   vlogerror(format, ap);
238   va_end(ap);
239   m_log_newline = format[strlen(format) - 1] == '\n';
240}
241#endif
242
243//-------------------------------------------------
244// driver interface to set diablo_hd_device
245//-------------------------------------------------
246
247void alto2_cpu_device::set_diablo(int unit, diablo_hd_device* ptr)
248{
249   m_drive[unit] = ptr;
250}
251
252//-------------------------------------------------
253//  device_rom_region - device-specific (P)ROMs
254//-------------------------------------------------
255
256ROM_START( alto2_cpu )
257   ROM_REGION( 16 * 02000, "ucode_proms", 0 )
258   ROM_LOAD( "55x.3",     0*02000, 0x400, CRC(de870d75) SHA1(2b98cc769d8302cb39948711424d987d94e4159b) )   //!< 00000-01777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
259   ROM_LOAD( "64x.3",     1*02000, 0x400, CRC(51b444c0) SHA1(8756e51f7f3253a55d75886465beb7ee1be6e1c4) )   //!< 00000-01777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
260   ROM_LOAD( "65x.3",     2*02000, 0x400, CRC(741d1437) SHA1(01f7cf07c2173ac93799b2475180bfbbe7e0149b) )   //!< 00000-01777 ALUF(3)',BS(0)',BS(1)',BS(2)'
261   ROM_LOAD( "63x.3",     3*02000, 0x400, CRC(f22d5028) SHA1(c65a42baef702d4aff2d9ad8e363daec27de6801) )   //!< 00000-01777 F1(0),F1(1)',F1(2)',F1(3)'
262   ROM_LOAD( "53x.3",     4*02000, 0x400, CRC(3c89a740) SHA1(95d812d489b2bde03884b2f126f961caa6c8ec45) )   //!< 00000-01777 F2(0),F2(1)',F2(2)',F2(3)'
263   ROM_LOAD( "60x.3",     5*02000, 0x400, CRC(a35de0bf) SHA1(7fa4aead44dcf5393bbfd1706c0ada24aa6fd3ac) )   //!< 00000-01777 LOADT',LOADL,NEXT(0)',NEXT(1)'
264   ROM_LOAD( "61x.3",     6*02000, 0x400, CRC(f25bcb2d) SHA1(acb57f3104a8dc4ba750dd1bf22ccc81cce9f084) )   //!< 00000-01777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
265   ROM_LOAD( "62x.3",     7*02000, 0x400, CRC(1b20a63f) SHA1(41dc86438e91c12b0fe42ffcce6b2ac2eb9e714a) )   //!< 00000-01777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
266
267   // extended memory Mesa 5.1 micro code PROMs, 8 x 4bit
268   ROM_LOAD( "xm51.u54",  8*02000, 02000, CRC(11086ae9) SHA1(c394e3fadbfb91801ddc1a70cb25dc6f606c4f76) )   //!< 00000-01777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
269   ROM_LOAD( "xm51.u74",  9*02000, 02000, CRC(be8224f2) SHA1(ea9abcc3832b26a094319796901237e1e3f238b6) )   //!< 00000-01777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
270   ROM_LOAD( "xm51.u75", 10*02000, 02000, CRC(dfe3e3ac) SHA1(246fd29f92150a5d5d7627fbb4f2504c7b6cd5ec) )   //!< 00000-01777 ALUF(3)',BS(0)',BS(1)',BS(2)'
271   ROM_LOAD( "xm51.u73", 11*02000, 02000, CRC(6c20fa46) SHA1(a054330c65048011f12209aaed5c6da73d95f029) )   //!< 00000-01777 F1(0),F1(1)',F1(2)',F1(3)'
272   ROM_LOAD( "xm51.u52", 12*02000, 02000, CRC(0a31eec8) SHA1(4e2ad5daa5e6a6f2143ee4de00c7b625d096fb02) )   //!< 00000-01777 F2(0),F2(1)',F2(2)',F2(3)'
273   ROM_LOAD( "xm51.u70", 13*02000, 02000, CRC(5c64ee54) SHA1(0eb16d1b5e5967be7c1bf8c8ef6efdf0518a752c) )   //!< 00000-01777 LOADT',LOADL,NEXT(0)',NEXT(1)'
274   ROM_LOAD( "xm51.u71", 14*02000, 02000, CRC(7283bf71) SHA1(819fdcc407ed0acdd8f12b02db6efbcab7bec19a) )   //!< 00000-01777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
275   ROM_LOAD( "xm51.u72", 15*02000, 02000, CRC(a28e5251) SHA1(44dd8ad4ad56541b5394d30ce3521b4d1d561394) )   //!< 00000-01777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
276
277   // constant PROMs, 4 x 4bit
278   // UINT16 src = BITS(addr, 3,2,1,4,5,6,7,0);
279   ROM_REGION( 4 * 0400, "const_proms", 0 )
280   ROM_LOAD( "madr.a6",   0*00400, 00400, CRC(c2c196b2) SHA1(8b2a599ac839ec2a070dbfef2f1626e645c858ca) )   //!< 0000-0377 C(00)',C(01)',C(02)',C(03)'
281   ROM_LOAD( "madr.a5",   1*00400, 00400, CRC(42336101) SHA1(c77819cf40f063af3abf66ea43f17cc1a62e928b) )   //!< 0000-0377 C(04)',C(05)',C(06)',C(07)'
282   ROM_LOAD( "madr.a4",   2*00400, 00400, CRC(b957e490) SHA1(c72660ad3ada4ca0ed8697c6bb6275a4fe703184) )   //!< 0000-0377 C(08)',C(09)',C(10)',C(11)'
283   ROM_LOAD( "madr.a3",   3*00400, 00400, CRC(e0992757) SHA1(5c45ea824970663cb9ee672dc50861539c860249) )   //!< 0000-0377 C(12)',C(13)',C(14)',C(15)'
284
285   // extended memory Mesa 4.1 (?) micro code PROMs, 8 x 4bit (unused)
286   ROM_REGION( 8 * 02000, "xm_mesa_4.1", 0 )
287   ROM_LOAD( "xm654.41",  0*02000, 02000, CRC(beace302) SHA1(0002fea03a0261f57365095c4b87385d833f7063) )   //!< 00000-01777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
288   ROM_LOAD( "xm674.41",  1*02000, 02000, CRC(7db5c097) SHA1(364bc41951baa3ad274031bd49abec1cf5b7a980) )   //!< 00000-01777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
289   ROM_LOAD( "xm675.41",  2*02000, 02000, CRC(26eac1e7) SHA1(9220a1386afae8de96bdb2cf084afbadeeb61d42) )   //!< 00000-01777 ALUF(3)',BS(0)',BS(1)',BS(2)'
290   ROM_LOAD( "xm673.41",  3*02000, 02000, CRC(8173d7e3) SHA1(7fbacf6dccb60dfe9cef88a248c3a1660efddcf4) )   //!< 00000-01777 F1(0),F1(1)',F1(2)',F1(3)'
291   ROM_LOAD( "xm652.41",  4*02000, 02000, CRC(ddfa94bb) SHA1(38625e269400aaf38cd07b5dbf36c0087a0f1b92) )   //!< 00000-01777 F2(0),F2(1)',F2(2)',F2(3)'
292   ROM_LOAD( "xm670.41",  5*02000, 02000, CRC(1cd187f3) SHA1(0fd5eff7c6b5c2383aa20148a795b80286554675) )   //!< 00000-01777 LOADT',LOADL,NEXT(0)',NEXT(1)'
293   ROM_LOAD( "xm671.41",  6*02000, 02000, CRC(f21b1ad7) SHA1(1e18bdb35de7802892ac373c128f900786d40886) )   //!< 00000-01777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
294   ROM_LOAD( "xm672.41",  7*02000, 02000, CRC(110ee075) SHA1(bb72fceba5ce9e5e8c8a0024915006bdd011a3f3) )   //!< 00000-01777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
295
296   ROM_REGION( 0400, "2kctl_u3", 0 )
297   ROM_LOAD( "2kctl.u3",   00000, 00400, CRC(5f8d89e8) SHA1(487cd944ab074290aea73425e81ef4900d92e250) )   //!< 3601-1 256x4 BPROM; Emulator address modifier
298
299   ROM_REGION( 0400, "2kctl_u38", 0 )
300   ROM_LOAD( "2kctl.u38",  00000, 00040, CRC(fc51b1d1) SHA1(e36c2a12a5da377394264899b5ae504e2ffda46e) )   //!< 82S23 32x8 BPROM; task priority and initial address
301
302   ROM_REGION( 0400, "2kctl_u76", 0 )
303   ROM_LOAD( "2kctl.u76",  00000, 00400, CRC(1edef867) SHA1(928b8a15ac515a99109f32672441832173883b81) )   //!< 3601-1 256x4 BPROM; 2KCTL replacement for u51 (1KCTL)
304
305   ROM_REGION( 0040, "alu_a10", 0 )
306   ROM_LOAD( "alu.a10",    00000, 00040, CRC(e0857892) SHA1(dcd389767139f0acc1f87cf074459115abc5b90b) )
307
308   ROM_REGION( 0400, "3kcram_a37", 0 )
309   ROM_LOAD( "3kcram.a37", 00000, 00400, CRC(9417360d) SHA1(bfcdbc56ee4ffafd0f2f672c0c869a55d6dd194b) )
310
311   ROM_REGION( 0400, "madr_a32", 0 )
312   ROM_LOAD( "madr.a32",   00000, 00400, CRC(a0e3b4a7) SHA1(24e50afdeb637a6a8588f8d3a3493c9188b8da2c) )   //! P3601 256x4 BPROM; mouse motion signals MX1, MX2, MY1, MY2
313
314   ROM_REGION( 0400, "madr_a64", 0 )
315   ROM_LOAD( "madr.a64",   00000, 00400, CRC(a66b0eda) SHA1(4d9088f592caa3299e90966b17765be74e523144) )   //! P3601 256x4 BPROM; memory addressing
316
317   ROM_REGION( 0400, "madr_a65", 0 )
318   ROM_LOAD( "madr.a65",   00000, 00400, CRC(ba37febd) SHA1(82e9db1cb65f451755295f0d179e6f8fe3349d4d) )   //! P3601 256x4 BPROM; memory addressing
319
320   ROM_REGION( 0400, "madr_a90", 0 )
321   ROM_LOAD( "madr.a90",   00000, 00400, CRC(7a2d8799) SHA1(c3760dba147740729d33b9b88e59088a4cc7437a) )
322
323   ROM_REGION( 0400, "madr_a91", 0 )
324   ROM_LOAD( "madr.a91",   00000, 00400, CRC(dd556aeb) SHA1(900f333a091e3ccde0843019c25f25fba62e6023) )
325
326   ROM_REGION( 0400, "displ_a38", 0 )
327   ROM_LOAD( "displ.a38",  00000, 00400, CRC(fd30beb7) SHA1(65e4a19ba4ff748d525122128c514abedd55d866) )   //!< P3601 256x4 BPROM; display FIFO control: STOPWAKE, MBEMPTY
328
329   ROM_REGION( 0040, "displ_a63", 0 )
330   ROM_LOAD( "displ.a63",  00000, 00040, CRC(82a20d60) SHA1(39d90703568be5419ada950e112d99227873fdea) )   //!< 82S23 32x8 BPROM; display HBLANK, HSYNC, SCANEND, HLCGATE ...
331
332   ROM_REGION( 0400, "displ_a66", 0 )
333   ROM_LOAD( "displ.a66",  00000, 00400, CRC(9f91aad9) SHA1(69b1d4c71f4e18103112e8601850c2654e9265cf) )   //!< P3601 256x4 BPROM; display VSYNC and VBLANK
334
335   ROM_REGION( 0400, "ether_a41", 0 )
336   ROM_LOAD( "enet.a41",   00000, 00400, CRC(d5de8d86) SHA1(c134a4c898c73863124361a9b0218f7a7f00082a) )
337
338   ROM_REGION( 0400, "ether_a42", 0 )
339   ROM_LOAD( "enet.a42",   00000, 00400, CRC(9d5c81bd) SHA1(ac7e63332a3dad0bef7cd0349b24e156a96a4bf0) )
340
341   ROM_REGION( 0400, "ether_a49", 0 )
342   ROM_LOAD( "enet.a49",   00000, 00400, CRC(4d2dcdb2) SHA1(583327a7d70cd02702c941c0e43c1e9408ff7fd0) )
343ROM_END
344
345const rom_entry *alto2_cpu_device::device_rom_region() const
346{
347   return ROM_NAME( alto2_cpu );
348}
349
350//-------------------------------------------------
351// device_memory_interface overrides
352//-------------------------------------------------
353
354const address_space_config*alto2_cpu_device::memory_space_config(address_spacenum spacenum) const
355{
356   if (AS_0 == spacenum)
357      return &m_ucode_config;
358   if (AS_1 == spacenum)
359      return &m_const_config;
360   if (AS_2 == spacenum)
361      return &m_iomem_config;
362   return NULL;
363}
364
365/**
366 * @brief list of microcode PROM loading options
367 */
368static const prom_load_t pl_ucode[] = {
369   {   // 0000-01777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
370      "55x.3",
371      0,
372      "de870d75",
373      "2b98cc769d8302cb39948711424d987d94e4159b",
374/* size */   ALTO2_UCODE_PAGE_SIZE,
375/* amap */   AMAP_DEFAULT,
376/* axor */   ALTO2_UCODE_PAGE_MASK,
377/* dxor */   017,                  // invert D0-D3
378/* width */   4,
379/* shift */   28,
380/* dmap */   DMAP_DEFAULT,
381/* dand */   ZERO,
382/* type */   sizeof(UINT32)
383   },
384   {   // 0000-01777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
385      "64x.3",
386      0,
387      "51b444c0",
388      "8756e51f7f3253a55d75886465beb7ee1be6e1c4",
389/* size */   ALTO2_UCODE_PAGE_SIZE,
390/* amap */   AMAP_DEFAULT,
391/* axor */   ALTO2_UCODE_PAGE_MASK,
392/* dxor */   017,                  // invert D0-D3
393/* width */   4,
394/* shift */   24,
395/* dmap */   DMAP_DEFAULT,
396/* dand */   KEEP,
397/* type */   sizeof(UINT32)
398   },
399   {   // 0000-01777 ALUF(3)',BS(0)',BS(1)',BS(2)'
400      "65x.3",
401      0,
402      "741d1437",
403      "01f7cf07c2173ac93799b2475180bfbbe7e0149b",
404/* size */   ALTO2_UCODE_PAGE_SIZE,
405/* amap */   AMAP_DEFAULT,
406/* axor */   ALTO2_UCODE_PAGE_MASK,
407/* dxor */   017,                  // invert D0-D3
408/* width */   4,
409/* shift */   20,
410/* dmap */   DMAP_DEFAULT,
411/* dand */   KEEP,
412/* type */   sizeof(UINT32)
413   },
414   {   // 0000-01777 F1(0),F1(1)',F1(2)',F1(3)'
415      "63x.3",
416      0,
417      "f22d5028",
418      "c65a42baef702d4aff2d9ad8e363daec27de6801",
419/* size */   ALTO2_UCODE_PAGE_SIZE,
420/* amap */   AMAP_DEFAULT,
421/* axor */   ALTO2_UCODE_PAGE_MASK,
422/* dxor */   007,                  // keep D0, invert D1-D3
423/* width */   4,
424/* shift */   16,
425/* dmap */   DMAP_DEFAULT,
426/* dand */   KEEP,
427/* type */   sizeof(UINT32)
428   },
429   {   // 0000-01777 F2(0),F2(1)',F2(2)',F2(3)'
430      "53x.3",
431      0,
432      "3c89a740",
433      "95d812d489b2bde03884b2f126f961caa6c8ec45",
434/* size */   ALTO2_UCODE_PAGE_SIZE,
435/* amap */   AMAP_DEFAULT,
436/* axor */   ALTO2_UCODE_PAGE_MASK,
437/* dxor */   007,                  // keep D0, invert D1-D3
438/* width */   4,
439/* shift */   12,
440/* dmap */   DMAP_DEFAULT,
441/* dand */   KEEP,
442/* type */   sizeof(UINT32)
443   },
444   {   // 0000-01777 LOADT',LOADL,NEXT(0)',NEXT(1)'
445      "60x.3",
446      0,
447      "a35de0bf",
448      "7fa4aead44dcf5393bbfd1706c0ada24aa6fd3ac",
449/* size */   ALTO2_UCODE_PAGE_SIZE,
450/* amap */   AMAP_DEFAULT,
451/* axor */   ALTO2_UCODE_PAGE_MASK,
452/* dxor */   013,                  // invert D0 and D2-D3
453/* width */   4,
454/* shift */   8,
455/* dmap */   DMAP_DEFAULT,
456/* dand */   KEEP,
457/* type */   sizeof(UINT32)
458   },
459   {   // 0000-01777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
460      "61x.3",
461      0,
462      "f25bcb2d",
463      "acb57f3104a8dc4ba750dd1bf22ccc81cce9f084",
464/* size */   ALTO2_UCODE_PAGE_SIZE,
465/* amap */   AMAP_DEFAULT,
466/* axor */   ALTO2_UCODE_PAGE_MASK,
467/* dxor */   017,                  // invert D0-D3
468/* width */   4,
469/* shift */   4,
470/* dmap */   DMAP_DEFAULT,
471/* dand */   KEEP,
472/* type */   sizeof(UINT32)
473   },
474   {   // 0000-01777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
475      "62x.3",
476      0,
477      "1b20a63f",
478      "41dc86438e91c12b0fe42ffcce6b2ac2eb9e714a",
479/* size */   ALTO2_UCODE_PAGE_SIZE,
480/* amap */   AMAP_DEFAULT,
481/* axor */   ALTO2_UCODE_PAGE_MASK,
482/* dxor */   017,                  // invert D0-D3
483/* width */   4,
484/* shift */   0,
485/* dmap */   DMAP_DEFAULT,
486/* dand */   KEEP,
487/* type */   sizeof(UINT32)
488   }
489
490#if   (ALTO2_UCODE_ROM_PAGES > 1)
491   ,
492   {   // 02000-03777 RSEL(0)',RSEL(1)',RSEL(2)',RSEL(3)'
493      "xm51.u54",
494      0,
495      "11086ae9",
496      "c394e3fadbfb91801ddc1a70cb25dc6f606c4f76",
497/* size */   ALTO2_UCODE_PAGE_SIZE,
498/* amap */   AMAP_DEFAULT,
499/* axor */   ALTO2_UCODE_PAGE_MASK,
500/* dxor */   017,                  // invert D0-D3
501/* width */   4,
502/* shift */   28,
503/* dmap */   DMAP_DEFAULT,
504/* dand */   ZERO,
505/* type */   sizeof(UINT32)
506   },
507   {   // 02000-03777 RSEL(4)',ALUF(0)',ALUF(1)',ALUF(2)'
508      "xm51.u74",
509      0,
510      "be8224f2",
511      "ea9abcc3832b26a094319796901237e1e3f238b6",
512/* size */   ALTO2_UCODE_PAGE_SIZE,
513/* amap */   AMAP_DEFAULT,
514/* axor */   ALTO2_UCODE_PAGE_MASK,
515/* dxor */   017,                  // invert D0-D3
516/* width */   4,
517/* shift */   24,
518/* dmap */   DMAP_DEFAULT,
519/* dand */   KEEP,
520/* type */   sizeof(UINT32)
521   },
522   {   // 02000-03777 ALUF(3)',BS(0)',BS(1)',BS(2)'
523      "xm51.u75",
524      0,
525      "dfe3e3ac",
526      "246fd29f92150a5d5d7627fbb4f2504c7b6cd5ec",
527/* size */   ALTO2_UCODE_PAGE_SIZE,
528/* amap */   AMAP_DEFAULT,
529/* axor */   ALTO2_UCODE_PAGE_MASK,
530/* dxor */   017,                  // invert D0-D3
531/* width */   4,
532/* shift */   20,
533/* dmap */   DMAP_DEFAULT,
534/* dand */   KEEP,
535/* type */   sizeof(UINT32)
536   },
537   {   // 02000-03777 F1(0),F1(1)',F1(2)',F1(3)'
538      "xm51.u73",
539      0,
540      "6c20fa46",
541      "a054330c65048011f12209aaed5c6da73d95f029",
542/* size */   ALTO2_UCODE_PAGE_SIZE,
543/* amap */   AMAP_DEFAULT,
544/* axor */   ALTO2_UCODE_PAGE_MASK,
545/* dxor */   007,                  // keep D0, invert D1-D3
546/* width */   4,
547/* shift */   16,
548/* dmap */   DMAP_DEFAULT,
549/* dand */   KEEP,
550/* type */   sizeof(UINT32)
551   },
552   {   // 02000-03777 F2(0),F2(1)',F2(2)',F2(3)'
553      "xm51.u52",
554      0,
555      "0a31eec8",
556      "4e2ad5daa5e6a6f2143ee4de00c7b625d096fb02",
557/* size */   ALTO2_UCODE_PAGE_SIZE,
558/* amap */   AMAP_DEFAULT,
559/* axor */   ALTO2_UCODE_PAGE_MASK,
560/* dxor */   007,                  // keep D0, invert D1-D3
561/* width */   4,
562/* shift */   12,
563/* dmap */   DMAP_DEFAULT,
564/* dand */   KEEP,
565/* type */   sizeof(UINT32)
566   },
567   {   // 02000-03777 LOADT',LOADL,NEXT(0)',NEXT(1)'
568      "xm51.u70",
569      0,
570      "5c64ee54",
571      "0eb16d1b5e5967be7c1bf8c8ef6efdf0518a752c",
572/* size */   ALTO2_UCODE_PAGE_SIZE,
573/* amap */   AMAP_DEFAULT,
574/* axor */   ALTO2_UCODE_PAGE_MASK,
575/* dxor */   013,                  // invert D0 and D2-D3
576/* width */   4,
577/* shift */   8,
578/* dmap */   DMAP_DEFAULT,
579/* dand */   KEEP,
580/* type */   sizeof(UINT32)
581   },
582   {   // 02000-03777 NEXT(2)',NEXT(3)',NEXT(4)',NEXT(5)'
583      "xm51.u71",
584      0,
585      "7283bf71",
586      "819fdcc407ed0acdd8f12b02db6efbcab7bec19a",
587/* size */   ALTO2_UCODE_PAGE_SIZE,
588/* amap */   AMAP_DEFAULT,
589/* axor */   ALTO2_UCODE_PAGE_MASK,
590/* dxor */   017,                  // invert D0-D3
591/* width */   4,
592/* shift */   4,
593/* dmap */   DMAP_DEFAULT,
594/* dand */   KEEP,
595/* type */   sizeof(UINT32)
596   },
597   {   // 02000-03777 NEXT(6)',NEXT(7)',NEXT(8)',NEXT(9)'
598      "xm51.u72",
599      0,
600      "a28e5251",
601      "44dd8ad4ad56541b5394d30ce3521b4d1d561394",
602/* size */   ALTO2_UCODE_PAGE_SIZE,
603/* amap */   AMAP_DEFAULT,
604/* axor */   ALTO2_UCODE_PAGE_MASK,
605/* dxor */   017,                  // invert D0-D3
606/* width */   4,
607/* shift */   0,
608/* dmap */   DMAP_DEFAULT,
609/* dand */   KEEP,
610/* type */   sizeof(UINT32)
611    }
612#endif   // (UCODE_ROM_PAGES > 1)
613};
614
615/**
616 * @brief list of constant PROM loading options
617 */
618static const prom_load_t pl_const[] = {
619   {   // constant prom D0-D3
620      "madr.a6",
621      "c3.3",
622      "c2c196b2",
623      "8b2a599ac839ec2a070dbfef2f1626e645c858ca",
624/* size */   ALTO2_CONST_SIZE,
625/* amap */   AMAP_CONST_PROM,         // descramble constant address
626/* axor */   0,
627/* dxor */   017,                  // invert D0-D3
628/* width */   4,
629/* shift */   0,
630/* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
631/* dand */   ZERO,
632/* type */   sizeof(UINT16)
633   },
634   {   // constant prom D4-D7
635      "madr.a5",
636      "c2.3",
637      "42336101",
638      "c77819cf40f063af3abf66ea43f17cc1a62e928b",
639/* size */   ALTO2_CONST_SIZE,
640/* amap */   AMAP_CONST_PROM,         // descramble constant address
641/* axor */   0,
642/* dxor */   017,                  // invert D0-D3
643/* width */   4,
644/* shift */   4,
645/* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
646/* dand */   KEEP,
647/* type */   sizeof(UINT16)
648   },
649   {   // constant prom D8-D11
650      "madr.a4",
651      "c1.3",
652      "b957e490",
653      "c72660ad3ada4ca0ed8697c6bb6275a4fe703184",
654/* size */   ALTO2_CONST_SIZE,
655/* amap */   AMAP_CONST_PROM,         // descramble constant address
656/* axor */   0,
657/* dxor */   017,                  // invert D0-D3
658/* width */   4,
659/* shift */   8,
660/* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
661/* dand */   KEEP,
662/* type */   sizeof(UINT16)
663   },
664   {   // constant PROM D12-D15
665      "madr.a3",
666      "c0.3",
667      "e0992757",
668      "5c45ea824970663cb9ee672dc50861539c860249",
669/* size */   ALTO2_CONST_SIZE,
670/* amap */   AMAP_CONST_PROM,         // descramble constant address
671/* axor */   0,
672/* dxor */   017,                  // invert D0-D3
673/* width */   4,
674/* shift */   12,
675/* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
676/* dand */   KEEP,
677/* type */   sizeof(UINT16)
678   }
679};
680
681//! 82S23 32x8 BPROM; display HBLANK, HSYNC, SCANEND, HLCGATE ...
682static const prom_load_t pl_displ_a63 =
683{
684   "displ.a63",
685   0,
686   "82a20d60",
687   "39d90703568be5419ada950e112d99227873fdea",
688   /* size */   0040,
689   /* amap */   AMAP_DEFAULT,
690   /* axor */   0,
691   /* dxor */   0,
692   /* width */   8,
693   /* shift */   0,
694   /* dmap */   DMAP_DEFAULT,
695   /* dand */   ZERO,
696   /* type */   sizeof(UINT8)
697};
698
699//! P3601 256x4 BPROM; display FIFO control: STOPWAKE, MBEMPTY
700static const prom_load_t pl_displ_a38 =
701{
702   "displ.a38",
703   0,
704   "fd30beb7",
705   "65e4a19ba4ff748d525122128c514abedd55d866",
706   /* size */   0400,
707   /* amap */   AMAP_REVERSE_0_7,         // reverse address lines A0-A7
708   /* axor */   0,
709   /* dxor */   0,
710   /* width */   4,
711   /* shift */   0,
712   /* dmap */   DMAP_DEFAULT,
713   /* dand */   ZERO,
714   /* type */   sizeof(UINT8)
715};
716
717//! P3601 256x4 BPROM; display VSYNC and VBLANK
718static const prom_load_t pl_displ_a66 =
719{
720   "displ.a66",
721   0,
722   "9f91aad9",
723   "69b1d4c71f4e18103112e8601850c2654e9265cf",
724   /* size */   0400,
725   /* amap */   AMAP_DEFAULT,
726   /* axor */   0,
727   /* dxor */   0,
728   /* width */   4,
729   /* shift */   0,
730   /* dmap */   DMAP_DEFAULT,
731   /* dand */   ZERO,
732   /* type */   sizeof(UINT8)
733};
734
735//! 3601-1 256x4 BPROM; Emulator address modifier
736static const prom_load_t pl_2kctl_u3 =
737{
738   "2kctl.u3",
739   0,
740   "5f8d89e8",
741   "487cd944ab074290aea73425e81ef4900d92e250",
742   /* size */   0400,
743   /* amap */   AMAP_REVERSE_0_7,         // reverse address lines A0-A7
744   /* axor */   0377,                  // invert address lines A0-A7
745   /* dxor */   017,                  // invert data lines D0-D3
746   /* width */   4,
747   /* shift */   0,
748   /* dmap */   DMAP_DEFAULT,
749   /* dand */   ZERO,
750   /* type */   sizeof(UINT8)
751};
752
753//! 82S23 32x8 BPROM; task priority and initial address
754static const prom_load_t pl_2kctl_u38 =
755{
756   "2kctl.u38",
757   0,
758   "fc51b1d1",
759   "e36c2a12a5da377394264899b5ae504e2ffda46e",
760   /* size */   0040,
761   /* amap */   AMAP_DEFAULT,
762   /* axor */   0,
763   /* dxor */   0,
764   /* width */   8,
765   /* shift */   0,
766   /* dmap */   DMAP_DEFAULT,
767   /* dand */   ZERO,
768   /* type */   sizeof(UINT8)
769};
770
771//! 3601-1 256x4 BPROM; 2KCTL replacement for u51 (1KCTL)
772static const prom_load_t pl_2kctl_u76 =
773{
774   "2kctl.u76",
775   0,
776   "1edef867",
777   "928b8a15ac515a99109f32672441832173883b81",
778   /* size */   0400,
779   /* amap */   AMAP_DEFAULT,
780   /* axor */   0077,                  // invert address lines A0-A5
781   /* dxor */   0,
782   /* width */   4,
783   /* shift */   0,
784   /* dmap */   DMAP_DEFAULT,
785   /* dand */   ZERO,
786   /* type */   sizeof(UINT8)
787};
788
789//! ALUF to ALU 741818 functions and carry in mapper
790static const prom_load_t pl_alu_a10 =
791{
792   "alu.a10",
793   0,
794   "e0857892",
795   "dcd389767139f0acc1f87cf074459115abc5b90b",
796   /* size */   0040,
797   /* amap */   AMAP_DEFAULT,
798   /* axor */   0,
799   /* dxor */   0372,                  // invert D7-D3 and D1
800   /* width */   8,
801   /* shift */   0,
802   /* dmap */   DMAP_DEFAULT,
803   /* dand */   ZERO,
804   /* type */   sizeof(UINT8)
805};
806
807static const prom_load_t pl_3kcram_a37 =
808{
809   "3kcram.a37",
810   0,
811   "9417360d",
812   "bfcdbc56ee4ffafd0f2f672c0c869a55d6dd194b",
813   /* size */   0400,
814   /* amap */   AMAP_DEFAULT,
815   /* axor */   0,
816   /* dxor */   017,                  // invert D0-D3
817   /* width */   4,
818   /* shift */   0,
819   /* dmap */   DMAP_DEFAULT,
820   /* dand */   ZERO,
821   /* type */   sizeof(UINT8)
822};
823
824static const prom_load_t pl_madr_a32 =
825{
826   "madr.a32",
827   0,
828   "a0e3b4a7",
829   "24e50afdeb637a6a8588f8d3a3493c9188b8da2c",
830   /* size */   0400,
831   /* amap */   AMAP_DEFAULT,
832   /* axor */   0,
833   /* dxor */   017,                  // invert D0-D3
834   /* width */   4,
835   /* shift */   0,
836   /* dmap */   DMAP_REVERSE_0_3,         // reverse D0-D3 to D3-D0
837   /* dand */   ZERO,
838   /* type */   sizeof(UINT8)
839};
840
841static const prom_load_t pl_madr_a64 =
842{
843   "madr.a64",
844   0,
845   "a66b0eda",
846   "4d9088f592caa3299e90966b17765be74e523144",
847   /* size */   0400,
848   /* amap */   AMAP_DEFAULT,
849   /* axor */   0,
850   /* dxor */   017,                  // invert D0-D3
851   /* width */   4,
852   /* shift */   0,
853   /* dmap */   DMAP_DEFAULT,
854   /* dand */   ZERO,
855   /* type */   sizeof(UINT8)
856};
857
858static const prom_load_t pl_madr_a65 =
859{
860   "madr.a65",
861   0,
862   "ba37febd",
863   "82e9db1cb65f451755295f0d179e6f8fe3349d4d",
864   /* size */   0400,
865   /* amap */   AMAP_DEFAULT,
866   /* axor */   0,
867   /* dxor */   017,                  // invert D0-D3
868   /* width */   4,
869   /* shift */   0,
870   /* dmap */   DMAP_DEFAULT,
871   /* dand */   ZERO,
872   /* type */   sizeof(UINT8)
873};
874
875static const prom_load_t pl_madr_a90 =
876{
877   "madr.a90",
878   0,
879   "7a2d8799",
880   "c3760dba147740729d33b9b88e59088a4cc7437a",
881   /* size */   0400,
882   /* amap */   AMAP_DEFAULT,
883   /* axor */   0,
884   /* dxor */   017,                  // invert D0-D3
885   /* width */   4,
886   /* shift */   0,
887   /* dmap */   DMAP_DEFAULT,
888   /* dand */   ZERO,
889   /* type */   sizeof(UINT8)
890};
891
892static const prom_load_t pl_madr_a91 =
893{
894   "madr.a91",
895   0,
896   "dd556aeb",
897   "900f333a091e3ccde0843019c25f25fba62e6023",
898   /* size */   0400,
899   /* amap */   AMAP_DEFAULT,
900   /* axor */   0,
901   /* dxor */   017,                  // invert D0-D3
902   /* width */   4,
903   /* shift */   0,
904   /* dmap */   DMAP_DEFAULT,
905   /* dand */   ZERO,
906   /* type */   sizeof(UINT8)
907};
908
909static const prom_load_t pl_enet_a41 =
910{   /* P3601 256x4 BPROM; Ethernet phase encoder 1 "PE1" */
911   "enet.a41",
912   0,
913   "d5de8d86",
914   "c134a4c898c73863124361a9b0218f7a7f00082a",
915   /* size */   0400,
916   /* amap */   AMAP_DEFAULT,
917   /* axor */   0,
918   /* dxor */   0,
919   /* width */   4,
920   /* shift */   0,
921   /* dmap */   DMAP_DEFAULT,
922   /* dand */   ZERO,
923   /* type */   sizeof(UINT8)
924};
925
926static const prom_load_t pl_enet_a42 =
927{   /* P3601 256x4 BPROM; Ethernet phase encoder 2 "PE2" */
928   "enet.a42",
929   0,
930   "9d5c81bd",
931   "ac7e63332a3dad0bef7cd0349b24e156a96a4bf0",
932   /* size */   0400,
933   /* amap */   AMAP_DEFAULT,
934   /* axor */   0,
935   /* dxor */   0,
936   /* width */   4,
937   /* shift */   0,
938   /* dmap */   DMAP_DEFAULT,
939   /* dand */   ZERO,
940   /* type */   sizeof(UINT8)
941};
942
943static const prom_load_t pl_enet_a49 =
944{   /* P3601 256x4 BPROM; Ethernet FIFO control "AFIFO" */
945   "enet.a49",
946   0,
947   "4d2dcdb2",
948   "583327a7d70cd02702c941c0e43c1e9408ff7fd0",
949   /* size */   0400,
950   /* amap */   AMAP_REVERSE_0_7,            // reverse address lines A0-A7
951   /* axor */   0,
952   /* dxor */   0,
953   /* width */   4,
954   /* shift */   0,
955   /* dmap */   DMAP_DEFAULT,
956   /* dand */   ZERO,
957   /* type */   sizeof(UINT8)
958};
959
960//-------------------------------------------------
961//  device_start - device-specific startup
962//-------------------------------------------------
963
964// FIXME
965void alto2_cpu_device::device_start()
966{
967   // get a pointer to the IO address space
968   m_iomem = &space(AS_2);
969
970   // decode micro code PROMs to CROM
971   m_ucode_crom = prom_load(machine(), pl_ucode, memregion("ucode_proms")->base(), ALTO2_UCODE_ROM_PAGES, 8);
972
973   // allocate micro code CRAM
974   m_ucode_cram = auto_alloc_array(machine(), UINT8, sizeof(UINT32) * ALTO2_UCODE_RAM_PAGES * ALTO2_UCODE_PAGE_SIZE);
975   // fill with inverted bits value
976   for (offs_t offset = 0; offset < ALTO2_UCODE_RAM_PAGES * ALTO2_UCODE_PAGE_SIZE; offset++)
977      *reinterpret_cast<UINT32 *>(m_ucode_cram + offset * 4) = ALTO2_UCODE_INVERTED;
978
979   // decode constant PROMs to const data
980   m_const_data = prom_load(machine(), pl_const, memregion("const_proms")->base(), 1, 4);
981
982   m_disp_a38 = prom_load(machine(), &pl_displ_a38, memregion("displ_a38")->base());
983   m_disp_a63 = prom_load(machine(), &pl_displ_a63, memregion("displ_a63")->base());
984   m_disp_a66 = prom_load(machine(), &pl_displ_a66, memregion("displ_a66")->base());
985   m_ctl2k_u3 = prom_load(machine(), &pl_2kctl_u3, memregion("2kctl_u3")->base());
986   m_ctl2k_u38 = prom_load(machine(), &pl_2kctl_u38, memregion("2kctl_u38")->base());
987   m_ctl2k_u76 = prom_load(machine(), &pl_2kctl_u76, memregion("2kctl_u76")->base());
988   m_alu_a10 = prom_load(machine(), &pl_alu_a10, memregion("alu_a10")->base());
989   m_cram3k_a37 = prom_load(machine(), &pl_3kcram_a37, memregion("3kcram_a37")->base());
990   m_madr_a32 = prom_load(machine(), &pl_madr_a32, memregion("madr_a32")->base());
991   m_madr_a64 = prom_load(machine(), &pl_madr_a64, memregion("madr_a64")->base());
992   m_madr_a65 = prom_load(machine(), &pl_madr_a65, memregion("madr_a65")->base());
993   m_madr_a90 = prom_load(machine(), &pl_madr_a90, memregion("madr_a90")->base());
994   m_madr_a91 = prom_load(machine(), &pl_madr_a91, memregion("madr_a91")->base());
995   m_ether_a41 = prom_load(machine(), &pl_enet_a41, memregion("ether_a41")->base());
996   m_ether_a42 = prom_load(machine(), &pl_enet_a42, memregion("ether_a42")->base());
997   m_ether_a49 = prom_load(machine(), &pl_enet_a49, memregion("ether_a49")->base());
998
999#if   0   // dump ALU a10 PROM after loading
1000   for (UINT8 i = 0; i < 32; i++) {
1001      UINT8 a = m_alu_a10[i];
1002      printf("%03o: S3-S0:%u%u%u%u M:%u CI:%u T:%u ?:%u\n",
1003            i, (a >> 7) & 1, (a >> 6) & 1, (a >> 5) & 1, (a >> 4) & 1,
1004            (a >> 3) & 1, (a >> 2) & 1, (a >> 1) & 1, (a >> 0) & 1);
1005   }
1006#endif
1007   save_item(NAME(m_task_mpc));
1008   save_item(NAME(m_task_next2));
1009   save_item(NAME(m_pico_time));
1010   save_item(NAME(m_task));
1011   save_item(NAME(m_next_task));
1012   save_item(NAME(m_next2_task));
1013   save_item(NAME(m_mpc));
1014   save_item(NAME(m_mir));
1015   save_item(NAME(m_rsel));
1016   save_item(NAME(m_next));
1017   save_item(NAME(m_next2));
1018   save_item(NAME(m_r));
1019   save_item(NAME(m_s));
1020   save_item(NAME(m_bus));
1021   save_item(NAME(m_t));
1022   save_item(NAME(m_alu));
1023   save_item(NAME(m_aluc0));
1024   save_item(NAME(m_l));
1025   save_item(NAME(m_shifter));
1026   save_item(NAME(m_laluc0));
1027   save_item(NAME(m_m));
1028   save_item(NAME(m_cram_addr));
1029   save_item(NAME(m_task_wakeup));
1030   save_item(NAME(m_reset_mode));
1031   save_item(NAME(m_rdram_flag));
1032   save_item(NAME(m_wrtram_flag));
1033   save_item(NAME(m_s_reg_bank));
1034   save_item(NAME(m_bank_reg));
1035   save_item(NAME(m_ether_enable));
1036   save_item(NAME(m_ewfct));
1037   save_item(NAME(m_dsp_time));
1038   save_item(NAME(m_dsp_state));
1039   save_item(NAME(m_unload_time));
1040   save_item(NAME(m_unload_word));
1041#if   (USE_BITCLK_TIMER == 0)
1042   save_item(NAME(m_bitclk_time));
1043   save_item(NAME(m_bitclk_index));
1044#endif
1045   save_item(NAME(m_mouse.x));
1046   save_item(NAME(m_mouse.y));
1047   save_item(NAME(m_mouse.dx));
1048   save_item(NAME(m_mouse.dy));
1049   save_item(NAME(m_mouse.latch));
1050   save_item(NAME(m_dsk.drive));
1051   save_item(NAME(m_dsk.kaddr));
1052   save_item(NAME(m_dsk.kadr));
1053   save_item(NAME(m_dsk.kstat));
1054   save_item(NAME(m_dsk.kcom));
1055   save_item(NAME(m_dsk.krecno));
1056   save_item(NAME(m_dsk.shiftin));
1057   save_item(NAME(m_dsk.shiftout));
1058   save_item(NAME(m_dsk.datain));
1059   save_item(NAME(m_dsk.dataout));
1060   save_item(NAME(m_dsk.krwc));
1061   save_item(NAME(m_dsk.kfer));
1062   save_item(NAME(m_dsk.wdtskena));
1063   save_item(NAME(m_dsk.wdinit0));
1064   save_item(NAME(m_dsk.wdinit));
1065   save_item(NAME(m_dsk.strobe));
1066   save_item(NAME(m_dsk.bitclk));
1067   save_item(NAME(m_dsk.datin));
1068   save_item(NAME(m_dsk.bitcount));
1069   save_item(NAME(m_dsk.carry));
1070   save_item(NAME(m_dsk.seclate));
1071   save_item(NAME(m_dsk.seekok));
1072   save_item(NAME(m_dsk.ok_to_run));
1073   save_item(NAME(m_dsk.ready_mf31a));
1074   save_item(NAME(m_dsk.seclate_mf31b));
1075#if   0
1076   save_item(NAME(m_dsk.ff_21a));
1077   save_item(NAME(m_dsk.ff_21a_old));
1078   save_item(NAME(m_dsk.ff_21b));
1079   save_item(NAME(m_dsk.ff_22a));
1080   save_item(NAME(m_dsk.ff_22b));
1081   save_item(NAME(m_dsk.ff_43b));
1082   save_item(NAME(m_dsk.ff_53a));
1083   save_item(NAME(m_dsk.ff_43a));
1084   save_item(NAME(m_dsk.ff_53b));
1085   save_item(NAME(m_dsk.ff_44a));
1086   save_item(NAME(m_dsk.ff_44b));
1087   save_item(NAME(m_dsk.ff_45a));
1088   save_item(NAME(m_dsk.ff_45b));
1089#endif
1090   save_item(NAME(m_dsp.hlc));
1091   save_item(NAME(m_dsp.a63));
1092   save_item(NAME(m_dsp.a66));
1093   save_item(NAME(m_dsp.setmode));
1094   save_item(NAME(m_dsp.inverse));
1095   save_item(NAME(m_dsp.halfclock));
1096   save_item(NAME(m_dsp.clr));
1097   save_item(NAME(m_dsp.fifo));
1098   save_item(NAME(m_dsp.fifo_wr));
1099   save_item(NAME(m_dsp.fifo_rd));
1100   save_item(NAME(m_dsp.dht_blocks));
1101   save_item(NAME(m_dsp.dwt_blocks));
1102   save_item(NAME(m_dsp.curt_blocks));
1103   save_item(NAME(m_dsp.curt_wakeup));
1104   save_item(NAME(m_dsp.vblank));
1105   save_item(NAME(m_dsp.xpreg));
1106   save_item(NAME(m_dsp.csr));
1107   save_item(NAME(m_dsp.curword));
1108   save_item(NAME(m_dsp.curdata));
1109   save_item(NAME(m_mem.mar));
1110   save_item(NAME(m_mem.rmdd));
1111   save_item(NAME(m_mem.wmdd));
1112   save_item(NAME(m_mem.md));
1113   save_item(NAME(m_mem.cycle));
1114   save_item(NAME(m_mem.access));
1115   save_item(NAME(m_mem.error));
1116   save_item(NAME(m_mem.mear));
1117   save_item(NAME(m_mem.mecr));
1118   save_item(NAME(m_emu.ir));
1119   save_item(NAME(m_emu.skip));
1120   save_item(NAME(m_emu.cy));
1121   save_item(NAME(m_eth.fifo));
1122   save_item(NAME(m_eth.fifo_rd));
1123   save_item(NAME(m_eth.fifo_wr));
1124   save_item(NAME(m_eth.status));
1125   save_item(NAME(m_eth.rx_crc));
1126   save_item(NAME(m_eth.tx_crc));
1127   save_item(NAME(m_eth.rx_count));
1128   save_item(NAME(m_eth.tx_count));
1129   save_item(NAME(m_eth.duckbreath));
1130
1131   state_add( A2_DRIVE,   "DRIVE",   m_dsk.drive).formatstr("%1u");
1132   state_add( A2_KADDR,   "KADDR",   m_dsk.kaddr).formatstr("%06O");
1133   state_add( A2_KADR,    "KADR",    m_dsk.kadr).formatstr("%06O");
1134   state_add( A2_KSTAT,   "KSTAT",   m_dsk.kstat).formatstr("%06O");
1135   state_add( A2_KCOM,    "KCOM",    m_dsk.kcom).formatstr("%06O");
1136   state_add( A2_KRECNO,  "KRECNO",  m_dsk.krecno).formatstr("%02O");
1137   state_add( A2_SHIFTIN, "SHIFTIN", m_dsk.shiftin).formatstr("%06O");
1138   state_add( A2_SHIFTOUT,"SHIFTOUT",m_dsk.shiftout).formatstr("%06O");
1139   state_add( A2_DATAIN,  "DATAIN",  m_dsk.datain).formatstr("%06O");
1140   state_add( A2_DATAOUT, "DATAOUT", m_dsk.dataout).formatstr("%06O");
1141   state_add( A2_KRWC,    "KRWC",    m_dsk.krwc).formatstr("%1u");
1142   state_add( A2_KFER,    "KFER",    m_dsk.kfer).formatstr("%1u");
1143   state_add( A2_WDTSKENA,"WDTSKENA",m_dsk.wdtskena).formatstr("%1u");
1144   state_add( A2_WDINIT0, "WDINIT0", m_dsk.wdinit0).formatstr("%1u");
1145   state_add( A2_WDINIT,  "WDINIT",  m_dsk.wdinit).formatstr("%1u");
1146   state_add( A2_STROBE,  "STROBE",  m_dsk.strobe).formatstr("%1u");
1147   state_add( A2_BITCLK,  "BITCLK",  m_dsk.bitclk).formatstr("%1u");
1148   state_add( A2_DATIN,   "DATIN",   m_dsk.datin).formatstr("%06O");
1149   state_add( A2_BITCNT,  "BITCNT",  m_dsk.bitcount).formatstr("%02O");
1150   state_add( A2_CARRY,   "CARRY",   m_dsk.carry).formatstr("%1u");
1151   state_add( A2_SECLATE, "SECLATE", m_dsk.seclate).formatstr("%1u");
1152   state_add( A2_SEEKOK,  "SEEKOK",  m_dsk.seekok).formatstr("%1u");
1153   state_add( A2_OKTORUN, "OKTORUN", m_dsk.ok_to_run).formatstr("%1u");
1154   state_add( A2_READY,   "READY",   m_dsk.kstat).formatstr("%1u");
1155   state_add_divider(-1);
1156   state_add( A2_TASK,    "TASK",    m_task).formatstr("%03O");
1157   state_add( A2_MPC,     "MPC",     m_mpc).formatstr("%06O");
1158   state_add( A2_NEXT,    "NEXT",    m_next).formatstr("%06O");
1159   state_add( A2_NEXT2,   "NEXT2",   m_next2).formatstr("%06O");
1160   state_add( A2_BUS,     "BUS",     m_bus).formatstr("%06O");
1161   state_add( A2_T,       "T",       m_t).formatstr("%06O");
1162   state_add( A2_ALU,     "ALU",     m_alu).formatstr("%06O");
1163   state_add( A2_ALUC0,   "ALUC0",   m_aluc0).formatstr("%1u");
1164   state_add( A2_L,       "L",       m_l).formatstr("%06O");
1165   state_add( A2_SHIFTER, "SHIFTER", m_shifter).formatstr("%06O");
1166   state_add( A2_LALUC0,  "LALUC0",  m_laluc0).formatstr("%1u");
1167   state_add( A2_M,       "M",       m_m).formatstr("%06O");
1168   state_add_divider(-1);
1169   state_add( A2_AC3,     "AC(3)",   m_r[000]).formatstr("%06O");
1170   state_add( A2_AC2,     "AC(2)",   m_r[001]).formatstr("%06O");
1171   state_add( A2_AC1,     "AC(1)",   m_r[002]).formatstr("%06O");
1172   state_add( A2_AC0,     "AC(0)",   m_r[003]).formatstr("%06O");
1173   state_add( A2_R04,     "R04",     m_r[004]).formatstr("%06O");
1174   state_add( A2_R05,     "R05",     m_r[005]).formatstr("%06O");
1175   state_add( A2_PC,      "PC",      m_r[006]).formatstr("%06O");
1176   state_add( A2_R07,     "R07",     m_r[007]).formatstr("%06O");
1177   state_add( A2_R10,     "R10",     m_r[010]).formatstr("%06O");
1178   state_add( A2_R11,     "R11",     m_r[011]).formatstr("%06O");
1179   state_add( A2_R12,     "R12",     m_r[012]).formatstr("%06O");
1180   state_add( A2_R13,     "R13",     m_r[013]).formatstr("%06O");
1181   state_add( A2_R14,     "R14",     m_r[014]).formatstr("%06O");
1182   state_add( A2_R15,     "R15",     m_r[015]).formatstr("%06O");
1183   state_add( A2_R16,     "R16",     m_r[016]).formatstr("%06O");
1184   state_add( A2_R17,     "R17",     m_r[017]).formatstr("%06O");
1185   state_add( A2_R20,     "R20",     m_r[020]).formatstr("%06O");
1186   state_add( A2_R21,     "R21",     m_r[021]).formatstr("%06O");
1187   state_add( A2_R22,     "R22",     m_r[022]).formatstr("%06O");
1188   state_add( A2_R23,     "R23",     m_r[023]).formatstr("%06O");
1189   state_add( A2_R24,     "R24",     m_r[024]).formatstr("%06O");
1190   state_add( A2_R25,     "R25",     m_r[025]).formatstr("%06O");
1191   state_add( A2_R26,     "R26",     m_r[026]).formatstr("%06O");
1192   state_add( A2_R27,     "R27",     m_r[027]).formatstr("%06O");
1193   state_add( A2_R30,     "R30",     m_r[030]).formatstr("%06O");
1194   state_add( A2_R31,     "R31",     m_r[031]).formatstr("%06O");
1195   state_add( A2_R32,     "R32",     m_r[032]).formatstr("%06O");
1196   state_add( A2_R33,     "R33",     m_r[033]).formatstr("%06O");
1197   state_add( A2_R34,     "R34",     m_r[034]).formatstr("%06O");
1198   state_add( A2_R35,     "R35",     m_r[035]).formatstr("%06O");
1199   state_add( A2_R36,     "R36",     m_r[036]).formatstr("%06O");
1200   state_add( A2_R37,     "R37",     m_r[037]).formatstr("%06O");
1201   state_add_divider(-1);
1202   state_add( A2_S00,     "S00",     m_s[0][000]).formatstr("%06O");
1203   state_add( A2_S01,     "S01",     m_s[0][001]).formatstr("%06O");
1204   state_add( A2_S02,     "S02",     m_s[0][002]).formatstr("%06O");
1205   state_add( A2_S03,     "S03",     m_s[0][003]).formatstr("%06O");
1206   state_add( A2_S04,     "S04",     m_s[0][004]).formatstr("%06O");
1207   state_add( A2_S05,     "S05",     m_s[0][005]).formatstr("%06O");
1208   state_add( A2_S06,     "S06",     m_s[0][006]).formatstr("%06O");
1209   state_add( A2_S07,     "S07",     m_s[0][007]).formatstr("%06O");
1210   state_add( A2_S10,     "S10",     m_s[0][010]).formatstr("%06O");
1211   state_add( A2_S11,     "S11",     m_s[0][011]).formatstr("%06O");
1212   state_add( A2_S12,     "S12",     m_s[0][012]).formatstr("%06O");
1213   state_add( A2_S13,     "S13",     m_s[0][013]).formatstr("%06O");
1214   state_add( A2_S14,     "S14",     m_s[0][014]).formatstr("%06O");
1215   state_add( A2_S15,     "S15",     m_s[0][015]).formatstr("%06O");
1216   state_add( A2_S16,     "S16",     m_s[0][016]).formatstr("%06O");
1217   state_add( A2_S17,     "S17",     m_s[0][017]).formatstr("%06O");
1218   state_add( A2_S20,     "S20",     m_s[0][020]).formatstr("%06O");
1219   state_add( A2_S21,     "S21",     m_s[0][021]).formatstr("%06O");
1220   state_add( A2_S22,     "S22",     m_s[0][022]).formatstr("%06O");
1221   state_add( A2_S23,     "S23",     m_s[0][023]).formatstr("%06O");
1222   state_add( A2_S24,     "S24",     m_s[0][024]).formatstr("%06O");
1223   state_add( A2_S25,     "S25",     m_s[0][025]).formatstr("%06O");
1224   state_add( A2_S26,     "S26",     m_s[0][026]).formatstr("%06O");
1225   state_add( A2_S27,     "S27",     m_s[0][027]).formatstr("%06O");
1226   state_add( A2_S30,     "S30",     m_s[0][030]).formatstr("%06O");
1227   state_add( A2_S31,     "S31",     m_s[0][031]).formatstr("%06O");
1228   state_add( A2_S32,     "S32",     m_s[0][032]).formatstr("%06O");
1229   state_add( A2_S33,     "S33",     m_s[0][033]).formatstr("%06O");
1230   state_add( A2_S34,     "S34",     m_s[0][034]).formatstr("%06O");
1231   state_add( A2_S35,     "S35",     m_s[0][035]).formatstr("%06O");
1232   state_add( A2_S36,     "S36",     m_s[0][036]).formatstr("%06O");
1233   state_add( A2_S37,     "S37",     m_s[0][037]).formatstr("%06O");
1234
1235   state_add(STATE_GENPC, "curpc", m_mpc).formatstr("%03X").noshow();
1236   state_add(STATE_GENFLAGS, "GENFLAGS", m_aluc0).formatstr("%5s").noshow();
1237
1238   m_icountptr = &m_icount;
1239
1240   hard_reset();
1241}
1242
1243//! read microcode CROM
1244READ32_MEMBER ( alto2_cpu_device::crom_r )
1245{
1246   return *reinterpret_cast<UINT32 *>(m_ucode_crom + offset * 4);
1247}
1248
1249//! read microcode CRAM
1250READ32_MEMBER ( alto2_cpu_device::cram_r )
1251{
1252   return *reinterpret_cast<UINT32 *>(m_ucode_cram + offset * 4);
1253}
1254
1255//! write microcode CRAM
1256WRITE32_MEMBER( alto2_cpu_device::cram_w )
1257{
1258   *reinterpret_cast<UINT32 *>(m_ucode_cram + offset * 4) = data;
1259}
1260
1261//! direct read access to the microcode CROM
1262#define   RD_CROM(addr) (*reinterpret_cast<UINT32 *>(m_ucode_crom + addr * 4))
1263//! direct read access to the microcode CRAM
1264#define   RD_CRAM(addr) (*reinterpret_cast<UINT32 *>(m_ucode_cram + addr * 4))
1265//! direct write access to the microcode CRAM
1266#define   WR_CRAM(addr,data) do { \
1267   *reinterpret_cast<UINT32 *>(m_ucode_cram + addr * 4) = data; \
1268} while (0)
1269
1270//! read constants PROM
1271READ16_MEMBER ( alto2_cpu_device::const_r )
1272{
1273   return *reinterpret_cast<UINT16 *>(m_const_data + offset * 2);
1274}
1275
1276#define   PUT_EVEN(dword,word)         A2_PUT32(dword,32, 0,15,word)
1277#define   GET_EVEN(dword)               A2_GET32(dword,32, 0,15)
1278#define   PUT_ODD(dword,word)            A2_PUT32(dword,32,16,31,word)
1279#define   GET_ODD(dword)               A2_GET32(dword,32,16,31)
1280
1281//! read i/o space RAM
1282READ16_MEMBER ( alto2_cpu_device::ioram_r )
1283{
1284   offs_t dword_addr = offset / 2;
1285   return static_cast<UINT16>(offset & 1 ? GET_ODD(m_mem.ram[dword_addr]) : GET_EVEN(m_mem.ram[dword_addr]));
1286}
1287
1288//! write i/o space RAM
1289WRITE16_MEMBER( alto2_cpu_device::ioram_w )
1290{
1291   offs_t dword_addr = offset / 2;
1292   if (offset & 1)
1293      PUT_ODD(m_mem.ram[dword_addr], data);
1294   else
1295      PUT_EVEN(m_mem.ram[dword_addr], data);
1296}
1297
1298//-------------------------------------------------
1299//  device_reset - device-specific reset
1300//-------------------------------------------------
1301
1302// FIXME
1303void alto2_cpu_device::device_reset()
1304{
1305    soft_reset();
1306}
1307
1308/**
1309 * @brief callback is called by the drive timer whenever a new sector starts
1310 *
1311 * @param unit the unit number
1312 */
1313static void disk_sector_start(void* cookie, int unit)
1314{
1315   alto2_cpu_device* cpu = reinterpret_cast<alto2_cpu_device *>(cookie);
1316   cpu->next_sector(unit);
1317}
1318
1319void alto2_cpu_device::interface_post_reset()
1320{
1321
1322   // set the disk unit sector callbacks
1323   for (int unit = 0; unit < diablo_hd_device::DIABLO_UNIT_MAX; unit++) {
1324      diablo_hd_device* dhd = m_drive[unit];
1325      dhd->set_sector_callback(this, &disk_sector_start);
1326   }
1327}
1328
1329//-------------------------------------------------
1330//  execute_set_input - act on a changed input/
1331//  interrupt line
1332//-------------------------------------------------
1333
1334// FIXME
1335void alto2_cpu_device::execute_set_input(int inputnum, int state)
1336{
1337}
1338
1339//-------------------------------------------------
1340//  state_string_export - export state as a string
1341//  for the debugger
1342//-------------------------------------------------
1343
1344void alto2_cpu_device::state_string_export(const device_state_entry &entry, astring &string)
1345{
1346   switch (entry.index())
1347   {
1348   case STATE_GENFLAGS:
1349      string.printf("%s%s%s%s",
1350                 m_aluc0 ? "C":"-",
1351                 m_laluc0 ? "c":"-",
1352                 m_shifter == 0 ? "0":"-",
1353                 static_cast<INT16>(m_shifter) < 0 ? "<":"-");
1354      break;
1355   }
1356}
1357
1358void alto2_cpu_device::fatal(int exitcode, const char *format, ...)
1359{
1360   va_list ap;
1361   va_start(ap, format);
1362   emu_fatalerror error(exitcode, format, ap);
1363   va_end(ap);
1364}
1365
1366/** @brief task names */
1367const char* alto2_cpu_device::task_name(int task)
1368{
1369   switch (task) {
1370   case 000: return "emu";
1371   case 001: return "task01";
1372   case 002: return "task02";
1373   case 003: return "task03";
1374   case 004: return "ksec";
1375   case 005: return "task05";
1376   case 006: return "task06";
1377   case 007: return "ether";
1378   case 010: return "mrt";
1379   case 011: return "dwt";
1380   case 012: return "curt";
1381   case 013: return "dht";
1382   case 014: return "dvt";
1383   case 015: return "part";
1384   case 016: return "kwd";
1385   case 017: return "task17";
1386   }
1387   return "???";
1388}
1389
1390/** @brief register names (as used by the microcode) */
1391const char* alto2_cpu_device::r_name(UINT8 reg)
1392{
1393   switch (reg) {
1394   case 000: return "ac(3)";
1395   case 001: return "ac(2)";
1396   case 002: return "ac(1)";
1397   case 003: return "ac(0)";
1398   case 004: return "nww";
1399   case 005: return "r05";
1400   case 006: return "pc";
1401   case 007: return "r07";
1402   case 010: return "xh";
1403   case 011: return "r11";
1404   case 012: return "ecntr";
1405   case 013: return "epntr";
1406   case 014: return "r14";
1407   case 015: return "r15";
1408   case 016: return "r16";
1409   case 017: return "r17";
1410   case 020: return "curx";
1411   case 021: return "curdata";
1412   case 022: return "cba";
1413   case 023: return "aecl";
1414   case 024: return "slc";
1415   case 025: return "mtemp";
1416   case 026: return "htab";
1417   case 027: return "ypos";
1418   case 030: return "dwa";
1419   case 031: return "kwdctw";
1420   case 032: return "cksumrw";
1421   case 033: return "knmarw";
1422   case 034: return "dcbr";
1423   case 035: return "dwax";
1424   case 036: return "mask";
1425   case 037: return "r37";
1426   }
1427   return "???";
1428}
1429
1430/** @brief ALU function names */
1431const char* alto2_cpu_device::aluf_name(UINT8 aluf)
1432{
1433   switch (aluf) {
1434   case 000: return "bus";
1435   case 001: return "t";
1436   case 002: return "bus or t";
1437   case 003: return "bus and t";
1438   case 004: return "bus xor t";
1439   case 005: return "bus + 1";
1440   case 006: return "bus - 1";
1441   case 007: return "bus + t";
1442   case 010: return "bus - t";
1443   case 011: return "bus - t - 1";
1444   case 012: return "bus + t + 1";
1445   case 013: return "bus + skip";
1446   case 014: return "bus, t";
1447   case 015: return "bus and not t";
1448   case 016: return "0 (undef)";
1449   case 017: return "0 (undef)";
1450   }
1451   return "???";
1452}
1453
1454/** @brief BUS source names */
1455const char* alto2_cpu_device::bs_name(UINT8 bs)
1456{
1457   switch (bs) {
1458   case 000: return "read_r";
1459   case 001: return "load_r";
1460   case 002: return "no_source";
1461   case 003: return "task_3";
1462   case 004: return "task_4";
1463   case 005: return "read_md";
1464   case 006: return "mouse";
1465   case 007: return "disp";
1466   }
1467   return "???";
1468}
1469
1470/** @brief F1 function names */
1471const char* alto2_cpu_device::f1_name(UINT8 f1)
1472{
1473   switch (f1) {
1474   case 000: return "nop";
1475   case 001: return "load_mar";
1476   case 002: return "task";
1477   case 003: return "block";
1478   case 004: return "l_lsh_1";
1479   case 005: return "l_rsh_1";
1480   case 006: return "l_lcy_8";
1481   case 007: return "const";
1482   case 010: return "task_10";
1483   case 011: return "task_11";
1484   case 012: return "task_12";
1485   case 013: return "task_13";
1486   case 014: return "task_14";
1487   case 015: return "task_15";
1488   case 016: return "task_16";
1489   case 017: return "task_17";
1490   }
1491   return "???";
1492}
1493
1494/** @brief F2 function names */
1495const char* alto2_cpu_device::f2_name(UINT8 f2)
1496{
1497   switch (f2) {
1498   case 000: return "nop";
1499   case 001: return "bus=0";
1500   case 002: return "shifter<0";
1501   case 003: return "shifter=0";
1502   case 004: return "bus";
1503   case 005: return "alucy";
1504   case 006: return "load_md";
1505   case 007: return "const";
1506   case 010: return "task_10";
1507   case 011: return "task_11";
1508   case 012: return "task_12";
1509   case 013: return "task_13";
1510   case 014: return "task_14";
1511   case 015: return "task_15";
1512   case 016: return "task_16";
1513   case 017: return "task_17";
1514   }
1515   return "???";
1516}
1517
1518#if   ALTO2_DEBUG
1519void alto2_cpu_device::watch_read(UINT32 addr, UINT32 data)
1520{
1521   LOG((LOG_MEM,0,"mem: rd[%06o] = %06o\n", addr, data));
1522}
1523
1524void alto2_cpu_device::watch_write(UINT32 addr, UINT32 data)
1525{
1526   LOG((LOG_MEM,0,"mem: wr[%06o] = %06o\n", addr, data));
1527}
1528#endif
1529
1530/** @brief fatal exit on unitialized dynamic phase BUS source */
1531void alto2_cpu_device::fn_bs_bad_0()
1532{
1533   fatal(9,"fatal: bad early bus source pointer for task %s, mpc:%05o bs:%s\n",
1534      task_name(m_task), m_mpc, bs_name(MIR_BS(m_mir)));
1535}
1536
1537/** @brief fatal exit on unitialized latching phase BUS source */
1538void alto2_cpu_device::fn_bs_bad_1()
1539{
1540   fatal(9,"fatal: bad late bus source pointer for task %s, mpc:%05o bs: %s\n",
1541      task_name(m_task), m_mpc, bs_name(MIR_BS(m_mir)));
1542}
1543
1544/** @brief fatal exit on unitialized dynamic phase F1 function */
1545void alto2_cpu_device::fn_f1_bad_0()
1546{
1547   fatal(9,"fatal: bad early f1 function pointer for task %s, mpc:%05o f1: %s\n",
1548      task_name(m_task), m_mpc, f1_name(MIR_F1(m_mir)));
1549}
1550
1551/** @brief fatal exit on unitialized latching phase F1 function */
1552void alto2_cpu_device::fn_f1_bad_1()
1553{
1554   fatal(9,"fatal: bad late f1 function pointer for task %s, mpc:%05o f1: %s\n",
1555      task_name(m_task), m_mpc, f1_name(MIR_F1(m_mir)));
1556}
1557
1558/** @brief fatal exit on unitialized dynamic phase F2 function */
1559void alto2_cpu_device::fn_f2_bad_0()
1560{
1561   fatal(9,"fatal: bad early f2 function pointer for task %s, mpc:%05o f2: %s\n",
1562      task_name(m_task), m_mpc, f2_name(MIR_F2(m_mir)));
1563}
1564
1565/** @brief fatal exit on unitialized latching phase F2 function */
1566void alto2_cpu_device::fn_f2_bad_1()
1567{
1568   fatal(9,"fatal: bad late f2 function pointer for task %s, mpc:%05o f2: %s\n",
1569        task_name(m_task), m_mpc, f2_name(MIR_F2(m_mir)));
1570}
1571
1572#if   ALTO2_DEBUG
1573typedef struct {
1574   UINT16 first, last;
1575   const char* name;
1576}   memory_range_name_t;
1577
1578memory_range_name_t memory_range_name_table[] = {
1579   {0177016, 0177017,   "UTILOUT    Printer output (Std. Hardware)"},
1580   {0177020, 0177023,   "XBUS       Utility input bus (Alto II Std. Hardware)"},
1581   {0177024, 0177024,   "MEAR       Memory Error Address Register (Alto II Std. Hardware)"},
1582   {0177025, 0177025,   "MESR       Memory error status register (Alto II Std. Hardware)"},
1583   {0177026, 0177026,   "MECR       Memory error control register (Alto II Std. Hardware)"},
1584   {0177030, 0177033,   "UTILIN     Printer status, mouse, keyset (all 4 locations return same thing)"},
1585   {0177034, 0177037,   "KBDAD      Undecoded keyboard (Std. Hardware)"},
1586   {0177740, 0177757,   "BANKREGS   Extended memory option bank registers"},
1587   {0177100, 0177100,   "-          Sumagraphics tablet X"},
1588   {0177101, 0177101,   "-          Sumagraphics tablet Y"},
1589   {0177140, 0177157,   "-          Organ keyboard"},
1590   {0177200, 0177204,   "-          PROM programmer"},
1591   {0177234, 0177237,   "-          Experimental ursor control"},
1592   {0177240, 0177257,   "-          Alto II debugger"},
1593   {0177244, 0177247,   "-          Graphics keyboard"},
1594   {0177400, 0177405,   "-          Maxc2 maintenance interface"},
1595   {0177400, 0177400,   "-          Alto DLS input (0)"},
1596   {0177420, 0177420,   "-          Alto DLS input (1)"},
1597   {0177440, 0177440,   "-          Alto DLS input (2)"},
1598   {0177460, 0177460,   "-          Alto DLS input (3)"},
1599   {0177600, 0177677,   "-          Alto DLS output"},
1600   {0177700, 0177700,   "-          EIA interface output bit"},
1601   {0177701, 0177701,   "EIALOC     EIA interface input bit"},
1602   {0177720, 0177737,   "-          TV Camera Interface"},
1603   {0177764, 0177773,   "-          Redactron tape drive"},
1604   {0177776, 0177776,   "-          Digital-Analog Converter, Joystick"},
1605   {0177777, 0177777,   "-          Digital-Analog Converter, Joystick"}
1606};
1607
1608static const char* memory_range_name(offs_t offset)
1609{
1610   int _min = 0;
1611   int _max = sizeof(memory_range_name_table) / sizeof(memory_range_name_table[0]) - 1;
1612   int _mid;
1613
1614   offset %= ALTO2_IO_PAGE_SIZE;
1615   offset += ALTO2_IO_PAGE_BASE;
1616
1617   /* binary search in table of memory ranges */
1618   while (_max >= _min)
1619   {
1620      _mid = (_min + _max) / 2;
1621      if (memory_range_name_table[_mid].last < offset)
1622         _min = _mid + 1;
1623      else if (memory_range_name_table[_mid].first > offset)
1624         _max = _mid - 1;
1625      else if (memory_range_name_table[_mid].first <= offset &&
1626             memory_range_name_table[_mid].last >= offset)
1627         return memory_range_name_table[_mid].name;
1628   }
1629   return "-          UNUSED";
1630}
1631
1632#endif
1633
1634/**
1635 * @brief read the open bus for unused MMIO range
1636 */
1637READ16_MEMBER( alto2_cpu_device::noop_r )
1638{
1639   LOG((LOG_CPU,0,"   MMIO rd %s\n", memory_range_name(offset)));
1640   return 0177777;
1641}
1642
1643/**
1644 * @brief write nowhere for unused MMIO range
1645 */
1646WRITE16_MEMBER( alto2_cpu_device::noop_w )
1647{
1648    LOG((LOG_CPU,0,"   MMIO wr %s\n", memory_range_name(offset)));
1649}
1650
1651/**
1652 * @brief read bank register in memory mapped I/O range
1653 *
1654 * The bank registers are stored in a 16x4-bit RAM 74S189.
1655 */
1656READ16_MEMBER( alto2_cpu_device::bank_reg_r )
1657{
1658   int task = offset & 017;
1659   int bank = m_bank_reg[task] | 0177760;
1660   return bank;
1661}
1662
1663/**
1664 * @brief write bank register in memory mapped I/O range
1665 *
1666 * The bank registers are stored in a 16x4-bit RAM 74S189.
1667 */
1668WRITE16_MEMBER( alto2_cpu_device::bank_reg_w )
1669{
1670   int task = offset & 017;
1671   m_bank_reg[task] = data & 017;
1672   LOG((LOG_CPU,0,"   write bank[%02o]=%#o normal:%o extended:%o (%s)\n",
1673      task, data,
1674      GET_BANK_NORMAL(data),
1675      GET_BANK_EXTENDED(data),
1676      task_name(task)));
1677}
1678
1679/**
1680 * @brief bs_read_r early: drive bus by R register
1681 */
1682void alto2_cpu_device::bs_read_r_0()
1683{
1684   UINT16 r = m_r[m_rsel];
1685   LOG((LOG_CPU,2,"   ←R%02o; %s (%#o)\n", m_rsel, r_name(m_rsel), r));
1686   m_bus &= r;
1687}
1688
1689/**
1690 * @brief bs_load_r early: load R places 0 on the BUS
1691 */
1692void alto2_cpu_device::bs_load_r_0()
1693{
1694   UINT16 r = 0;
1695   LOG((LOG_CPU,2,"   R%02o←; %s (BUS&=0)\n", m_rsel, r_name(m_rsel)));
1696   m_bus &= r;
1697}
1698
1699/**
1700 * @brief bs_load_r late: load R from SHIFTER
1701 */
1702void alto2_cpu_device::bs_load_r_1()
1703{
1704   if (MIR_F2(m_mir) != f2_emu_load_dns) {
1705      m_r[m_rsel] = m_shifter;
1706      LOG((LOG_CPU,2,"   R%02o←; %s = SHIFTER (%#o)\n", m_rsel, r_name(m_rsel), m_shifter));
1707      /* HACK: programs writing r37 with xxx3 make the cursor
1708       * display go nuts. Until I found the real reason for this
1709       * obviously buggy display, I just clear the two
1710       * least significant bits of r37 if they are set at once.
1711       */
1712      if (m_rsel == 037 && ((m_shifter & 3) == 3)) {
1713         printf("writing r37 = %#o\n", m_shifter);
1714         m_r[037] &= ~3;
1715      }
1716   }
1717}
1718
1719/**
1720 * @brief bs_read_md early: drive BUS from read memory data
1721 */
1722void alto2_cpu_device::bs_read_md_0()
1723{
1724#if   ALTO2_DEBUG
1725   UINT32 mar = m_mem.mar;
1726#endif
1727   UINT16 md = read_mem();
1728   LOG((LOG_CPU,2,"   ←MD; BUS&=MD (%#o=[%#o])\n", md, mar));
1729   m_bus &= md;
1730}
1731
1732/**
1733 * @brief bs_mouse early: drive bus by mouse
1734 */
1735void alto2_cpu_device::bs_mouse_0()
1736{
1737   UINT16 r = mouse_read();
1738   LOG((LOG_CPU,2,"   ←MOUSE; BUS&=MOUSE (%#o)\n", r));
1739   m_bus &= r;
1740}
1741
1742/**
1743 * @brief bs_disp early: drive bus by displacement (which?)
1744 */
1745void alto2_cpu_device::bs_disp_0()
1746{
1747   UINT16 r = 0177777;
1748   LOG((LOG_CPU,0,"BS ←DISP not handled by task %s mpc:%04x\n", task_name(m_task), m_mpc));
1749   LOG((LOG_CPU,2,"   ←DISP; BUS&=DISP ?? (%#o)\n", r));
1750   m_bus &= r;
1751}
1752
1753/**
1754 * @brief f1_load_mar late: load memory address register
1755 *
1756 * Load memory address register from the ALU output;
1757 * start main memory reference (see section 2.3).
1758 */
1759void alto2_cpu_device::f1_load_mar_1()
1760{
1761   UINT8 bank = m_bank_reg[m_task];
1762   UINT32 msb;
1763   if (MIR_F2(m_mir) == f2_load_md) {
1764      msb = GET_BANK_EXTENDED(bank) << 16;
1765      LOG((LOG_CPU,7, "   XMAR %#o\n", msb | m_alu));
1766   } else {
1767      msb = GET_BANK_NORMAL(bank) << 16;
1768
1769   }
1770   load_mar(m_rsel, msb | m_alu);
1771}
1772
1773#if   USE_PRIO_F9318
1774/** @brief F9318 input lines */
1775typedef enum {
1776   PRIO_IN_EI = (1<<8),
1777   PRIO_IN_I7 = (1<<7),
1778   PRIO_IN_I6 = (1<<6),
1779   PRIO_IN_I5 = (1<<5),
1780   PRIO_IN_I4 = (1<<4),
1781   PRIO_IN_I3 = (1<<3),
1782   PRIO_IN_I2 = (1<<2),
1783   PRIO_IN_I1 = (1<<1),
1784   PRIO_IN_I0 = (1<<0),
1785   /* masks */
1786   PRIO_I7 = PRIO_IN_I7,
1787   PRIO_I6_I7 = (PRIO_IN_I6 | PRIO_IN_I7),
1788   PRIO_I5_I7 = (PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1789   PRIO_I4_I7 = (PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1790   PRIO_I3_I7 = (PRIO_IN_I3 | PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1791   PRIO_I2_I7 = (PRIO_IN_I2 | PRIO_IN_I3 | PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1792   PRIO_I1_I7 = (PRIO_IN_I1 | PRIO_IN_I2 | PRIO_IN_I3 | PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1793   PRIO_I0_I7 = (PRIO_IN_I0 | PRIO_IN_I1 | PRIO_IN_I2 | PRIO_IN_I3 | PRIO_IN_I4 | PRIO_IN_I5 | PRIO_IN_I6 | PRIO_IN_I7),
1794}   f9318_in_t;
1795
1796/** @brief F9318 output lines */
1797typedef enum {
1798   PRIO_OUT_Q0 = (1<<0),
1799   PRIO_OUT_Q1 = (1<<1),
1800   PRIO_OUT_Q2 = (1<<2),
1801   PRIO_OUT_EO = (1<<3),
1802   PRIO_OUT_GS = (1<<4),
1803   /* masks */
1804   PRIO_OUT_QZ = (PRIO_OUT_Q0 | PRIO_OUT_Q1 | PRIO_OUT_Q2)
1805}   f9318_out_t;
1806
1807/**
1808 * @brief F9318 priority encoder 8 to 3-bit
1809 *
1810 * Emulation of the F9318 chip (pin compatible with 74348).
1811 *
1812 * <PRE>
1813 *            F9318
1814 *         +---+-+---+
1815 *         |   +-+   |         +---------------------------------+----------------+
1816 *    I4' -|1      16|-  Vcc   |              input              |     output     |
1817 *         |         |         +---------------------------------+----------------+
1818 *    I5' -|2      15|-  EO'   |      EI I0 I1 I2 I3 I4 I5 I6 I7 | GS Q0 Q1 Q2 EO |
1819 *         |         |         +---------------------------------+----------------+
1820 *    I6' -|3      14|-  GS'   | (a)  H  x  x  x  x  x  x  x  x  | H  H  H  H  H  |
1821 *         |         |         | (b)  L  H  H  H  H  H  H  H  H  | H  H  H  H  L  |
1822 *    I7' -|4      13|-  I3'   +---------------------------------+----------------+
1823 *         |         |         | (c)  L  x  x  x  x  x  x  x  L  | L  L  L  L  H  |
1824 *    EI' -|5      12|-  I2'   | (d)  L  x  x  x  x  x  x  L  H  | L  H  L  L  H  |
1825 *         |         |         | (e)  L  x  x  x  x  x  L  H  H  | L  L  H  L  H  |
1826 *    Q2' -|6      11|-  I1'   | (f)  L  x  x  x  x  L  H  H  H  | L  H  H  L  H  |
1827 *         |         |         | (g)  L  x  x  x  L  H  H  H  H  | L  L  L  H  H  |
1828 *    Q1' -|7      10|-  I0'   | (h)  L  x  x  L  H  H  H  H  H  | L  H  L  H  H  |
1829 *         |         |         | (i)  L  x  L  H  H  H  H  H  H  | L  L  H  H  H  |
1830 *   GND  -|8       9|-  Q0'   | (j)  L  L  H  H  H  H  H  H  H  | L  H  H  H  H  |
1831 *         |         |         +---------------------------------+----------------+
1832 *         +---------+
1833 * </PRE>
1834 */
1835static __inline f9318_out_t f9318(f9318_in_t in)
1836{
1837   f9318_out_t out;
1838
1839   if (in & PRIO_IN_EI) {
1840      out = PRIO_OUT_EO | PRIO_OUT_GS | PRIO_OUT_QZ;
1841      LOG((LOG_CPU,2,"   f9318 case (a) in:%#o out:%#o\n", in, out));
1842      return out;
1843   }
1844
1845   if (0 == (in & PRIO_I7)) {
1846      out = PRIO_OUT_EO;
1847      LOG((LOG_CPU,2,"   f9318 case (c) in:%#o out:%#o\n", in, out));
1848      return out;
1849   }
1850
1851   if (PRIO_I7 == (in & PRIO_I6_I7)) {
1852      out = PRIO_OUT_EO | PRIO_OUT_Q0;
1853      LOG((LOG_CPU,2,"   f9318 case (d) in:%#o out:%#o\n", in, out));
1854      return out;
1855   }
1856
1857   if (PRIO_I6_I7 == (in & PRIO_I5_I7)) {
1858      out = PRIO_OUT_EO | PRIO_OUT_Q1;
1859      LOG((LOG_CPU,2,"   f9318 case (e) in:%#o out:%#o\n", in, out));
1860      return out;
1861   }
1862
1863   if (PRIO_I5_I7 == (in & PRIO_I4_I7)) {
1864      out = PRIO_OUT_EO | PRIO_OUT_Q0 | PRIO_OUT_Q1;
1865      LOG((LOG_CPU,2,"   f9318 case (f) in:%#o out:%#o\n", in, out));
1866      return out;
1867   }
1868
1869   if (PRIO_I4_I7 == (in & PRIO_I3_I7)) {
1870      out = PRIO_OUT_EO | PRIO_OUT_Q2;
1871      LOG((LOG_CPU,2,"   f9318 case (g) in:%#o out:%#o\n", in, out));
1872      return out;
1873   }
1874
1875   if (PRIO_I3_I7 == (in & PRIO_I2_I7)) {
1876      out = PRIO_OUT_EO | PRIO_OUT_Q0 | PRIO_OUT_Q2;
1877      LOG((LOG_CPU,2,"   f9318 case (h) in:%#o out:%#o\n", in, out));
1878      return out;
1879   }
1880
1881   if (PRIO_I2_I7 == (in & PRIO_I1_I7)) {
1882      out = PRIO_OUT_EO | PRIO_OUT_Q1 | PRIO_OUT_Q2;
1883      LOG((LOG_CPU,2,"   f9318 case (i) in:%#o out:%#o\n", in, out));
1884      return out;
1885   }
1886
1887   if (PRIO_I1_I7 == (in & PRIO_I0_I7)) {
1888      out = PRIO_OUT_EO | PRIO_OUT_Q0 | PRIO_OUT_Q1 | PRIO_OUT_Q2;
1889      LOG((LOG_CPU,2,"   f9318 case (j) in:%#o out:%#o\n", in, out));
1890      return out;
1891   }
1892
1893   out = PRIO_OUT_QZ | PRIO_OUT_GS;
1894   LOG((LOG_CPU,2,"   f9318 case (b) in:%#o out:%#o\n", in, out));
1895   return out;
1896}
1897#endif
1898
1899/**
1900 * @brief f1_task early: task switch
1901 *
1902 * The priority encoder finds the highest task requesting service
1903 * and switches the task number after the next cycle.
1904 *
1905 * <PRE>
1906 *   CT       PROM    NEXT'     RDCT'
1907 *   1 2 4 8  DATA   6 7 8 9   1 2 4 8
1908 *   ---------------------------------
1909 *   0 0 0 0  0367   1 1 1 1   0 1 1 1
1910 *   1 0 0 0  0353   1 1 1 0   1 0 1 1
1911 *   0 1 0 0  0323   1 1 0 1   0 0 1 1
1912 *   1 1 0 0  0315   1 1 0 0   1 1 0 1
1913 *   0 0 1 0  0265   1 0 1 1   0 1 0 1
1914 *   1 0 1 0  0251   1 0 1 0   1 0 0 1
1915 *   0 1 1 0  0221   1 0 0 1   0 0 0 1
1916 *   1 1 1 0  0216   1 0 0 0   1 1 1 0
1917 *   0 0 0 1  0166   0 1 1 1   0 1 1 0
1918 *   1 0 0 1  0152   0 1 1 0   1 0 1 0
1919 *   0 1 0 1  0122   0 1 0 1   0 0 1 0
1920 *   1 1 0 1  0114   0 1 0 0   1 1 0 0
1921 *   0 0 1 1  0064   0 0 1 1   0 1 0 0
1922 *   1 0 1 1  0050   0 0 1 0   1 0 0 0
1923 *   0 1 1 1  0020   0 0 0 1   0 0 0 0
1924 *   1 1 1 1  0017   0 0 0 0   1 1 1 1
1925 *
1926 * The various task wakeups are encoded using two 8:3-bit priority encoders F9318,
1927 * which are pin-compatible to the 74348 (inverted inputs and outputs).
1928 * Their part numbers are U1 and U2.
1929 * The two encoders are chained (EO of U1 goes to EI of U2):
1930 *
1931 * The outputs are fed into some NAND gates (74H10 and 74H00) to decode
1932 * the task number to latch (CT1-CT4) after a F1 TASK. The case where all
1933 * of RDCT1' to RDCT8' are high (1) is decoded as RESET'.
1934 *
1935 * signal   function
1936 * --------------------------------------------------
1937 * CT1      (U1.Q0' & U2.Q0' & RDCT1')'
1938 * CT2      (U1.Q1' & U2.Q1' & RDCT2')'
1939 * CT4      (U1.Q2' & U2.Q2' & RDCT4')'
1940 * CT8      (U1.GS' & RDCT8')'
1941 * RESET'   RDCT1' & RDCT2' & RDCT4' & RDCT8'
1942 *
1943 * In the tables below "x" is RDCTx' of current task
1944 *
1945 * signal          input   output, if first 0        CT1  CT2  CT4  CT8
1946 * ----------------------------------------------------------------------------------------
1947 * WAKE17' (T19?)   4 I7   Q2:0 Q1:0 Q0:0 GS:0 EO:1  1    1    1    1
1948 * WAKEKWDT'        3 I6   Q2:0 Q1:0 Q0:1 GS:0 EO:1  x    1    1    1
1949 * WAKEPART'        2 I5   Q2:0 Q1:1 Q0:0 GS:0 EO:1  1    x    1    1
1950 * WAKEDVT'         1 I4   Q2:0 Q1:1 Q0:1 GS:0 EO:1  x    x    1    1
1951 * WAKEDHT'        13 I3   Q2:1 Q1:0 Q0:0 GS:0 EO:1  1    1    x    1
1952 * WAKECURT'       12 I2   Q2:1 Q1:0 Q0:1 GS:0 EO:1  x    1    x    1
1953 * WAKEDWT'        11 I1   Q2:1 Q1:1 Q0:0 GS:0 EO:1  1    x    x    1
1954 * WAKEMRT'        10 I0   Q2:1 Q1:1 Q0:1 GS:0 EO:1  x    x    x    1
1955 * otherwise               Q2:1 Q1:1 Q0:1 GS:1 EO:0  x    x    x    x
1956 *
1957 * signal          input   output, if first 0
1958 * ----------------------------------------------------------------------------------------
1959 * WAKEET'          4 I7   Q2:0 Q1:0 Q0:0 GS:0 EO:1  1    1    1    x
1960 * WAKE6'           3 I6   Q2:0 Q1:0 Q0:1 GS:0 EO:1  x    1    1    x
1961 * WAKE5'           2 I5   Q2:0 Q1:1 Q0:0 GS:0 EO:1  1    x    1    x
1962 * WAKEKST'         1 I4   Q2:0 Q1:1 Q0:1 GS:0 EO:1  x    x    1    x
1963 * WAKE3' (T23?)   13 I3   Q2:1 Q1:0 Q0:0 GS:0 EO:1  1    1    x    x
1964 * WAKE2'          12 I2   Q2:1 Q1:0 Q0:1 GS:0 EO:1  x    1    x    x
1965 * WAKE1'          11 I1   Q2:1 Q1:1 Q0:0 GS:0 EO:1  1    x    x    x
1966 * 0 (GND)         10 I0   Q2:1 Q1:1 Q0:1 GS:0 EO:1  x    x    x    x
1967 * </PRE>
1968 */
1969void alto2_cpu_device::f1_task_0()
1970{
1971#if   USE_PRIO_F9318
1972   /* Doesn't work yet */
1973   register f9318_in_t wakeup_hi;
1974   register f9318_out_t u1;
1975   register f9318_in_t wakeup_lo;
1976   register f9318_out_t u2;
1977   register int addr = 017;
1978   register int rdct1, rdct2, rdct4, rdct8;
1979   register int ct1, ct2, ct4, ct8;
1980   register int wakeup, ct;
1981
1982   LOG((LOG_CPU,2, "   TASK %02o:%s\n", m_task, task_name(m_task)));
1983
1984   if (m_task > task_emu && (m_task_wakeup & (1 << m_task)))
1985      addr = m_task;
1986   LOG((LOG_CPU,2,"   ctl2k_u38[%02o] = %04o\n", addr, ctl2k_u38[addr] & 017));
1987
1988   rdct1 = (ctl2k_u38[addr] >> U38_RDCT1) & 1;
1989   rdct2 = (ctl2k_u38[addr] >> U38_RDCT2) & 1;
1990   rdct4 = (ctl2k_u38[addr] >> U38_RDCT4) & 1;
1991   rdct8 = (ctl2k_u38[addr] >> U38_RDCT8) & 1;
1992
1993   /* wakeup signals are active low */
1994   wakeup = ~m_task_wakeup;
1995
1996   /* U1
1997    * task wakeups 017 to 010 on I7 to I0
1998    * EI is 0 (would be 1 at reset)
1999    */
2000   wakeup_hi = (wakeup >> 8) & PRIO_I0_I7;
2001   u1 = f9318(wakeup_hi);
2002
2003   /* U2
2004    * task wakeups 007 to 001 on I7 to I1, I0 is 0
2005    * EO of U1 chained to EI
2006    */
2007   wakeup_lo = wakeup & PRIO_I0_I7;
2008   if (u1 & PRIO_OUT_EO)
2009      wakeup_lo |= PRIO_IN_EI;
2010   u2 = f9318(wakeup_lo);
2011
2012   /* CT1 = (U1.Q0' & U2.Q0' & RDCT1')' */
2013   ct1 = !((u1 & PRIO_OUT_Q0) && (u2 & PRIO_OUT_Q0) && rdct1);
2014   LOG((LOG_CPU,2,"     CT1:%o U1.Q0':%o U2.Q0':%o RDCT1':%o\n",
2015      ct1, (u1 & PRIO_OUT_Q0)?1:0, (u2 & PRIO_OUT_Q0)?1:0, rdct1));
2016   /* CT2 = (U1.Q1' & U2.Q1' & RDCT2')' */
2017   ct2 = !((u1 & PRIO_OUT_Q1) && (u2 & PRIO_OUT_Q1) && rdct2);
2018   LOG((LOG_CPU,2,"     CT2:%o U1.Q1':%o U2.Q1':%o RDCT2':%o\n",
2019      ct2, (u1 & PRIO_OUT_Q1)?1:0, (u2 & PRIO_OUT_Q1)?1:0, rdct2));
2020   /* CT4 = (U1.Q2' & U2.Q2' & RDCT4')' */
2021   ct4 = !((u1 & PRIO_OUT_Q2) && (u2 & PRIO_OUT_Q2) && rdct4);
2022   LOG((LOG_CPU,2,"     CT4:%o U1.Q2':%o U2.Q2':%o RDCT4':%o\n",
2023      ct4, (u1 & PRIO_OUT_Q2)?1:0, (u2 & PRIO_OUT_Q2)?1:0, rdct4));
2024   /* CT8 */
2025   ct8 = !((u1 & PRIO_OUT_GS) && rdct8);
2026   LOG((LOG_CPU,2,"     CT8:%o U1.GS':%o RDCT8':%o\n",
2027      ct8, (u1 & PRIO_OUT_GS)?1:0, rdct8));
2028
2029   ct = 8*ct8 + 4*ct4 + 2*ct2 + ct1;
2030
2031   if (ct != m_next_task) {
2032      LOG((LOG_CPU,2, "      switch to %02o\n", ct));
2033      m_next2_task = ct;
2034   } else {
2035      LOG((LOG_CPU,2, "      no switch\n"));
2036   }
2037#else   /* USE_PRIO_F9318 */
2038   int i;
2039
2040   LOG((LOG_CPU,2, "   TASK %02o:%s", m_task, task_name(m_task)));
2041   for (i = 15; i >= 0; i--) {
2042      if (m_task_wakeup & (1 << i)) {
2043         m_next2_task = i;
2044         if (m_next2_task != m_next_task) {
2045            LOG((LOG_CPU,2, " switch to %02o:%s\n", m_next2_task, task_name(m_next2_task)));
2046         } else {
2047            LOG((LOG_CPU,2, " no switch\n"));
2048         }
2049         return;
2050      }
2051   }
2052   fatal(3, "no tasks requesting service\n");
2053#endif   /* !USE_PRIO_F9318 */
2054}
2055
2056#ifdef   f1_block0_unused
2057/**
2058 * @brief f1_block early: block task
2059 *
2060 * The task request for the active task is cleared
2061 */
2062void alto2_cpu_device::f1_block_0()
2063{
2064   CPU_CLR_TASK_WAKEUP(m_task);
2065   LOG((LOG_CPU,2, "   BLOCK %02o:%s\n", m_task, task_name(m_task)));
2066}
2067#endif
2068
2069/**
2070 * @brief f2_bus_eq_zero late: branch on bus equals zero
2071 */
2072void alto2_cpu_device::f2_bus_eq_zero_1()
2073{
2074   UINT16 r = m_bus == 0 ? 1 : 0;
2075   LOG((LOG_CPU,2, "   BUS=0; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2076   m_next2 |= r;
2077}
2078
2079/**
2080 * @brief f2_shifter_lt_zero late: branch on shifter less than zero
2081 */
2082void alto2_cpu_device::f2_shifter_lt_zero_1()
2083{
2084   UINT16 r = (m_shifter & 0100000) ? 1 : 0;
2085   LOG((LOG_CPU,2, "   SH<0; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2086   m_next2 |= r;
2087}
2088
2089/**
2090 * @brief f2_shifter_eq_zero late: branch on shifter equals zero
2091 */
2092void alto2_cpu_device::f2_shifter_eq_zero_1()
2093{
2094   UINT16 r = m_shifter == 0 ? 1 : 0;
2095   LOG((LOG_CPU,2, "   SH=0; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2096   m_next2 |= r;
2097}
2098
2099/**
2100 * @brief f2_bus late: branch on bus bits BUS[6-15]
2101 */
2102void alto2_cpu_device::f2_bus_1()
2103{
2104   UINT16 r = A2_GET16(m_bus,16,6,15);
2105   LOG((LOG_CPU,2, "   BUS; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2106   m_next2 |= r;
2107}
2108
2109/**
2110 * @brief f2_alucy late: branch on latched ALU carry
2111 */
2112void alto2_cpu_device::f2_alucy_1()
2113{
2114   UINT16 r = m_laluc0;
2115   LOG((LOG_CPU,2, "   ALUCY; %sbranch (%#o|%#o)\n", r ? "" : "no ", m_next2, r));
2116   m_next2 |= r;
2117}
2118
2119/**
2120 * @brief f2_load_md late: load memory data
2121 *
2122 * Deliver BUS data to memory.
2123 */
2124void alto2_cpu_device::f2_load_md_1()
2125{
2126#if   ALTO2_DEBUG
2127   UINT16 mar = m_mem.mar;
2128#endif
2129   if (MIR_F1(m_mir) == f1_load_mar) {
2130      /* part of an XMAR */
2131      LOG((LOG_CPU,2, "   XMAR %#o (%#o)\n", mar, m_bus));
2132   } else {
2133      write_mem(m_bus);
2134      LOG((LOG_CPU,2, "   MD← BUS ([%#o]=%#o)\n", mar, m_bus));
2135   }
2136}
2137
2138/**
2139 * @brief read the microcode ROM/RAM halfword
2140 *
2141 * Note: HALFSEL is selecting the even (0) or odd (1) half of the
2142 * microcode RAM 32-bit word. Here's how the demultiplexers (74298)
2143 * u8, u18, u28 and u38 select the bits:
2144 *
2145 *           SN74298
2146 *         +---+-+---+
2147 *         |   +-+   |
2148 *    B2  -|1      16|-  Vcc
2149 *         |         |
2150 *    A2  -|2      15|-  QA
2151 *         |         |
2152 *    A1  -|3      14|-  QB
2153 *         |         |
2154 *    B1  -|4      13|-  QC
2155 *         |         |
2156 *    C2  -|5      12|-  QD
2157 *         |         |
2158 *    D2  -|6      11|-  CLK
2159 *         |         |
2160 *    D1  -|7      10|-  SEL
2161 *         |         |
2162 *   GND  -|8       9|-  C1
2163 *         |         |
2164 *         +---------+
2165 *
2166 *   chip  out pin  BUS in   pin HSEL=0      in   pin HSEL=1
2167 *   --------------------------------------------------------------
2168 *  u8    QA  15   0   A1   3   DRSEL(0)'   A2   2   DF2(0)
2169 *  u8    QB  14   1   B1   4   DRSEL(1)'   B2   1   DF2(1)'
2170 *  u8    QC  13   2   C1   9   DRSEL(2)'   C2   5   DF2(2)'
2171 *  u8    QD  12   3   D1   7   DRSEL(3)'   D2   6   DF2(3)'
2172 *
2173 *  u18   QA  15   4   A1   3   DRSEL(4)'   A2   2   LOADT'
2174 *  u18   QB  14   5   B1   4   DALUF(0)'   B2   1   LOADL
2175 *  u18   QC  13   6   C1   9   DALUF(1)'   C2   5   NEXT(00)'
2176 *  u18   QD  12   7   D1   7   DALUF(2)'   D2   6   NEXT(01)'
2177 *
2178 *  u28   QA  15   8   A1   3   DALUF(3)'   A2   2   NEXT(02)'
2179 *  u28   QB  14   9   B1   4   DBS(0)'     B2   1   NEXT(03)'
2180 *  u28   QC  13   10  C1   9   DBS(1)'     C2   5   NEXT(04)'
2181 *  u28   QD  12   11  D1   7   DBS(2)'     D2   6   NEXT(05)'
2182 *
2183 *  u38   QA  15   12  A1   3   DF1(0)      A2   2   NEXT(06)'
2184 *  u38   QB  14   13  B1   4   DF1(1)'     B2   1   NEXT(07)'
2185 *  u38   QC  13   14  C1   9   DF1(2)'     C2   5   NEXT(08)'
2186 *  u38   QD  12   15  D1   7   DF1(3)'     D2   6   NEXT(09)'
2187 *
2188 * The HALFSEL signal to the demultiplexers is the inverted bit BUS(5):
2189 * BUS(5)=1, HALFSEL=0, A1,B1,C1,D1 inputs, upper half of the 32-bit word
2190 * BUS(5)=0, HALFSEL=1, A2,B2,C2,D2 inputs, lower half of the 32-bit word
2191 */
2192void alto2_cpu_device::rdram()
2193{
2194   UINT32 addr, val;
2195   UINT32 bank = GET_CRAM_BANKSEL(m_cram_addr) % ALTO2_UCODE_RAM_PAGES;
2196   UINT32 wordaddr = GET_CRAM_WORDADDR(m_cram_addr);
2197
2198   m_rdram_flag = false;
2199   if (GET_CRAM_RAMROM(m_cram_addr)) {
2200      /* read ROM 0 at current mpc */
2201      addr = m_mpc & 01777;
2202      LOG((LOG_CPU,0,"   rdram: ROM [%05o] ", addr));
2203   } else {
2204      /* read RAM 0,1,2 */
2205      addr = bank * ALTO2_UCODE_PAGE_SIZE + wordaddr;
2206      LOG((LOG_CPU,0,"   rdram: RAM%d [%04o] ", bank, wordaddr));
2207   }
2208
2209   if (ALTO2_UCODE_RAM_BASE + addr >= ALTO2_UCODE_SIZE) {
2210      val = 0177777;   /* ??? */
2211      LOG((LOG_CPU,0,"invalid address (%06o)\n", val));
2212      return;
2213   }
2214   val = RD_CRAM(addr) ^ ALTO2_UCODE_INVERTED;
2215   if (GET_CRAM_HALFSEL(m_cram_addr)) {
2216      val = val >> 16;
2217      LOG((LOG_CPU,0,"upper:%06o\n", val));
2218   } else {
2219      val = val & 0177777;
2220      LOG((LOG_CPU,0,"lower:%06o\n", val));
2221   }
2222   m_bus &= val;
2223}
2224
2225/**
2226 * @brief write the microcode RAM from M register and ALU
2227 *
2228 * Note: M is a latch (MYL, i.e. memory L) on the CRAM board that latches
2229 * the ALU whenever LOADL and GOODTASK are met. GOODTASK is the Emulator
2230 * task and something I have not yet found out about: TASKA' and TASKB'.
2231 *
2232 * There's also an undumped PROM u21 which is addressed by GOODTASK and
2233 * 7 other signals...
2234 */
2235void alto2_cpu_device::wrtram()
2236{
2237   UINT32 addr;
2238   UINT32 bank = GET_CRAM_BANKSEL(m_cram_addr) % ALTO2_UCODE_RAM_PAGES;
2239   UINT32 wordaddr = GET_CRAM_WORDADDR(m_cram_addr);
2240
2241   m_wrtram_flag = false;
2242
2243   /* write RAM 0,1,2 */
2244   addr = bank * ALTO2_UCODE_PAGE_SIZE + wordaddr;
2245   LOG((LOG_CPU,0,"   wrtram: RAM%d [%04o] upper:%06o lower:%06o", bank, wordaddr, m_m, m_alu));
2246   if (ALTO2_UCODE_RAM_BASE + addr >= ALTO2_UCODE_SIZE) {
2247      LOG((LOG_CPU,0," invalid address\n"));
2248      return;
2249   }
2250   LOG((LOG_CPU,0,"\n"));
2251   WR_CRAM(addr, ((m_m << 16) | m_alu) ^ ALTO2_UCODE_INVERTED);
2252}
2253
2254#if   USE_ALU_74181
2255/**
2256 * <PRE>
2257 * Functional description of the 4-bit ALU 74181
2258 *
2259 * The 74181 is a 4-bit high speed parallel Arithmetic Logic Unit (ALU).
2260 * Controlled by four Function Select inputs (S0-S3) and the Mode Control
2261 * input (M), it can perform all the 16 possible logic operations or 16
2262 * different arithmetic operations on active HIGH or active LOW operands.
2263 * The Function Table lists these operations.
2264 *
2265 * When the Mode Control input (M) is HIGH, all internal carries are
2266 * inhibited and the device performs logic operations on the individual
2267 * bits as listed. When the Mode Control input is LOW, the carries are
2268 * enabled and the device performs arithmetic operations on the two 4-bit
2269 * words. The device incorporates full internal carry lookahead and
2270 * provides for either ripple carry between devices using the Cn+4 output,
2271 * or for carry lookahead between packages using the signals P' (Carry
2272 * Propagate) and G' (Carry Generate). In the ADD mode, P' indicates that
2273 * F' is 15 or more, while G' indicates that F' is 16 or more. In the
2274 * SUBTRACT mode, P' indicates that F' is zero or less, while G' indicates
2275 * that F' is less than zero. P' and G' are not affected by carry in.
2276 * When speed requirements are not stringent, it can be used in a simple
2277 * ripple carry mode by connecting the Carry output (Cn+4) signal to the
2278 * Carry input (Cn) of the next unit. For high speed operation the device
2279 * is used in conjunction with the 74182 carry lookahead circuit. One
2280 * carry lookahead package is required for each group of four 74181 devices.
2281 * Carry lookahead can be provided at various levels and offers high speed
2282 * capability over extremely long word lengths.
2283 *
2284 * The A=B output from the device goes HIGH when all four F' outputs are
2285 * HIGH and can be used to indicate logic equivalence over four bits when
2286 * the unit is in the subtract mode. The A=B output is open collector and
2287 * can be wired-AND with other A=B outputs to give a comparison for more
2288 * than four bits. The A=B signal can also be used with the Cn+4 signal
2289 * to indicated A>B and A<B.
2290 *
2291 * The Function Table lists the arithmetic operations that are performed
2292 * without a carry in. An incoming carry adds a one to each operation.
2293 * Thus, select code 0110 generates A minus B minus 1 (2's complement
2294 * notation) without a carry in and generates A minus B when a carry is
2295 * applied. Because subtraction is actually performed by the complementary
2296 * addition (1's complement), a carry out means borrow; thus a carry is
2297 * generated when there is no underflow and no carry is generated when
2298 * there is underflow. As indicated, this device can be used with either
2299 * active LOW inputs producing active LOW outputs or with active HIGH
2300 * inputs producing active HIGH outputs. For either case the table lists
2301 * the operations that are performed to the operands labeled inside the
2302 * logic symbol.
2303 *
2304 * The AltoI/II use four 74181s and a 74182 carry lookahead circuit,
2305 * and the inputs and outputs are all active HIGH.
2306 *
2307 * Active HIGH operands:
2308 *
2309 * +-------------------+-------------+------------------------+------------------------+
2310 * |    Mode Select    |   Logic     | Arithmetic w/o carry   | Arithmetic w/ carry    |
2311 * |      Inputs       |             |                        |                        |
2312 * |  S3  S2  S1  S0   |   (M=1)     | (M=0) (Cn=1)           | (M=0) (Cn=0)           |
2313 * +-------------------+-------------+------------------------+------------------------+
2314 * |   0   0   0   0   | A'          | A                      | A + 1                  |
2315 * +-------------------+-------------+------------------------+------------------------+
2316 * |   0   0   0   1   | A' | B'     | A | B                  | (A | B) + 1            |
2317 * +-------------------+-------------+------------------------+------------------------+
2318 * |   0   0   1   0   | A' & B      | A | B'                 | (A | B') + 1           |
2319 * +-------------------+-------------+------------------------+------------------------+
2320 * |   0   0   1   1   | logic 0     | - 1                    | -1 + 1                 |
2321 * +-------------------+-------------+------------------------+------------------------+
2322 * |   0   1   0   0   | (A & B)'    | A + (A & B')           | A + (A & B') + 1       |
2323 * +-------------------+-------------+------------------------+------------------------+
2324 * |   0   1   0   1   | B'          | (A | B) + (A & B')     | (A | B) + (A & B') + 1 |
2325 * +-------------------+-------------+------------------------+------------------------+
2326 * |   0   1   1   0   | A ^ B       | A - B - 1              | A - B - 1 + 1          |
2327 * +-------------------+-------------+------------------------+------------------------+
2328 * |   0   1   1   1   | A & B'      | (A & B) - 1            | (A & B) - 1 + 1        |
2329 * +-------------------+-------------+------------------------+------------------------+
2330 * |   1   0   0   0   | A' | B      | A + (A & B)            | A + (A & B) + 1        |
2331 * +-------------------+-------------+------------------------+------------------------+
2332 * |   1   0   0   1   | A' ^ B'     | A + B                  | A + B + 1              |
2333 * +-------------------+-------------+------------------------+------------------------+
2334 * |   1   0   1   0   | B           | (A | B') + (A & B)     | (A | B') + (A & B) + 1 |
2335 * +-------------------+-------------+------------------------+------------------------+
2336 * |   1   0   1   1   | A & B       | (A & B) - 1            | (A & B) - 1 + 1        |
2337 * +-------------------+-------------+------------------------+------------------------+
2338 * |   1   1   0   0   | logic 1     | A + A                  | A + A + 1              |
2339 * +-------------------+-------------+------------------------+------------------------+
2340 * |   1   1   0   1   | A | B'      | (A | B) + A            | (A | B) + A + 1        |
2341 * +-------------------+-------------+------------------------+------------------------+
2342 * |   1   1   1   0   | A | B       | (A | B') + A           | (A | B') + A + 1       |
2343 * +-------------------+-------------+------------------------+------------------------+
2344 * |   1   1   1   1   | A           | A - 1                  | A - 1 + 1              |
2345 * +-------------------+-------------+------------------------+------------------------+
2346 * </PRE>
2347 */
2348
2349enum {
2350    A10_UNUSED  = (1 << 0),
2351    A10_TSELECT = (1 << 1),
2352    A10_ALUCI   = (1 << 2),
2353    A10_ALUM    = (1 << 3),
2354    A10_ALUS0   = (1 << 4),
2355    A10_ALUS1   = (1 << 5),
2356    A10_ALUS2   = (1 << 6),
2357    A10_ALUS3   = (1 << 7),
2358    A10_ALUIN   = (A10_ALUM|A10_ALUCI|A10_ALUS0|A10_ALUS1|A10_ALUS2|A10_ALUS3)
2359};
2360
2361//! S function, M flag and C carry in
2362#define   SMC(s3,s2,s1,s0,m,ci) (s3*A10_ALUS3 + s2*A10_ALUS2 + s1*A10_ALUS1 + s0*A10_ALUS0 + m*A10_ALUM + ci*A10_ALUCI)
2363
2364/**
2365 * @brief Compute the 74181 ALU operation smc for inputs a and b
2366 *
2367 * The function, arithmetic / logic flag and carry in define the
2368 * ALU operation. The carry in is irrelevant for the logic operations.
2369 * The result is 17 bit, where bit #16 is the carry out.
2370 *
2371 * @param smc S function [0-15], M arithmetic/logic flag, C carry
2372 * @return resulting ALU output
2373 */
2374UINT32 alto2_cpu_device::alu_74181(UINT32 a, UINT32 b, UINT8 smc)
2375{
2376   register UINT32 f;
2377   register const UINT32 cout = 1 << 16;
2378
2379   switch (smc & A10_ALUIN) {
2380   case SMC(0,0,0,0, 0, 0): // 0000: A + 1
2381      f = a + 1;
2382      break;
2383
2384   case SMC(0,0,0,0, 0, 1): // 0000: A
2385      f = a;
2386      break;
2387
2388   case SMC(0,0,0,0, 1, 0): // 0000: A'
2389   case SMC(0,0,0,0, 1, 1):
2390      f = (~a) | cout;
2391      break;
2392
2393   case SMC(0,0,0,1, 0, 0): // 0001: (A | B) + 1
2394      f = (a | b) + 1;
2395      break;
2396
2397   case SMC(0,0,0,1, 0, 1): // 0001: A | B
2398      f = a | b;
2399      break;
2400
2401   case SMC(0,0,0,1, 1, 0): // 0001: A' | B'
2402   case SMC(0,0,0,1, 1, 1):
2403      f = (~a | ~b) | cout;
2404      break;
2405
2406   case SMC(0,0,1,0, 0, 0): // 0010: (A | B') + 1
2407      f = (a | ~b) + 1;
2408      break;
2409
2410   case SMC(0,0,1,0, 0, 1): // 0010: A | B'
2411      f = a | ~b;
2412      break;
2413
2414   case SMC(0,0,1,0, 1, 0): // 0010: A' & B
2415   case SMC(0,0,1,0, 1, 1):
2416      f = (~a & b) | cout;
2417      break;
2418
2419   case SMC(0,0,1,1, 0, 0): // 0011: -1 + 1
2420      f = (-1 + 1) | cout;
2421      break;
2422
2423   case SMC(0,0,1,1, 0, 1): // 0011: -1
2424      f = (-1) | cout;
2425      break;
2426
2427   case SMC(0,0,1,1, 1, 0): // 0011: logic 0
2428   case SMC(0,0,1,1, 1, 1):
2429      f = cout;
2430      break;
2431
2432   case SMC(0,1,0,0, 0, 0): // 0100: A + (A & B') + 1
2433      f = a + (a & ~b) + 1;
2434      break;
2435
2436   case SMC(0,1,0,0, 0, 1): // 0100: A + (A & B')
2437      f = a + (a & ~b);
2438      break;
2439
2440   case SMC(0,1,0,0, 1, 0): // 0100: (A & B)'
2441   case SMC(0,1,0,0, 1, 1):
2442      f = ~(a & b) | cout;
2443      break;
2444
2445   case SMC(0,1,0,1, 0, 0): // 0101: (A | B) + (A & B') + 1
2446      f = (a | b) + (a & ~b) + 1;
2447      break;
2448
2449   case SMC(0,1,0,1, 0, 1): // 0101: (A | B) + (A & B')
2450      f = (a | b) + (a & ~b);
2451      break;
2452
2453   case SMC(0,1,0,1, 1, 0): // 0101: B'
2454   case SMC(0,1,0,1, 1, 1):
2455      f = (~b) | cout;
2456      break;
2457
2458   case SMC(0,1,1,0, 0, 0): // 0110: A - B - 1 + 1
2459      f = (a - b - 1 + 1)  ^ cout;
2460      break;
2461
2462   case SMC(0,1,1,0, 0, 1): // 0110: A - B - 1
2463      f = (a - b - 1) ^ cout;
2464      break;
2465
2466   case SMC(0,1,1,0, 1, 0): // 0110: A ^ B
2467   case SMC(0,1,1,0, 1, 1):
2468      f = (a ^ b) | cout;
2469      break;
2470
2471   case SMC(0,1,1,1, 0, 0): // 0111: (A & B) - 1 + 1
2472      f = ((a & b) - 1 + 1) ^ cout;
2473      break;
2474
2475   case SMC(0,1,1,1, 0, 1): // 0111: (A & B) - 1
2476      f = ((a & b) - 1) ^ cout;
2477      break;
2478
2479   case SMC(0,1,1,1, 1, 0): // 0111: A & B'
2480   case SMC(0,1,1,1, 1, 1):
2481      f = (a & ~b) | cout;
2482      break;
2483
2484   case SMC(1,0,0,0, 0, 0): // 1000: A + (A & B) + 1
2485      f = a + (a & b) + 1;
2486      break;
2487
2488   case SMC(1,0,0,0, 0, 1): // 1000: A + (A & B)
2489      f = a + (a & b);
2490      break;
2491
2492   case SMC(1,0,0,0, 1, 0): // 1000: A' | B
2493   case SMC(1,0,0,0, 1, 1):
2494      f = (~a | b) | cout;
2495      break;
2496
2497   case SMC(1,0,0,1, 0, 0): // 1001: A + B + 1
2498      f = a + b + 1;
2499      break;
2500
2501   case SMC(1,0,0,1, 0, 1): // 1001: A + B
2502      f = a + b;
2503      break;
2504
2505   case SMC(1,0,0,1, 1, 0): // 1001: A' ^ B'
2506   case SMC(1,0,0,1, 1, 1):
2507      f = (~a ^ ~b) | cout;
2508      break;
2509
2510   case SMC(1,0,1,0, 0, 0): // 1010: (A | B') + (A & B) + 1
2511      f = (a | ~b) + (a & b) + 1;
2512      break;
2513
2514   case SMC(1,0,1,0, 0, 1): // 1010: (A | B') + (A & B)
2515      f = (a | ~b) + (a & b);
2516      break;
2517
2518   case SMC(1,0,1,0, 1, 0): // 1010: B
2519   case SMC(1,0,1,0, 1, 1):
2520      f = (b) | cout;
2521      break;
2522
2523   case SMC(1,0,1,1, 0, 0): // 1011: (A & B) - 1 + 1
2524      f = ((a & b) - 1 + 1) ^ cout;
2525      break;
2526
2527   case SMC(1,0,1,1, 0, 1): // 1011: (A & B) - 1
2528      f = ((a & b) - 1)  ^ cout;
2529      break;
2530
2531   case SMC(1,0,1,1, 1, 0): // 1011: A & B
2532   case SMC(1,0,1,1, 1, 1):
2533      f = (a & b) | cout;
2534      break;
2535
2536   case SMC(1,1,0,0, 0, 0): // 1100: A + A + 1
2537      f = a + a + 1;
2538      break;
2539
2540   case SMC(1,1,0,0, 0, 1): // 1100: A + A
2541      f = a + a;
2542      break;
2543
2544   case SMC(1,1,0,0, 1, 0): // 1100: logic 1
2545   case SMC(1,1,0,0, 1, 1):
2546      f = (~0) | cout;
2547      break;
2548
2549   case SMC(1,1,0,1, 0, 0): // 1101: (A | B) + A + 1
2550      f = (a | b) + a + 1;
2551      break;
2552
2553   case SMC(1,1,0,1, 0, 1): // 1101: (A | B) + A
2554      f = (a | b) + a;
2555      break;
2556
2557   case SMC(1,1,0,1, 1, 0): // 1101: A | B'
2558   case SMC(1,1,0,1, 1, 1):
2559      f = (a | ~b) | cout;
2560      break;
2561
2562   case SMC(1,1,1,0, 0, 0): // 1110: (A | B') + A + 1
2563      f = (a | ~b) + a + 1;
2564      break;
2565
2566   case SMC(1,1,1,0, 0, 1): // 1110: (A | B') + A
2567      f = (a | ~b) + a;
2568      break;
2569
2570   case SMC(1,1,1,0, 1, 0): // 1110: A | B
2571   case SMC(1,1,1,0, 1, 1):
2572      f = (a | b) | cout;
2573      break;
2574
2575   case SMC(1,1,1,1, 0, 0): // 1111: A - 1 + 1
2576      f = (a - 1 + 1) ^ cout;
2577      break;
2578
2579   case SMC(1,1,1,1, 0, 1): // 1111: A - 1
2580      f = (a - 1) ^ cout;
2581      break;
2582
2583   case SMC(1,1,1,1, 1, 0): // 1111: A
2584   case SMC(1,1,1,1, 1, 1):
2585      f = (a) | cout;
2586      break;
2587   }
2588   return f;
2589}
2590#endif
2591
2592/** @brief flag that tells whether to load the T register from BUS or ALU */
2593#define   TSELECT   A10_TSELECT
2594
2595/** @brief flag that tells wheter operation was 0: logic (M=1) or 1: arithmetic (M=0) */
2596#define   ALUM2   A10_ALUM
2597
2598/** @brief execute the CPU for at most nsecs nano seconds */
2599void alto2_cpu_device::execute_run()
2600{
2601   m_next = m_task_mpc[m_task];      // get current task's next mpc and address modifier
2602   m_next2 = m_task_next2[m_task];
2603
2604   do {
2605      int do_bs, flags;
2606
2607      /*
2608       * Subtract the microcycle time from the display time accu.
2609       * If it underflows, call the display state machine and add
2610       * the time for 24 pixel clocks to the accu.
2611       * This is very close to every seventh CPU cycle.
2612       */
2613      m_dsp_time -= ALTO2_UCYCLE;
2614      if (m_dsp_time < 0) {
2615         display_state_machine();
2616         m_dsp_time += ALTO2_DISPLAY_BITTIME(24);
2617      }
2618      if (m_unload_time >= 0) {
2619         /*
2620          * Subtract the microcycle time from the unload time accu.
2621          * If it underflows, call the unload word function which adds
2622          * the time for 16 or 32 pixel clocks to the accu, or ends
2623          * the unloading by leaving m_unload_time at -1.
2624          */
2625         m_unload_time -= ALTO2_UCYCLE;
2626         if (m_unload_time < 0)
2627            unload_word();
2628      }
2629#if   (USE_BITCLK_TIMER == 0)
2630      if (m_bitclk_time >= 0) {
2631         /*
2632          * Subtract the microcycle time from the bitclk time accu.
2633          * If it underflows, call the disk bitclk function which adds
2634          * the time for one bit as clocks to the accu, or ends
2635          * the bitclk sequence by leaving m_bitclk_time at -1.
2636          */
2637         m_bitclk_time -= ALTO2_UCYCLE;
2638         disk_bitclk(0, m_bitclk_index);
2639      }
2640#endif
2641
2642      m_cycle++;
2643      /* nano seconds per cycle */
2644      m_pico_time[m_task] += ALTO2_UCYCLE;
2645
2646      /* next instruction's mpc */
2647      m_mpc = m_next;
2648      m_mir = RD_CROM(m_mpc);
2649      m_rsel = MIR_RSEL(m_mir);
2650      m_next = MIR_NEXT(m_mir) | m_next2;
2651      m_next2 = A2_GET32(RD_CROM(m_next), 32, NEXT0, NEXT9) | (m_next2 & ~ALTO2_UCODE_PAGE_MASK);
2652      UINT8 aluf = MIR_ALUF(m_mir);
2653      UINT8 bs = MIR_BS(m_mir);
2654      UINT8 f1 = MIR_F1(m_mir);
2655      UINT8 f2 = MIR_F2(m_mir);
2656      LOG((LOG_CPU,2,"%s-%04o: %011o r:%02o aluf:%02o bs:%02o f1:%02o f2:%02o t:%o l:%o next:%05o next2:%05o\n",
2657         task_name(m_task), m_mpc, m_mir, m_rsel, aluf, bs, f1, f2, MIR_T(m_mir), MIR_L(m_mir), m_next, m_next2));
2658      debugger_instruction_hook(this, m_mpc);
2659
2660      /*
2661       * This bus source decoding is not performed if f1 = 7 or f2 = 7.
2662       * These functions use the BS field to provide part of the address
2663       * to the constant ROM
2664       */
2665      do_bs = !(f1 == f1_const || f2 == f2_const);
2666
2667      if (f1 == f1_load_mar) {
2668         if (check_mem_load_mar_stall(m_rsel)) {
2669            LOG((LOG_CPU,3, "   MAR← stall\n"));
2670            m_next2 = m_next;
2671            m_next = m_mpc;
2672            continue;
2673         }
2674      } else if (f2 == f2_load_md) {
2675         if (check_mem_write_stall()) {
2676            LOG((LOG_CPU,3, "   MD← stall\n"));
2677            m_next2 = m_next;
2678            m_next = m_mpc;
2679            continue;
2680         }
2681      }
2682      if (do_bs && bs == bs_read_md) {
2683         if (check_mem_read_stall()) {
2684            LOG((LOG_CPU,3, "   ←MD stall\n"));
2685            m_next2 = m_next;
2686            m_next = m_mpc;
2687            continue;
2688         }
2689      }
2690
2691      m_bus = 0177777;
2692
2693      if (m_rdram_flag)
2694         rdram();
2695
2696      /*
2697       * The constant memory is gated to the bus by F1 = 7, F2 = 7, or BS >= 4
2698       */
2699      if (!do_bs || bs >= 4) {
2700         int addr = 8 * m_rsel + bs;
2701         // There is something going wrong with using:
2702         // m_const->read_word(m_const->address_to_byte(addr));
2703         // because for addr=0160 it returns const[0161] instead of const[0160]
2704         // For now fall back to reading the const data from the byte array
2705         UINT16 data = m_const_data[2*addr+0] | (m_const_data[2*addr+1] << 8);
2706         m_bus &= data;
2707         LOG((LOG_CPU,2,"   %#o; BUS &= %#o CONST[%03o]\n", m_bus, data, addr));
2708      }
2709
2710      /*
2711       * early f2 has to be done before early bs, because the
2712       * emulator f2 acsource or acdest may change rsel
2713       */
2714      ((*this).*m_f2[0][m_task][f2])();
2715
2716      /*
2717       * early bs can be done now
2718       */
2719      if (do_bs)
2720         ((*this).*m_bs[0][m_task][bs])();
2721
2722      /*
2723       * early f1
2724       */
2725      ((*this).*m_f1[0][m_task][f1])();
2726
2727#if   USE_ALU_74181
2728      // The ALU a10 PROM address lines are
2729      // A4:SKIP      A3:ALUF0     A2:ALUF1     A1:ALUF2     A0:ALUF3
2730      // The PROM output lines are
2731      // B0: unused   B1: TSELECT  B2: ALUCI'   B3: ALUM'
2732      // B4: ALUS0'   B5: ALUS1'   B6: ALUS2'   B7: ALUS3'
2733      // B1 and B3-B7 are inverted on loading the PROM
2734      UINT8 a10 = m_alu_a10[(m_emu.skip << 4) | aluf];
2735      UINT32 alu = alu_74181(m_bus, m_t, a10);
2736      m_aluc0 = (alu >> 16) & 1;
2737      flags = (a10 ^ ALUM2) & (TSELECT | ALUM2);
2738      m_alu = static_cast<UINT16>(alu);
2739#else
2740      UINT32 alu;
2741      /* compute the ALU function */
2742      switch (aluf) {
2743      /**
2744       * 00: ALU ← BUS
2745       * PROM data for S3-0:1111 M:1 C:0 T:0
2746       * 74181 function F=A
2747       * T source is BUS
2748       */
2749      case aluf_bus__alut:
2750         alu = m_bus;
2751         m_aluc0 = 1;
2752         flags = 0;
2753         LOG((LOG_CPU,2,"   ALU← BUS (%#o := %#o)\n", alu, m_bus));
2754         break;
2755
2756      /**
2757       * 01: ALU ← T
2758       * PROM data for S3-0:1010 M:1 C:0 T:0
2759       * 74181 function F=B
2760       * T source is BUS
2761       */
2762      case aluf_treg:
2763         alu = m_t;
2764         m_aluc0 = 1;
2765         flags = 0;
2766         LOG((LOG_CPU,2,"   ALU← T (%#o := %#o)\n", alu, m_t));
2767         break;
2768
2769      /**
2770       * 02: ALU ← BUS | T
2771       * PROM data for S3-0:1110 M:1 C:0 T:1
2772       * 74181 function F=A|B
2773       * T source is ALU
2774       */
2775      case aluf_bus_or_t__alut:
2776         alu = m_bus | m_t;
2777         m_aluc0 = 1;
2778         flags = TSELECT;
2779         LOG((LOG_CPU,2,"   ALU← BUS OR T (%#o := %#o | %#o)\n", alu, m_bus, m_t));
2780         break;
2781
2782      /**
2783       * 03: ALU ← BUS & T
2784       * PROM data for S3-0:1011 M:1 C:0 T:0
2785       * 74181 function F=A&B
2786       * T source is BUS
2787       */
2788      case aluf_bus_and_t:
2789         alu = m_bus & m_t;
2790         m_aluc0 = 1;
2791         flags = 0;
2792         LOG((LOG_CPU,2,"   ALU← BUS AND T (%#o := %#o & %#o)\n", alu, m_bus, m_t));
2793         break;
2794
2795      /**
2796       * 04: ALU ← BUS ^ T
2797       * PROM data for S3-0:0110 M:1 C:0 T:0
2798       * 74181 function F=A^B
2799       * T source is BUS
2800       */
2801      case aluf_bus_xor_t:
2802         alu = m_bus ^ m_t;
2803         m_aluc0 = 1;
2804         flags = 0;
2805         LOG((LOG_CPU,2,"   ALU← BUS XOR T (%#o := %#o ^ %#o)\n", alu, m_bus, m_t));
2806         break;
2807
2808      /**
2809       * 05: ALU ← BUS + 1
2810       * PROM data for S3-0:0000 M:0 C:0 T:1
2811       * 74181 function F=A+1
2812       * T source is ALU
2813       */
2814      case aluf_bus_plus_1__alut:
2815         alu = m_bus + 1;
2816         m_aluc0 = (alu >> 16) & 1;
2817         flags = ALUM2 | TSELECT;
2818         LOG((LOG_CPU,2,"   ALU← BUS + 1 (%#o := %#o + 1)\n", alu, m_bus));
2819         break;
2820
2821      /**
2822       * 06: ALU ← BUS - 1
2823       * PROM data for S3-0:1111 M:0 C:1 T:1
2824       * 74181 function F=A-1
2825       * T source is ALU
2826       */
2827      case aluf_bus_minus_1__alut:
2828         alu = m_bus + 0177777;
2829         m_aluc0 = (~alu >> 16) & 1;
2830         flags = ALUM2 | TSELECT;
2831         LOG((LOG_CPU,2,"   ALU← BUS - 1 (%#o := %#o - 1)\n", alu, m_bus));
2832         break;
2833
2834      /**
2835       * 07: ALU ← BUS + T
2836       * PROM data for S3-0:1001 M:0 C:1 T:0
2837       * 74181 function F=A+B
2838       * T source is BUS
2839       */
2840      case aluf_bus_plus_t:
2841         alu = m_bus + m_t;
2842         m_aluc0 = (alu >> 16) & 1;
2843         flags = ALUM2;
2844         LOG((LOG_CPU,2,"   ALU← BUS + T (%#o := %#o + %#o)\n", alu, m_bus, m_t));
2845         break;
2846
2847      /**
2848       * 10: ALU ← BUS - T
2849       * PROM data for S3-0:0110 M:0 C:0 T:0
2850       * 74181 function F=A-B
2851       * T source is BUS
2852       */
2853      case aluf_bus_minus_t:
2854         alu = m_bus + ~m_t + 1;
2855         m_aluc0 = (~alu >> 16) & 1;
2856         flags = ALUM2;
2857         LOG((LOG_CPU,2,"   ALU← BUS - T (%#o := %#o - %#o)\n", alu, m_bus, m_t));
2858         break;
2859
2860      /**
2861       * 11: ALU ← BUS - T - 1
2862       * PROM data for S3-0:0110 M:0 C:1 T:0
2863       * 74181 function F=A-B-1
2864       * T source is BUS
2865       */
2866      case aluf_bus_minus_t_minus_1:
2867         alu = m_bus + ~m_t;
2868         m_aluc0 = (~alu >> 16) & 1;
2869         flags = ALUM2;
2870         LOG((LOG_CPU,2,"   ALU← BUS - T - 1 (%#o := %#o - %#o - 1)\n", alu, m_bus, m_t));
2871         break;
2872
2873      /**
2874       * 12: ALU ← BUS + T + 1
2875       * PROM data for S3-0:1001 M:0 C:0 T:1
2876       * 74181 function F=A+B+1
2877       * T source is ALU
2878       */
2879      case aluf_bus_plus_t_plus_1__alut:
2880         alu = m_bus + m_t + 1;
2881         m_aluc0 = (alu >> 16) & 1;
2882         flags = ALUM2 | TSELECT;
2883         LOG((LOG_CPU,2,"   ALU← BUS + T + 1 (%#o := %#o + %#o + 1)\n", alu, m_bus, m_t));
2884         break;
2885
2886      /**
2887       * 13: ALU ← BUS + SKIP
2888       * PROM data for S3-0:0000 M:0 C:SKIP T:1
2889       * 74181 function F=A (SKIP=1) or F=A+1 (SKIP=0)
2890       * T source is ALU
2891       */
2892      case aluf_bus_plus_skip__alut:
2893         alu = m_bus + m_emu.skip;
2894         m_aluc0 = (alu >> 16) & 1;
2895         flags = ALUM2 | TSELECT;
2896         LOG((LOG_CPU,2,"   ALU← BUS + SKIP (%#o := %#o + %#o)\n", alu, m_bus, m_emu.skip));
2897         break;
2898
2899      /**
2900       * 14: ALU ← BUS,T
2901       * PROM data for S3-0:1011 M:1 C:0 T:1
2902       * 74181 function F=A&B
2903       * T source is ALU
2904       */
2905      case aluf_bus_and_t__alut:
2906         alu = m_bus & m_t;
2907         m_aluc0 = 1;
2908         flags = TSELECT;
2909         LOG((LOG_CPU,2,"   ALU← BUS,T (%#o := %#o & %#o)\n", alu, m_bus, m_t));
2910         break;
2911
2912      /**
2913       * 15: ALU ← BUS & ~T
2914       * PROM data for S3-0:0111 M:1 C:0 T:0
2915       * 74181 function F=A&~B
2916       * T source is BUS
2917       */
2918      case aluf_bus_and_not_t:
2919         alu = m_bus & ~m_t;
2920         m_aluc0 = 1;
2921         flags = 0;
2922         LOG((LOG_CPU,2,"   ALU← BUS AND NOT T (%#o := %#o & ~%#o)\n", alu, m_bus, m_t));
2923         break;
2924
2925      /**
2926       * 16: ALU ← BUS
2927       * PROM data for S3-0:1111 M:1 C:0 T:1
2928       * 74181 function F=A
2929       * T source is ALU
2930       */
2931      case aluf_undef_16:
2932         alu = m_bus;
2933         m_aluc0 = 1;
2934         flags = TSELECT;
2935         LOG((LOG_CPU,0,"   ALU← 0 (illegal aluf in task %s, mpc:%05o aluf:%02o)\n", task_name(m_task), m_mpc, aluf));
2936         break;
2937
2938      /**
2939       * 17: ALU ← BUS
2940       * PROM data for S3-0:1111 M:1 C:0 T:1
2941       * 74181 function F=A
2942       * T source is ALU
2943       */
2944      case aluf_undef_17:
2945      default:
2946         alu = m_bus;
2947         m_aluc0 = 1;
2948         flags = TSELECT;
2949         LOG((LOG_CPU,0,"   ALU← 0 (illegal aluf in task %s, mpc:%05o aluf:%02o)\n", task_name(m_task), m_mpc, aluf));
2950      }
2951      m_alu = static_cast<UINT16>(alu);
2952#endif
2953
2954      /* WRTRAM now, before L is changed */
2955      if (m_wrtram_flag)
2956         wrtram();
2957
2958      switch (f1) {
2959      case f1_l_lsh_1:
2960         if (m_task == task_emu) {
2961            if (f2 == f2_emu_magic) {
2962               m_shifter = ((m_l << 1) | (m_t >> 15)) & 0177777;
2963               LOG((LOG_CPU,2,"   SHIFTER ←L MLSH 1 (%#o := %#o<<1|%#o)\n", m_shifter, m_l, m_t >> 15));
2964               break;
2965            }
2966            if (f2 == f2_emu_load_dns) {
2967               /* shifter is done in F2 */
2968               break;
2969            }
2970         }
2971         m_shifter = (m_l << 1) & 0177777;
2972         LOG((LOG_CPU,2,"   SHIFTER ←L LSH 1 (%#o := %#o<<1)\n", m_shifter, m_l));
2973         break;
2974
2975      case f1_l_rsh_1:
2976         if (m_task == task_emu) {
2977            if (f2 == f2_emu_magic) {
2978               m_shifter = ((m_l >> 1) | (m_t << 15)) & 0177777;
2979               LOG((LOG_CPU,2,"   SHIFTER ←L MRSH 1 (%#o := %#o>>1|%#o)\n", m_shifter, m_l, (m_t << 15) & 0100000));
2980               break;
2981            }
2982            if (f2 == f2_emu_load_dns) {
2983               /* shifter is done in F2 */
2984               break;
2985            }
2986         }
2987         m_shifter = m_l >> 1;
2988         LOG((LOG_CPU,2,"   SHIFTER ←L RSH 1 (%#o := %#o>>1)\n", m_shifter, m_l));
2989         break;
2990
2991      case f1_l_lcy_8:
2992         m_shifter = ((m_l >> 8) | (m_l << 8)) & 0177777;
2993         LOG((LOG_CPU,2,"   SHIFTER ←L LCY 8 (%#o := bswap %#o)\n", m_shifter, m_l));
2994         break;
2995
2996      default:
2997         /* shifter passes L, if F1 is not one of L LSH 1, L RSH 1 or L LCY 8 */
2998         m_shifter = m_l;
2999      }
3000
3001      /* late F1 is done now, if any */
3002      ((*this).*m_f1[1][m_task][f1])();
3003
3004      /* late F2 is done now, if any */
3005      ((*this).*m_f2[1][m_task][f2])();
3006
3007      /* late BS is done now, if no constant was put on the bus */
3008      if (do_bs)
3009         ((*this).*m_bs[1][m_task][bs])();
3010
3011      /*
3012       * update L register and LALUC0, and also M register,
3013       * if a RAM related task is active
3014       */
3015      if (MIR_L(m_mir)) {
3016         /* load L from ALU */
3017         m_l = m_alu;
3018         if (flags & ALUM2) {
3019            m_laluc0 = m_aluc0;
3020            LOG((LOG_CPU,2, "   L← ALU (%#o); LALUC0← ALUC0 (%o)\n", m_alu, m_aluc0));
3021         } else {
3022            m_laluc0 = 0;
3023            LOG((LOG_CPU,2, "   L← ALU (%#o); LALUC0← %o\n", m_alu, 0));
3024         }
3025         if (m_ram_related[m_task]) {
3026            /* load M from ALU, if 'GOODTASK' */
3027            m_m = m_alu;
3028            /* also writes to S[bank][0], which can't be read */
3029            m_s[m_s_reg_bank[m_task]][0] = m_alu;
3030            LOG((LOG_CPU,2, "   M← ALU (%#o)\n", m_alu));
3031         }
3032      }
3033
3034      /* update T register, if LOADT is set */
3035      if (MIR_T(m_mir)) {
3036         m_cram_addr = m_alu;
3037         if (flags & TSELECT) {
3038            LOG((LOG_CPU,2, "   T← ALU (%#o)\n", m_alu));
3039            m_t = m_alu;
3040         } else {
3041            LOG((LOG_CPU,2, "   T← BUS (%#o)\n", m_bus));
3042            m_t = m_bus;
3043         }
3044      }
3045
3046      if (m_task != m_next2_task) {
3047         /* switch now? */
3048         if (m_task == m_next_task) {
3049            /* one more microinstruction */
3050            m_next_task = m_next2_task;
3051         } else {
3052            /* save this task's mpc */
3053            m_task_mpc[m_task] = m_next;
3054            m_task_next2[m_task] = m_next2;
3055            m_task = m_next_task;
3056            LOG((LOG_CPU,1, "task switch to %02o:%s (cycle %lld)\n", m_task, task_name(m_task), cycle()));
3057            /* get new task's mpc */
3058            m_next = m_task_mpc[m_task];
3059            /* get address modifier after task switch (?) */
3060            m_next2 = m_task_next2[m_task];
3061
3062            /*
3063             * let the task know it becomes active now
3064             * and (most probably) reset the wakeup
3065             */
3066            ((*this).*m_active_callback[m_task])();
3067         }
3068      }
3069   } while (m_icount-- > 0);
3070
3071   /* save this task's mpc and address modifier */
3072   m_task_mpc[m_task] = m_next;
3073   m_task_next2[m_task] = m_next2;
3074}
3075
3076/** @brief reset the various registers */
3077void alto2_cpu_device::hard_reset()
3078{
3079   /* all tasks start in ROM0 */
3080   m_reset_mode = 0xffff;
3081
3082   memset(&m_ram_related, 0, sizeof(m_ram_related));
3083
3084   // install standard handlers in all tasks
3085   for (int task = 0; task < ALTO2_TASKS; task++) {
3086
3087      // every task starts at mpc = task number, in either ROM0 or RAM0
3088      m_task_mpc[task] = (m_ctl2k_u38[task] >> 4) ^ 017;
3089      m_active_callback[task] = &alto2_cpu_device::noop;
3090      if (0 == (m_reset_mode & (1 << task)))
3091         m_task_mpc[task] |= ALTO2_UCODE_RAM_BASE;
3092
3093      set_bs(task, bs_read_r,         &alto2_cpu_device::bs_read_r_0,   0);
3094      set_bs(task, bs_load_r,         &alto2_cpu_device::bs_load_r_0,   &alto2_cpu_device::bs_load_r_1);
3095      set_bs(task, bs_no_source,      0, 0);
3096      set_bs(task, bs_task_3,         &alto2_cpu_device::fn_bs_bad_0,   &alto2_cpu_device::fn_bs_bad_1);   // task specific
3097      set_bs(task, bs_task_4,         &alto2_cpu_device::fn_bs_bad_0,   &alto2_cpu_device::fn_bs_bad_1);   // task specific
3098      set_bs(task, bs_read_md,      &alto2_cpu_device::bs_read_md_0, 0);
3099      set_bs(task, bs_mouse,         &alto2_cpu_device::bs_mouse_0, 0);
3100      set_bs(task, bs_disp,         &alto2_cpu_device::bs_disp_0, 0);
3101
3102      set_f1(task, f1_nop,         0, 0);
3103      set_f1(task, f1_load_mar,      0, &alto2_cpu_device::f1_load_mar_1);
3104      set_f1(task, f1_task,         &alto2_cpu_device::f1_task_0, 0);
3105      set_f1(task, f1_block,         &alto2_cpu_device::fn_f1_bad_0, &alto2_cpu_device::fn_f1_bad_1);   // not all tasks have the f1_block
3106      set_f1(task, f1_l_lsh_1,      0, 0);         // inlined in execute()
3107      set_f1(task, f1_l_rsh_1,      0, 0);         // inlined in execute()
3108      set_f1(task, f1_l_lcy_8,      0, 0);         // inlined in execute()
3109      set_f1(task, f1_const,         0, 0);
3110      set_f1(task, f1_task_10,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3111      set_f1(task, f1_task_11,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3112      set_f1(task, f1_task_12,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3113      set_f1(task, f1_task_13,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3114      set_f1(task, f1_task_14,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3115      set_f1(task, f1_task_15,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3116      set_f1(task, f1_task_16,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3117      set_f1(task, f1_task_17,      &alto2_cpu_device::fn_f1_bad_0,   &alto2_cpu_device::fn_f1_bad_1);   // f1_task_10 to f1_task_17 are task specific
3118
3119      set_f2(task, f2_nop,         0, 0);
3120      set_f2(task, f2_bus_eq_zero,   0, &alto2_cpu_device::f2_bus_eq_zero_1);
3121      set_f2(task, f2_shifter_lt_zero,0, &alto2_cpu_device::f2_shifter_lt_zero_1);
3122      set_f2(task, f2_shifter_eq_zero,0, &alto2_cpu_device::f2_shifter_eq_zero_1);
3123      set_f2(task, f2_bus,         0, &alto2_cpu_device::f2_bus_1);
3124      set_f2(task, f2_alucy,         0, &alto2_cpu_device::f2_alucy_1);
3125      set_f2(task, f2_load_md,      0, &alto2_cpu_device::f2_load_md_1);
3126      set_f2(task, f2_const,         0, 0);
3127      set_f2(task, f2_task_10,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3128      set_f2(task, f2_task_11,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3129      set_f2(task, f2_task_12,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3130      set_f2(task, f2_task_13,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3131      set_f2(task, f2_task_14,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3132      set_f2(task, f2_task_15,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3133      set_f2(task, f2_task_16,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3134      set_f2(task, f2_task_17,      &alto2_cpu_device::fn_f2_bad_0,   &alto2_cpu_device::fn_f2_bad_1);   // f2_task_10 to f2_task_17 are task specific
3135   }
3136
3137   init_memory();
3138   init_disk();
3139   init_disp();
3140   init_kbd();
3141   init_mouse();
3142   init_hw();
3143
3144   init_emu(task_emu);
3145   init_ksec(task_ksec);
3146   init_ether(task_ether);
3147   init_mrt(task_mrt);
3148   init_dwt(task_dwt);
3149   init_curt(task_curt);
3150   init_dht(task_dht);
3151   init_dvt(task_dvt);
3152   init_part(task_part);
3153   init_kwd(task_kwd);
3154
3155   m_dsp_time = 0;         // reset the display state machine values
3156   m_dsp_state = 020;
3157
3158   m_task = 0;                  // start with task 0
3159   m_task_wakeup |= 1 << 0;      // set wakeup flag
3160}
3161
3162/** @brief software initiated reset (STARTF) */
3163int alto2_cpu_device::soft_reset()
3164{
3165
3166   for (int task = 0; task < ALTO2_TASKS; task++) {
3167      // every task starts at mpc = task number, in either ROM0 or RAM0
3168      m_task_mpc[task] = (m_ctl2k_u38[task] >> 4) ^ 017;
3169      if (0 == (m_reset_mode & (1 << task)))
3170         m_task_mpc[task] |= ALTO2_UCODE_RAM_BASE;
3171   }
3172   m_next2_task = 0;      // switch to task 0
3173   m_reset_mode = 0xffff;   // all tasks start in ROM0 again
3174
3175   m_dsp_time = 0;         // reset the display state machine values
3176   m_dsp_state = 020;
3177
3178   return m_next_task;      // return next task (?)
3179}
Property changes on: branches/alto2/src/emu/cpu/alto2/alto2cpu.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
branches/alto2/src/emu/cpu/alto2/a2part.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212//! called by the CPU when the parity task becomes active
1313void alto2_cpu_device::activate_part()
branches/alto2/src/emu/cpu/alto2/a2ether.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/** @brief the ethernet ID of this machine */
1313UINT8 ether_id = 254;
branches/alto2/src/emu/cpu/alto2/alto2cpu.h
r0r26287
1/*****************************************************************************
2 *
3 *   Portable Xerox AltoII CPU core interface
4 *
5 *   Copyright: Juergen Buchmueller <pullmoll@t-online.de>
6 *
7 *   Licenses: MAME, GPLv2
8 *
9 *****************************************************************************/
10#include "emu.h"
11#include "debugger.h"
12
13#pragma once
14
15#ifndef _CPU_ALTO2_H_
16#define _CPU_ALTO2_H
17
18#include "machine/diablo_hd.h"
19
20#define   ALTO2_TAG "alto2"
21
22#ifndef   ALTO2_DEBUG
23#define   ALTO2_DEBUG             0   //!< define to 1 to enable logerror() output
24#endif
25
26#define   USE_PRIO_F9318         0   //!< define to 1 to use the F9318 priority encoder code
27#define   USE_ALU_74181         1   //!< define to 1 to use the SN74181 ALU code
28#define   DEBUG_DISPLAY_TIMING   0   //!< define to 1 to debug the display timing
29#define   USE_BITCLK_TIMER      0   //!< define to 1 to use a very high rate timer for the disk bit clock
30#define   ALTO2_HAMMING_CHECK      0   //!< define to 1 to incorporate the Hamming code and Parity check
31
32#define   ALTO2_TASKS      16         //!< 16 task slots
33#define   ALTO2_REGS      32         //!< 32 16-bit words in the R register file
34#define   ALTO2_ALUF      16         //!< 16 ALU functions (74181)
35#define   ALTO2_BUSSRC   8         //!< 8 bus sources
36#define   ALTO2_F1MAX      16         //!< 16 F1 functions
37#define   ALTO2_F2MAX      16         //!< 16 F2 functions
38#define   ALTO2_UCYCLE   169542      //!< time in pico seconds for a CPU micro cycle: 29.4912MHz/5 -> 5.898240Hz ~= 169.542ns/clock
39
40#define   ALTO2_ETHER_FIFO_SIZE   16
41
42#ifndef   ALTO2_CRAM_CONFIG
43#define   ALTO2_CRAM_CONFIG   2      //!< use default configuration 2
44#endif
45
46#if   (ALTO2_CRAM_CONFIG==1)
47#define   ALTO2_UCODE_ROM_PAGES   1      //!< number of microcode ROM pages
48#define   ALTO2_UCODE_RAM_PAGES   1      //!< number of microcode RAM pages
49#elif (ALTO2_CRAM_CONFIG==2)
50#define   ALTO2_UCODE_ROM_PAGES   2      //!< number of microcode ROM pages
51#define   ALTO2_UCODE_RAM_PAGES   1      //!< number of microcode RAM pages
52#elif (ALTO2_CRAM_CONFIG==3)
53#define   ALTO2_UCODE_ROM_PAGES   1      //!< number of microcode ROM pages
54#define   ALTO2_UCODE_RAM_PAGES   3      //!< number of microcode RAM pages
55#else
56#error "Undefined CROM/CRAM configuration"
57#endif
58
59/**
60 * \brief number of S register banks
61 * This depends on the number of RAM pages
62 *   8 pages in 3K CRAM configuration
63 *   1 page in 1K CRAM configurations
64 */
65#if   (ALTO2_UCODE_RAM_PAGES == 3)
66#define   ALTO2_SREG_BANKS   8
67#else
68#define   ALTO2_SREG_BANKS   1
69#endif
70
71#define   ALTO2_UCODE_PAGE_SIZE   1024                  //!< number of words of microcode
72#define   ALTO2_UCODE_PAGE_MASK   (ALTO2_UCODE_PAGE_SIZE-1)   //!< mask for microcode ROM/RAM address
73#define   ALTO2_UCODE_SIZE      ((ALTO2_UCODE_ROM_PAGES + ALTO2_UCODE_RAM_PAGES) * ALTO2_UCODE_PAGE_SIZE)   //!< total number of words of microcode
74#define   ALTO2_UCODE_RAM_BASE   (ALTO2_UCODE_ROM_PAGES * ALTO2_UCODE_PAGE_SIZE)   //!< base offset for the RAM page(s)
75#define   ALTO2_CONST_SIZE      256                     //!< number words in the constant ROM
76#define   ALTO2_RAM_SIZE         0200000                  //!< size of main memory in words
77#define   ALTO2_IO_PAGE_BASE      0177000                  //!< base address of the memory mapped io range
78#define   ALTO2_IO_PAGE_SIZE      01000                  //!< size of the memory mapped io range
79
80//! inverted bits in the micro instruction 32 bit word
81#define   ALTO2_UCODE_INVERTED   ((1 << 10) | (1 << 15) | (1 << 19))
82
83/**
84 * @brief start value for the horizontal line counter
85 *
86 * This value is loaded into the three 4 bit counters (type 9316)
87 * with numbers 65, 67, and 75.
88 * 65: A=0 B=1 C=1 D=0
89 * 67: A=1 B=0 C=0 D=1
90 * 75: A=0 B=0 C=0 D=0
91 *
92 * The value is 150
93 */
94#define   ALTO2_DISPLAY_HLC_START (2+4+16+128)
95
96/**
97 * @brief end value for the horizontal line counter
98 *
99 * This is decoded by H30, an 8 input NAND gate.
100 * The value is 1899; horz. line count range 150…1899 = 1750.
101 *
102 * There are 1750 / 2 = 875 total scanlines.
103 */
104#define   ALTO2_DISPLAY_HLC_END (1+2+8+32+64+256+512+1024)
105
106/**
107 * @brief display total height, including overscan (vertical blanking and synch)
108 *
109 * The display is interleaved in two fields, alternatingly drawing the even and odd
110 * scanlines to the monitor. The frame rate is 60Hz, which is actually the rate
111 * of the half-frames. The rate for full frames is thus 30Hz.
112 */
113#define   ALTO2_DISPLAY_TOTAL_HEIGHT ((ALTO2_DISPLAY_HLC_END + 1 - ALTO2_DISPLAY_HLC_START) / 2)
114
115/**
116 * @brief display total width, including horizontal blanking
117 *
118 * Known facts:
119 *
120 * We have 606x808 visible pixels, and the pixel clock is said to be 50ns
121 * (20MHz), while the crystal in the schematics is labeled 20.16 MHz,
122 * so the pixel clock would actually be 49.6031ns.
123 *
124 * The total number of scanlines is, according to the docs, 875.
125 *
126 * 875 scanlines at 30 frames per second, thus the scanline rate is 26.250 kHz.
127 *
128 * If I divide 20.16 MHz by 26.250 kHz, I get 768 pixels for the total width
129 * of a scanline in pixels.
130 *
131 * The horizontal blanking period would then be 768 - 606 = 162 pixels, and
132 * thus 162 * 49.6031ns ~= 8036ns = 8.036us for the HBLANK time.
133 *
134 * In the display schematics there is a divide by 24 logic, and when
135 * dividing the 768 pixels per scanline by 24, we have 32 phases of a scanline.
136 *
137 * A S8223 PROM (a63) with 32x8 bits contains the status of the HBLANK and
138 * HSYNC signals for these phases, the SCANEND and HLCGATE signals, as well
139 * as its own next address A0-A3!
140 *
141 */
142#define   ALTO2_DISPLAY_TOTAL_WIDTH 768
143
144
145#define   ALTO2_DISPLAY_FIFO 16                                          //!< the display fifo has 16 words
146#define   ALTO2_DISPLAY_SCANLINE_WORDS (ALTO2_DISPLAY_TOTAL_WIDTH/16)               //!< words per scanline
147#define   ALTO2_DISPLAY_HEIGHT 808                                                    //!< number of visible scanlines per frame; 808 really, but there are some empty lines?
148#define   ALTO2_DISPLAY_WIDTH 606                                                     //!< visible width of the display; 38 words - 2 pixels
149#define   ALTO2_DISPLAY_VISIBLE_WORDS ((ALTO2_DISPLAY_WIDTH+15)/16)                   //!< visible words per scanline
150#define   ALTO2_DISPLAY_BITCLOCK 20160000ll                                           //!< display bit clock in in Hertz (20.16MHz)
151#define   ALTO2_DISPLAY_BITTIME(n) (U64(1000000000000)*(n)/ALTO2_DISPLAY_BITCLOCK)   //!< display bit time in in pico seconds (~= 49.6031ns)
152#define   ALTO2_DISPLAY_SCANLINE_TIME   ALTO2_DISPLAY_BITTIME(ALTO2_DISPLAY_TOTAL_WIDTH)//!< time for a scanline in pico seconds (768 * 49.6031ns)
153#define   ALTO2_DISPLAY_VISIBLE_TIME ALTO2_DISPLAY_BITTIME(ALTO2_DISPLAY_WIDTH)      //!< time of the visible part of a scanline in pico seconds (606 * 49.6031ns)
154#define   ALTO2_DISPLAY_WORD_TIME   ALTO2_DISPLAY_BITTIME(16)                     //!< time for a word in pico seconds (16 pixels * 49.6031ns)
155#define   ALTO2_DISPLAY_VBLANK_TIME ((ALTO2_DISPLAY_TOTAL_HEIGHT-ALTO2_DISPLAY_HEIGHT)*HZ_TO_ATTOSECONDS(26250))
156
157enum {
158   // micro code task, micro program counter, next and next2
159   A2_TASK, A2_MPC, A2_NEXT, A2_NEXT2,
160   // BUS, ALU, temp, latch, memory latch and carry flags
161   A2_BUS, A2_T, A2_ALU, A2_ALUC0,   A2_L, A2_SHIFTER, A2_LALUC0, A2_M,
162   // DISK controller registers
163   A2_DRIVE, A2_KADDR, A2_KADR, A2_KSTAT, A2_KCOM, A2_KRECNO,
164   A2_SHIFTIN, A2_SHIFTOUT, A2_DATAIN, A2_DATAOUT, A2_KRWC,
165   A2_KFER, A2_WDTSKENA, A2_WDINIT0, A2_WDINIT, A2_STROBE,
166   A2_BITCLK, A2_DATIN, A2_BITCNT, A2_CARRY, A2_SECLATE,
167   A2_SEEKOK, A2_OKTORUN, A2_READY,
168   A2_R,   // 32 R registers
169   A2_AC3 = A2_R, A2_AC2, A2_AC1, A2_AC0, A2_R04, A2_R05, A2_PC,  A2_R07,
170   A2_R10, A2_R11, A2_R12, A2_R13, A2_R14, A2_R15, A2_R16, A2_R17,
171   A2_R20, A2_R21, A2_R22, A2_R23, A2_R24, A2_R25, A2_R26, A2_R27,
172   A2_R30, A2_R31, A2_R32, A2_R33, A2_R34, A2_R35, A2_R36, A2_R37,
173   A2_S,   // 32 S registers
174   A2_S00 = A2_S, A2_S01, A2_S02, A2_S03, A2_S04, A2_S05, A2_S06, A2_S07,
175   A2_S10, A2_S11, A2_S12, A2_S13, A2_S14, A2_S15, A2_S16, A2_S17,
176   A2_S20, A2_S21, A2_S22, A2_S23, A2_S24, A2_S25, A2_S26, A2_S27,
177   A2_S30, A2_S31, A2_S32, A2_S33, A2_S34, A2_S35, A2_S36, A2_S37
178};
179
180/**
181 * @brief enumeration of the inputs and outputs of a JK flip-flop type 74109
182 * <PRE>
183 * 74109
184 * Dual J-/K flip-flops with set and reset.
185 *
186 *       +----------+           +-----------------------------+
187 * /1RST |1  +--+ 16| VCC       | J |/K |CLK|/SET|/RST| Q |/Q |
188 *    1J |2       15| /2RST     |---+---+---+----+----+---+---|
189 *   /1K |3       14| 2J        | X | X | X |  0 |  0 | 1 | 1 |
190 *  1CLK |4   74  13| /2K       | X | X | X |  0 |  1 | 1 | 0 |
191 * /1SET |5  109  12| 2CLK      | X | X | X |  1 |  0 | 0 | 1 |
192 *    1Q |6       11| /2SET     | 0 | 0 | / |  1 |  1 | 0 | 1 |
193 *   /1Q |7       10| 2Q        | 0 | 1 | / |  1 |  1 | - | - |
194 *   GND |8        9| /2Q       | 1 | 0 | / |  1 |  1 |/Q | Q |
195 *       +----------+           | 1 | 1 | / |  1 |  1 | 1 | 0 |
196 *                              | X | X |!/ |  1 |  1 | - | - |
197 *                              +-----------------------------+
198 *
199 * [This information is part of the GIICM]
200 * </PRE>
201 */
202typedef enum {
203   JKFF_0,               //!< no inputs or outputs
204   JKFF_CLK   = (1 << 0),   //!< clock signal
205   JKFF_J      = (1 << 1),   //!< J input
206   JKFF_K      = (1 << 2),   //!< K' input
207   JKFF_S      = (1 << 3),   //!< S' input
208   JKFF_C      = (1 << 4),   //!< C' input
209   JKFF_Q      = (1 << 5),   //!< Q  output
210   JKFF_Q0      = (1 << 6)   //!< Q' output
211}   jkff_t;
212
213class alto2_cpu_device :  public cpu_device
214{
215public:
216   // construction/destruction
217   alto2_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
218   ~alto2_cpu_device();
219
220   //! driver interface to set diablo_hd_device
221   void set_diablo(int unit, diablo_hd_device* ptr);
222
223   //! call in for the next sector callback
224   void next_sector(int unit);
225
226   //! return the display bitmap
227   bitmap_ind16& display() { return *m_displ_bitmap; }
228
229   DECLARE_ADDRESS_MAP( ucode_map, 32 );
230   DECLARE_ADDRESS_MAP( const_map, 16 );
231   DECLARE_ADDRESS_MAP( iomem_map, 16 );
232
233   //! register a mouse motion in x direction
234   DECLARE_INPUT_CHANGED_MEMBER( mouse_motion_x );
235   //! register a mouse motion in y direction
236   DECLARE_INPUT_CHANGED_MEMBER( mouse_motion_y );
237   //! register a mouse button change
238   DECLARE_INPUT_CHANGED_MEMBER( mouse_buttons );
239
240protected:
241   //! device-level override for start
242   virtual void device_start();
243   //! device-level override for reset
244   virtual void device_reset();
245
246   //! device-level override for post reset
247   void interface_post_reset();
248
249   //! device_execute_interface overrides
250   virtual UINT32 execute_min_cycles() const { return 1; }
251   virtual UINT32 execute_max_cycles() const { return 1; }
252   virtual UINT32 execute_input_lines() const { return 1; }
253   virtual void execute_run();
254   virtual void execute_set_input(int inputnum, int state);
255
256   //! device_memory_interface overrides
257   virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const;
258
259   //! device (P)ROMs
260   virtual const rom_entry *device_rom_region() const;
261   //! device_state_interface overrides
262   void state_string_export(const device_state_entry &entry, astring &string);
263
264   //! device_disasm_interface overrides
265   virtual UINT32 disasm_min_opcode_bytes() const { return 4; }
266   virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
267   virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
268
269private:
270#if   ALTO2_DEBUG
271   enum {
272      LOG_0,
273      LOG_CPU      = (1 <<  0),
274      LOG_EMU      = (1 <<  1),
275      LOG_T01      = (1 <<  2),
276      LOG_T02      = (1 <<  3),
277      LOG_T03      = (1 <<  4),
278      LOG_KSEC   = (1 <<  5),
279      LOG_T05      = (1 <<  6),
280      LOG_T06      = (1 <<  7),
281      LOG_ETH      = (1 <<  8),
282      LOG_MRT      = (1 <<  9),
283      LOG_DWT      = (1 << 10),
284      LOG_CURT   = (1 << 11),
285      LOG_DHT      = (1 << 12),
286      LOG_DVT      = (1 << 13),
287      LOG_PART   = (1 << 14),
288      LOG_KWD      = (1 << 15),
289      LOG_T17      = (1 << 16),
290      LOG_MEM      = (1 << 17),
291      LOG_RAM      = (1 << 18),
292      LOG_DRIVE   = (1 << 19),
293      LOG_DISK   = (1 << 20),
294      LOG_DISPL   = (1 << 21),
295      LOG_MOUSE   = (1 << 22),
296      LOG_HW      = (1 << 23),
297      LOG_KBD      = (1 << 24),
298      LOG_ALL      = ((1 << 25) - 1)
299   };
300   int m_log_types;
301   int m_log_level;
302   bool m_log_newline;
303   void logprintf(int type, int level, const char* format, ...);
304#   define   LOG(x) logprintf x
305#else
306#   define   LOG(x)
307#endif
308
309   void fatal(int level, const char *format, ...);
310
311   address_space_config m_ucode_config;
312   address_space_config m_const_config;
313   address_space_config m_iomem_config;
314
315   address_space* m_iomem;
316
317   UINT8* m_ucode_crom;
318   UINT8* m_ucode_cram;
319   UINT8* m_const_data;
320
321   //! read microcode CROM
322   DECLARE_READ32_MEMBER ( crom_r );
323
324   //! read microcode CRAM
325   DECLARE_READ32_MEMBER ( cram_r );
326
327   //! write microcode CRAM
328   DECLARE_WRITE32_MEMBER( cram_w );
329
330   //! read constants PROM
331   DECLARE_READ16_MEMBER ( const_r );
332
333   //! read i/o space RAM
334   DECLARE_READ16_MEMBER ( ioram_r );
335
336   //!< write i/o space RAM
337   DECLARE_WRITE16_MEMBER( ioram_w );
338
339   //!< read memory mapped i/o
340   DECLARE_READ16_MEMBER ( mmio_r );
341
342   //!< write memory mapped i/o
343   DECLARE_WRITE16_MEMBER( mmio_w );
344
345   int m_icount;
346
347   static const UINT8 m_ether_id = 0241;
348
349   typedef void (alto2_cpu_device::*a2func)();
350   typedef void (alto2_cpu_device::*a2cb)(int unit);
351   typedef void (alto2_cpu_device::*a2io_wr)(UINT32 addr, UINT16 data);
352   typedef UINT16 (alto2_cpu_device::*a2io_rd)(UINT32 addr);
353
354   //! task numbers
355   enum {
356      task_emu,      //!< emulator task
357      task_1,         //!< unused
358      task_2,         //!< unused
359      task_3,         //!< unused
360      task_ksec,      //!< disk sector task
361      task_5,         //!< unused
362      task_6,         //!< unused
363      task_ether,      //!< ethernet task
364      task_mrt,      //!< memory refresh task
365      task_dwt,      //!< display word task
366      task_curt,      //!< cursor task
367      task_dht,      //!< display horizontal task
368      task_dvt,      //!< display vertical task
369      task_part,      //!< parity task
370      task_kwd,      //!< disk word task
371      task_17         //!< unused task slot 017
372   };
373
374   //! register select values accessing R (Note: register numbers are octal)
375   enum {
376      rsel_ac3,      //!< AC3 used by emulator as accu 3. Also used by Mesa emulator to keep bytecode to execute after breakpoint
377      rsel_ac2,      //!< AC2 used by emulator as accu 2. Also used by Mesa emulator as x register for xfer
378      rsel_ac1,      //!< AC1 used by emulator as accu 1. Also used by Mesa emulator as r-temporary for return indices and values
379      rsel_ac0,      //!< AC0 used by emulator as accu 0. Also used by Mesa emulator as new field bits for WF and friends
380      rsel_r04,      //!< NWW state of the interrupt system
381      rsel_r05,      //!< SAD. Also used by Mesa emulator as scratch R-register for counting
382      rsel_pc,      //!< PC used by emulator as program counter
383      rsel_r07,      //!< XREG. Also used by Mesa emulator as task hole, i.e. pigeonhole for saving things across tasks.
384      rsel_r10,      //!< XH. Also used by Mesa emulator as instruction byte register
385      rsel_r11,      //!< CLOCKTEMP - used in the MRT
386      rsel_r12,      //!< ECNTR remaining words in buffer - ETHERNET
387      rsel_r13,      //!< EPNTR points BEFORE next word in buffer - ETHERNET
388      rsel_r14,
389      rsel_r15,      //!< MPC. Used by the Mesa emulator as program counter
390      rsel_r16,      //!< STKP. Used by the Mesa emulator as stack pointer [0-10] 0 empty, 10 full
391      rsel_r17,      //!< XTSreg. Used by the Mesa emulator to xfer trap state
392      rsel_r20,      //!< CURX. Holds cursor X; used by the cursor task
393      rsel_r21,      //!< CURDATA. Holds the cursor data; used by the cursor task
394      rsel_r22,      //!< CBA. Holds the address of the currently active DCB+1
395      rsel_r23,      //!< AECL. Holds the address of the end of the current scanline's bitmap
396      rsel_r24,      //!< SLC. Holds the number of scanlines remaining in currently active DCB
397      rsel_r25,      //!< MTEMP. Holds the temporary cell
398      rsel_r26,      //!< HTAB. Holds the number of tab words remaining on current scanline
399      rsel_r27,      //!< YPOS
400      rsel_r30,      //!< DWA. Holds the address of the bit map doubleword currently being fetched for transmission to the hardware buffer.
401      rsel_r31,      //!< KWDCT. Used by the disk tasks as word counter
402      rsel_r32,      //!< CKSUMR. Used by the disk tasks as checksum register (and *amble counter?)
403      rsel_r33,      //!< KNMAR. Used by the disk tasks as transfer memory address register
404      rsel_r34,      //!< DCBR. Used by the disk tasks to keep the current device control block
405      rsel_r35,      //!< TEMP. Used by the Mesa emulator, and also by BITBLT
406      rsel_r36,      //!< TEMP2. Used by the Mesa emulator, and also by BITBLT
407      rsel_r37      //!< CLOCKREG. Low order bits of the real time clock
408   };
409
410   //! ALU function numbers
411   enum {
412      /**
413       * \brief 00: ALU <- BUS
414       * PROM data for S3-0,M,C: 1111/1/0
415       * function F=A
416       * T source is ALU
417       */
418      aluf_bus__alut,
419      /**
420       * \brief 01: ALU <- T
421       * PROM data for S3-0,M,C: 1010/1/0
422       * function F=B
423       * T source is BUS
424       */
425      aluf_treg,
426      /**
427       * \brief 02: ALU <- BUS | T
428       * PROM data for S3-0,M,C: 1110/1/0
429       * function F=A|B
430       * T source is ALU
431       */
432      aluf_bus_or_t__alut,
433      /**
434       * \brief 03: ALU <- BUS & T
435       * PROM data for S3-0,M,C: 1011/1/0
436       * function F=A&B
437       * T source is BUS
438       */
439      aluf_bus_and_t,
440      /**
441       * \brief 04: ALU <- BUS ^ T
442       * PROM data for S3-0,M,C: 0110/1/0
443       * function F=A^B
444       * T source is BUS
445       */
446      aluf_bus_xor_t,
447      /**
448       * \brief 05: ALU <- BUS + 1
449       * PROM data for S3-0,M,C: 0000/0/0
450       * function F=A+1
451       * T source is ALU
452       */
453      aluf_bus_plus_1__alut,
454      /**
455       * \brief 06: ALU <- BUS - 1
456       * PROM data for S3-0,M,C: 1111/0/1
457       * function F=A-1
458       * T source is ALU
459       */
460      aluf_bus_minus_1__alut,
461      /**
462       * \brief 07: ALU <- BUS + T
463       * PROM data for S3-0,M,C: 1001/0/1
464       * function F=A+B
465       * T source is BUS
466       */
467      aluf_bus_plus_t,
468      /**
469       * \brief 10: ALU <- BUS - T
470       * PROM data for S3-0,M,C: 0110/0/0
471       * function F=A-B
472       * T source is BUS
473       */
474      aluf_bus_minus_t,
475      /**
476       * \brief 11: ALU <- BUS - T - 1
477       * PROM data for S3-0,M,C: 0110/0/1
478       * function F=A-B-1
479       * T source is BUS
480       */
481      aluf_bus_minus_t_minus_1,
482      /**
483       * \brief 12: ALU <- BUS + T + 1
484       * PROM data for S3-0,M,C: 1001/0/0
485       * function F=A+B+1
486       * T source is ALU
487       */
488      aluf_bus_plus_t_plus_1__alut,
489      /**
490       * \brief 13: ALU <- BUS + SKIP
491       * PROM data for S3-0,M,C: 0000/0/SKIP
492       * function F=A (SKIP=1) or F=A+1 (SKIP=0)
493       * T source is ALU
494       */
495      aluf_bus_plus_skip__alut,
496      /**
497       * \brief 14: ALU <- BUS & T
498       * PROM data for S3-0,M,C: 1011/1/0
499       * function F=A&B
500       * T source is ALU
501       */
502      aluf_bus_and_t__alut,
503      /**
504       * \brief 15: ALU <- BUS & ~T
505       * PROM data for S3-0,M,C: 0111/1/0
506       * function F=A&~B
507       * T source is BUS
508       */
509      aluf_bus_and_not_t,
510      /**
511       * \brief 16: ALU <- ???
512       * PROM data for S3-0,M,C: ????/?/?
513       * perhaps F=0 (0011/0/0)
514       * T source is BUS
515       */
516      aluf_undef_16,
517      /**
518       * \brief 17: ALU <- ???
519       * PROM data for S3-0,M,C: ????/?/?
520       * perhaps F=0 (0011/0/0)
521       * T source is BUS
522       */
523      aluf_undef_17
524   };
525
526   //! BUS source selection numbers
527   enum {
528      bs_read_r,                     //!< BUS source is R register
529      bs_load_r,                     //!< load R register from BUS
530      bs_no_source,                  //!< BUS is open (0177777)
531      bs_task_3,                     //!< BUS source is task specific
532      bs_task_4,                     //!< BUS source is task specific
533      bs_read_md,                     //!< BUS source is memory data
534      bs_mouse,                     //!< BUS source is mouse data
535      bs_disp,                     //!< BUS source displacement
536
537      bs_ram_read_slocation= bs_task_3,   //!< ram related: read S register
538      bs_ram_load_slocation= bs_task_4,   //!< ram related: load S register
539
540      bs_emu_read_sreg   = bs_task_3,   //!< emulator task: read S register
541      bs_emu_load_sreg   = bs_task_4,   //!< emulator task: load S register from BUS
542
543      bs_ksec_read_kstat   = bs_task_3,   //!< disk sector task: read status register
544      bs_ksec_read_kdata   = bs_task_4,   //!< disk sector task: read data register
545
546      bs_ether_eidfct      = bs_task_3,   //!< ethernet task: Ethernet input data function
547
548      bs_kwd_read_kstat   = bs_task_3,   //!< disk word task: read status register
549      bs_kwd_read_kdata   = bs_task_4      //!< disk word task: read data register
550   };
551
552   //! Function 1 numbers
553   enum {
554      f1_nop,                        //!< f1 (0000) no operation
555      f1_load_mar,                  //!< f1 (0001) load memory address register
556      f1_task,                     //!< f1 (0010) task switch
557      f1_block,                     //!< f1 (0011) block task
558      f1_l_lsh_1,                     //!< f1 (0100) left shift L once
559      f1_l_rsh_1,                     //!< f1 (0101) right shift L once
560      f1_l_lcy_8,                     //!< f1 (0110) cycle L 8 times
561      f1_const,                     //!< f1 (0111) constant from PROM
562
563      f1_task_10,                     //!< f1 (1000) task specific
564      f1_task_11,                     //!< f1 (1001) task specific
565      f1_task_12,                     //!< f1 (1010) task specific
566      f1_task_13,                     //!< f1 (1011) task specific
567      f1_task_14,                     //!< f1 (1100) task specific
568      f1_task_15,                     //!< f1 (1101) task specific
569      f1_task_16,                     //!< f1 (1110) task specific
570      f1_task_17,                     //!< f1 (1111) task specific
571
572      f1_ram_swmode      = f1_task_10,   //!< f1 (1000) ram related: switch mode to CROM/CRAM in same page
573      f1_ram_wrtram      = f1_task_11,   //!< f1 (1001) ram related: start WRTRAM cycle
574      f1_ram_rdram      = f1_task_12,   //!< f1 (1010) ram related: start RDRAM cycle
575#if   (ALTO2_UCODE_RAM_PAGES == 3)
576      f1_ram_load_rmr      = f1_task_13,   //!< f1 (1011) ram related: load the reset mode register
577#else   // ALTO2_UCODE_RAM_PAGES != 3
578      f1_ram_load_srb      = f1_task_13,   //!< f1 (1011) ram related: load the S register bank from BUS[12-14]
579#endif
580
581      f1_emu_swmode      = f1_task_10,   //!< f1 (1000) emu: switch mode; branch to ROM/RAM microcode
582      f1_emu_wrtram      = f1_task_11,   //!< f1 (1001) emu: write microcode RAM
583      f1_emu_rdram      = f1_task_12,   //!< f1 (1010) emu: read microcode RAM
584      f1_emu_load_rmr      = f1_task_13,   //!< f1 (1011) emu: load reset mode register
585                                 //!< f1 (1100) emu: undefined
586      f1_emu_load_esrb   = f1_task_15,   //!< f1 (1101) emu: load extended S register bank
587      f1_emu_rsnf         = f1_task_16,   //!< f1 (1110) emu: read serial number (Ethernet ID)
588      f1_emu_startf      = f1_task_17,   //!< f1 (1111) emu: start I/O hardware (Ethernet)
589
590      f1_ksec_strobe      = f1_task_11,   //!< f1 (1001) ksec: strobe
591      f1_ksec_load_kstat   = f1_task_12,   //!< f1 (1010) ksec: load kstat register
592      f1_ksec_increcno   = f1_task_13,   //!< f1 (1011) ksec: increment record number
593      f1_ksec_clrstat      = f1_task_14,   //!< f1 (1100) ksec: clear status register
594      f1_ksec_load_kcom   = f1_task_15,   //!< f1 (1101) ksec: load kcom register
595      f1_ksec_load_kadr   = f1_task_16,   //!< f1 (1110) ksec: load kadr register
596      f1_ksec_load_kdata   = f1_task_17,   //!< f1 (1111) ksec: load kdata register
597
598      f1_ether_eilfct      = f1_task_13,   //!< f1 (1011) ether: Ethernet input look function
599      f1_ether_epfct      = f1_task_14,   //!< f1 (1100) ether: Ethernet post function
600      f1_ether_ewfct      = f1_task_15,   //!< f1 (1101) ether: Ethernet countdown wakeup function
601
602      f1_kwd_strobe      = f1_task_11,   //!< f1 (1001) kwd: strobe
603      f1_kwd_load_kstat   = f1_task_12,   //!< f1 (1010) kwd: load kstat register
604      f1_kwd_increcno      = f1_task_13,   //!< f1 (1011) kwd: increment record number
605      f1_kwd_clrstat      = f1_task_14,   //!< f1 (1100) kwd: clear status register
606      f1_kwd_load_kcom   = f1_task_15,   //!< f1 (1101) kwd: load kcom register
607      f1_kwd_load_kadr   = f1_task_16,   //!< f1 (1110) kwd: load kadr register
608      f1_kwd_load_kdata   = f1_task_17,   //!< f1 (1111) kwd: load kdata register
609   };
610
611   //! Function 2 numbers
612   enum {
613      f2_nop,                        //!< f2 00 no operation
614      f2_bus_eq_zero,                  //!< f2 01 branch on bus equals 0
615      f2_shifter_lt_zero,               //!< f2 02 branch on shifter less than 0
616      f2_shifter_eq_zero,               //!< f2 03 branch on shifter equals 0
617      f2_bus,                        //!< f2 04 branch on BUS[6-15]
618      f2_alucy,                     //!< f2 05 branch on (latched) ALU carry
619      f2_load_md,                     //!< f2 06 load memory data
620      f2_const,                     //!< f2 07 constant from PROM
621      f2_task_10,                     //!< f2 10 task specific
622      f2_task_11,                     //!< f2 11 task specific
623      f2_task_12,                     //!< f2 12 task specific
624      f2_task_13,                     //!< f2 13 task specific
625      f2_task_14,                     //!< f2 14 task specific
626      f2_task_15,                     //!< f2 15 task specific
627      f2_task_16,                     //!< f2 16 task specific
628      f2_task_17,                     //!< f2 17 task specific
629
630      f2_emu_busodd      = f2_task_10,   //!< f2 (1000) emu: branch on bus odd
631      f2_emu_magic      = f2_task_11,   //!< f2 (1001) emu: magic shifter (MRSH 1: shifter[15]=T[0], MLSH 1: shifter[015])
632      f2_emu_load_dns      = f2_task_12,   //!< f2 (1010) emu: do novel shift (RSH 1: shifter[15]=XC, LSH 1: shifer[0]=XC)
633      f2_emu_acdest      = f2_task_13,   //!< f2 (1011) emu: destination accu
634      f2_emu_load_ir      = f2_task_14,   //!< f2 (1100) emu: load instruction register and branch
635      f2_emu_idisp      = f2_task_15,   //!< f2 (1101) emu: load instruction displacement and branch
636      f2_emu_acsource      = f2_task_16,   //!< f2 (1110) emu: source accu
637
638      f2_ksec_init      = f2_task_10,   //!< f2 (1000) ksec: branches NEXT[5-9] on WDTASKACT && WDINIT
639      f2_ksec_rwc         = f2_task_11,   //!< f2 (1001) ksec: branches NEXT[8-9] on READ/WRITE/CHECK for record
640      f2_ksec_recno      = f2_task_12,   //!< f2 (1010) ksec: branches NEXT[8-9] on RECNO[0-1]
641      f2_ksec_xfrdat      = f2_task_13,   //!< f2 (1011) ksec: branches NEXT[9] on !SEEKONLY
642      f2_ksec_swrnrdy      = f2_task_14,   //!< f2 (1100) ksec: branches NEXT[9] on !SWRDY
643      f2_ksec_nfer      = f2_task_15,   //!< f2 (1101) ksec: branches NEXT[9] on !KFER
644      f2_ksec_strobon      = f2_task_16,   //!< f2 (1110) ksec: branches NEXT[9] on STROBE
645
646      f2_ether_eodfct      = f2_task_10,   //!< f2 (1000) ether: Ethernet output data function
647      f2_ether_eosfct      = f2_task_11,   //!< f2 (1001) ether: Ethernet output start function
648      f2_ether_erbfct      = f2_task_12,   //!< f2 (1010) ether: Ethernet reset branch function
649      f2_ether_eefct      = f2_task_13,   //!< f2 (1011) ether: Ethernet end of transmission function
650      f2_ether_ebfct      = f2_task_14,   //!< f2 (1100) ether: Ethernet branch function
651      f2_ether_ecbfct      = f2_task_15,   //!< f2 (1101) ether: Ethernet countdown branch function
652      f2_ether_eisfct      = f2_task_16,   //!< f2 (1110) ether: Ethernet input start function
653
654      f2_dwt_load_ddr      = f2_task_10,   //!< f2 (1000) dwt: load display data register
655
656      f2_curt_load_xpreg   = f2_task_10,   //!< f2 (1000) curt: load x position register
657      f2_curt_load_csr   = f2_task_11,   //!< f2 (1001) curt: load cursor shift register
658
659      f2_dht_evenfield   = f2_task_10,   //!< f2 (1000) dht: load even field
660      f2_dht_setmode      = f2_task_11,   //!< f2 (1001) dht: set mode
661
662      f2_dvt_evenfield   = f2_task_10,   //!< f2 (1000) dvt: load even field
663
664      f2_kwd_init         = f2_task_10,   //!< f2 (1000) kwd: branches NEXT[5-9] on WDTASKACT && WDINIT
665      f2_kwd_rwc         = f2_task_11,   //!< f2 (1001) kwd: branches NEXT[8-9] on READ/WRITE/CHECK for record
666      f2_kwd_recno      = f2_task_12,   //!< f2 (1010) kwd: branches NEXT[8-9] on RECNO[0-1]
667      f2_kwd_xfrdat      = f2_task_13,   //!< f2 (1011) kwd: branches NEXT[9] on !SEEKONLY
668      f2_kwd_swrnrdy      = f2_task_14,   //!< f2 (1100) kwd: branches NEXT[9] on !SWRDY
669      f2_kwd_nfer         = f2_task_15,   //!< f2 (1101) kwd: branches NEXT[9] on !KFER
670      f2_kwd_strobon      = f2_task_16,   //!< f2 (1110) kwd: branches NEXT[9] on STROBE
671   };
672
673   enum {
674      p_dynamic,         //!< dynamic functions (e.g. ALU and SHIFTER operations)
675      p_latches         //!< latching function (T, L, M, R, etc. register latch)
676   };
677
678
679   /**
680    * Bit field primitives
681    * These are some inline functions to make it easier to access variable by the
682    * bit-reversed notation that the Xerox Alto documents use all over the place.
683    * Bit number 0 is the most significant there, and bit number (width - 1)
684    * is the least significant.
685    */
686
687   //! get the left shift required to access bit %to in a word of %width bits
688   static inline UINT8 A2_BITSHIFT(UINT8 width, UINT8 to) { return width - 1 - to; }
689
690   //! build a least significant bit mask for bits %from to %to (inclusive)
691   static inline UINT32 A2_BITMASK(UINT8 from, UINT8 to) { return (1ul << (to + 1 - from)) - 1; }
692
693   //! get a single bit number %bit value from %reg, a word of %width bits
694   static inline UINT8 A2_BIT8(UINT8 reg, UINT8 width, UINT8 bit) { return (reg >> A2_BITSHIFT(width,bit)) & 1; }
695
696   //! get a bit field from %reg, a word of %width bits, starting at bit %from until bit %to
697   static inline UINT8 A2_GET8(UINT8 reg, UINT8 width, UINT8 from, UINT8 to) { return (reg >> A2_BITSHIFT(width,to)) & A2_BITMASK(from,to); }
698
699   //! put a value %val into %reg, a word of %width bits, starting at bit %from until bit %to
700   static inline void A2_PUT8(UINT8& reg, UINT8 width, UINT8 from, UINT8 to, UINT8 val) {
701      UINT8 mask = A2_BITMASK(from,to) << A2_BITSHIFT(width,to);
702      reg = (reg & ~mask) | ((val << A2_BITSHIFT(width,to)) & mask);
703   }
704
705   //! get a single bit number %bit value from %reg, a word of %width bits
706   static inline UINT16 A2_BIT16(UINT16 reg, UINT8 width, UINT8 bit) { return (reg >> A2_BITSHIFT(width,bit)) & 1; }
707
708   //! get a bit field from %reg, a word of %width bits, starting at bit %from until bit %to
709   static inline UINT16 A2_GET16(UINT16 reg, UINT8 width, UINT8 from, UINT8 to) { return (reg >> A2_BITSHIFT(width,to)) & A2_BITMASK(from,to); }
710
711   //! put a value %val into %reg, a word of %width bits, starting at bit %from until bit %to
712   static inline void A2_PUT16(UINT16& reg, UINT8 width, UINT8 from, UINT8 to, UINT16 val) {
713      UINT16 mask = A2_BITMASK(from,to) << A2_BITSHIFT(width,to);
714      reg = (reg & ~mask) | ((val << A2_BITSHIFT(width,to)) & mask);
715   }
716
717   //! get a single bit number %bit value from %reg, a word of %width bits
718   static inline UINT32 A2_BIT32(UINT32 reg, UINT8 width, UINT8 bit) { return (reg >> A2_BITSHIFT(width,bit)) & 1; }
719
720   //! get a bit field from %reg, a word of %width bits, starting at bit %from until bit %to
721   static inline UINT32 A2_GET32(UINT32 reg, UINT8 width, UINT8 from, UINT8 to) { return (reg >> A2_BITSHIFT(width,to)) & A2_BITMASK(from,to); }
722
723   //! put a value %val into %reg, a word of %width bits, starting at bit %from until bit %to
724   static inline void A2_PUT32(UINT32& reg, UINT8 width, UINT8 from, UINT8 to, UINT32 val) {
725      UINT32 mask = A2_BITMASK(from,to) << A2_BITSHIFT(width,to);
726      reg = (reg & ~mask) | ((val << A2_BITSHIFT(width,to)) & mask);
727   }
728
729   //! enumeration of the micro code word bits
730   //! Note: The Alto documents enumerate bits from left (MSB = 0) to right (LSB = 31)
731   enum {
732      DRSEL0, DRSEL1, DRSEL2, DRSEL3, DRSEL4,
733      DALUF0, DALUF1, DALUF2, DALUF3,
734      DBS0, DBS1, DBS2,
735      DF1_0, DF1_1, DF1_2, DF1_3,
736      DF2_0, DF2_1, DF2_2, DF2_3,
737      LOADT,
738      LOADL,
739      NEXT0, NEXT1, NEXT2, NEXT3, NEXT4, NEXT5, NEXT6, NEXT7, NEXT8, NEXT9
740   };
741
742   //! get the RSEL value from a micro instruction word
743   static inline UINT32 MIR_RSEL(UINT32 mir) { return A2_GET32(mir, 32, DRSEL0, DRSEL4); }
744
745   //! get the ALUF value from a micro instruction word
746   static inline UINT32 MIR_ALUF(UINT32 mir) { return A2_GET32(mir, 32, DALUF0, DALUF3); }
747
748   //! get the BS value from a micro instruction word
749   static inline UINT32 MIR_BS(UINT32 mir) { return A2_GET32(mir, 32, DBS0, DBS2); }
750
751   //! get the F1 value from a micro instruction word
752   static inline UINT32 MIR_F1(UINT32 mir) { return A2_GET32(mir, 32, DF1_0, DF1_3); }
753
754   //! get the F2 value from a micro instruction word
755   static inline UINT32 MIR_F2(UINT32 mir) { return A2_GET32(mir, 32, DF2_0, DF2_3); }
756
757   //! get the T value from a micro instruction word
758   static inline UINT32 MIR_T(UINT32 mir) { return A2_BIT32(mir, 32, LOADT); }
759
760   //! get the L value from a micro instruction word
761   static inline UINT32 MIR_L(UINT32 mir) { return A2_BIT32(mir, 32, LOADL); }
762
763   //! get the NEXT value from a micro instruction word
764   static inline UINT32 MIR_NEXT(UINT32 mir) { return A2_GET32(mir, 32, NEXT0, NEXT9); }
765
766   //! get the normally accessed bank number from a bank register
767   static inline UINT16 GET_BANK_NORMAL(UINT16 breg) { return A2_GET16(breg,16,12,13); }
768
769   //! get the extended bank number (accessed via XMAR) from a bank register
770   static inline UINT16 GET_BANK_EXTENDED(UINT16 breg) { return A2_GET16(breg,16,14,15); }
771
772   //! get an ignored bit field from a control RAM address
773   static inline UINT16 GET_CRAM_IGNORE(UINT16 addr) { return A2_GET16(addr,16,0,1); }
774
775   //! get the bank select bit field from a control RAM address
776   static inline UINT16 GET_CRAM_BANKSEL(UINT16 addr) { return A2_GET16(addr,16,2,3); }
777
778   //! get the ROM/RAM flag from a control RAM address
779   static inline UINT16 GET_CRAM_RAMROM(UINT16 addr) { return A2_GET16(addr,16,4,4); }
780
781   //! get the half select flag from a control RAM address
782   static inline UINT16 GET_CRAM_HALFSEL(UINT16 addr) { return A2_GET16(addr,16,5,5); }
783
784   //! get the word address bit field from a control RAM address
785   static inline UINT16 GET_CRAM_WORDADDR(UINT16 addr)   { return A2_GET16(addr,16,6,15); }
786
787   UINT16 m_task_mpc[ALTO2_TASKS];               //!< per task micro program counter
788   UINT16 m_task_next2[ALTO2_TASKS];            //!< per task address modifier
789   attoseconds_t m_pico_time[ALTO2_TASKS];            //!< per task atto seconds executed
790   UINT8 m_task;                           //!< active task
791   UINT8 m_next_task;                        //!< next micro instruction's task
792   UINT8 m_next2_task;                        //!< next but one micro instruction's task
793   UINT16 m_mpc;                           //!< micro program counter
794   UINT32 m_mir;                           //!< micro instruction register
795
796   /**
797    * \brief current micro instruction's register selection
798    * The emulator F2s ACSOURCE and ACDEST modify this.
799    * Note: S registers are addressed by the original RSEL[0-4],
800    * even when the the emulator modifies this.
801    */
802   UINT8 m_rsel;
803
804   UINT16 m_next;                           //!< current micro instruction's next
805   UINT16 m_next2;                           //!< next micro instruction's next
806   UINT16 m_r[ALTO2_REGS];                     //!< R register file
807   UINT16 m_s[ALTO2_SREG_BANKS][ALTO2_REGS];      //!< S register file(s)
808   UINT16 m_bus;                           //!< wired-AND bus
809   UINT16 m_t;                              //!< T register
810   UINT16 m_alu;                           //!< the current ALU
811   UINT16 m_aluc0;                           //!< the current ALU carry output
812   UINT16 m_l;                              //!< L register
813   UINT16 m_shifter;                        //!< shifter output
814   UINT16 m_laluc0;                        //!< the latched ALU carry output
815   UINT16 m_m;                              //!< M register of RAM related tasks (MYL latch in the schematics)
816   UINT16 m_cram_addr;                        //!< constant RAM address
817   UINT16 m_task_wakeup;                     //!< task wakeup: bit 1<<n set if task n requesting service
818   a2func m_active_callback[ALTO2_TASKS];         //!< task activation callbacks
819
820   UINT16 m_reset_mode;                     //!< reset mode register: bit 1<<n set if task n starts in ROM
821   bool m_rdram_flag;                        //!< set by rdram, action happens on next cycle
822   bool m_wrtram_flag;                        //!< set by wrtram, action happens on next cycle
823
824   UINT8 m_s_reg_bank[ALTO2_TASKS];            //!< active S register bank per task
825   UINT8 m_bank_reg[ALTO2_TASKS];               //!< normal and extended RAM banks per task
826   bool m_ether_enable;                     //!< set to true, if the ethernet should be simulated
827   bool m_ewfct;                           //!< set by Ether task when it want's a wakeup at switch to task_mrt
828   int m_dsp_time;                           //!< display_state_machine() time accu
829   int m_dsp_state;                        //!< display_state_machine() previous state
830   int m_unload_time;                        //!< unload word time accu
831   int m_unload_word;                        //!< unload word number
832   int   m_bitclk_time;                        //!< bitclk call time accu
833   int m_bitclk_index;                        //!< bitclk index (bit number)
834
835   static const char *task_name(int task);         //!< human readable task names
836   static const char *r_name(UINT8 reg);         //!< human readable register names
837   static const char *aluf_name(UINT8 aluf);      //!< human readable ALU function names
838   static const char *bs_name(UINT8 bs);         //!< human readable bus source names
839   static const char *f1_name(UINT8 f1);         //!< human readable F1 function names
840   static const char *f2_name(UINT8 f2);         //!< human readable F2 function names
841
842   /**
843    * @brief 2KCTL PROM u3 - 256x4
844    * <PRE>
845    * PROM u3 is 256x4 type 3601-1, looks like SN74387, and it
846    * controls NEXT[6-9]', i.e. the outputs are wire-AND to NEXT
847    *
848    *           SN74387
849    *         +---+-+---+
850    *         |   +-+   |
851    *    A6  -|1      16|-  Vcc
852    *         |         |
853    *    A5  -|2      15|-  A7
854    *         |         |
855    *    A4  -|3      14|-  FE1'
856    *         |         |
857    *    A3  -|4      13|-  FE2'
858    *         |         |
859    *    A0  -|5      12|-  D0
860    *         |         |
861    *    A1  -|6      11|-  D1
862    *         |         |
863    *    A2  -|7      10|-  D2
864    *         |         |
865    *   GND  -|8       9|-  D3
866    *         |         |
867    *         +---------+
868    *
869    *
870    * It is enabled whenever the Emulator task is active and:
871    *   both F2[0] and F2[1] are 1  F2 functions 014, 015, 016, 017
872    *   F2=14 is 0                  not for F2 = 14 (load IR<-)
873    *   IR[0] is 0                  not for arithmetic group
874    *
875    * This means it controls the F2 functions 015:IDISP<- and 016:<-ACSOURCE
876    *
877    * Its address lines are:
878    *   line   pin   connected to         load swap
879    *   -------------------------------------------------------------------
880    *   A0     5     F2[2] (i.e. MIR[18]) IR[07]
881    *   A1     6     IR[01]               IR[06]
882    *   A2     7     IR[02]               IR[05]
883    *   A3     4     IR[03]               IR[04]
884    *   A4     3     IR[04]               IR[03]
885    *   A5     2     IR[05]               IR[02]
886    *   A6     1     IR[06]               IR[01]
887    *   A7     15    IR[07]               F2[2]
888    *
889    * Its data lines are:
890    *   line   pin   connected to         load
891    *   -------------------------------------------------------------------
892    *   D3     9     NEXT[06]'            NEXT[06]
893    *   D2     10    NEXT[07]'            NEXT[07]
894    *   D1     11    NEXT[08]'            NEXT[08]
895    *   D0     12    NEXT[09]'            NEXT[09]
896    *
897    * Its address lines are reversed at load time to make it easier to
898    * access it. Also both, address and data lines, are inverted.
899    * </PRE>
900    */
901   UINT8* m_ctl2k_u3;
902
903   /**
904    * @brief 2KCTL PROM u38; 82S23; 32x8 bit
905    * <PRE>
906    *
907    *            82S23
908    *         +---+-+---+
909    *         |   +-+   |
910    *    B0  -|1      16|-  Vcc
911    *         |         |
912    *    B1  -|2      15|-  EN'
913    *         |         |
914    *    B2  -|3      14|-  A4
915    *         |         |
916    *    B3  -|4      13|-  A3
917    *         |         |
918    *    B4  -|5      12|-  A2
919    *         |         |
920    *    B5  -|6      11|-  A1
921    *         |         |
922    *    B6  -|7      10|-  A0
923    *         |         |
924    *   GND  -|8       9|-  B7
925    *         |         |
926    *         +---------+
927    *
928    * Task priority encoder
929    *
930    *    line   pin    signal
931    *   -------------------------------
932    *   A0     10     CT1 (current task LSB)
933    *   A1     11     CT2
934    *   A2     12     CT4
935    *   A3     13     CT8 (current task MSB)
936    *   A4     14     0 (GND)
937    *
938    *   line   pin    signal
939    *   -------------------------------
940    *   B0     1      RDCT8'
941    *   B1     2      RDCT4'
942    *   B2     3      RDCT2'
943    *   B3     4      RDCT1'
944    *   B4     5      NEXT[09]'
945    *   B5     6      NEXT[08]'
946    *   B6     7      NEXT[07]'
947    *   B7     9      NEXT[06]'
948    * </PRE>
949    */
950   UINT8* m_ctl2k_u38;
951
952   //! output lines of the 2KCTL U38 PROM
953   enum {
954      U38_RDCT8,
955      U38_RDCT4,
956      U38_RDCT2,
957      U38_RDCT1,
958      U38_NEXT09,
959      U38_NEXT08,
960      U38_NEXT07,
961      U38_NEXT06
962   };
963
964   /**
965    * @brief 2KCTL PROM u76; P3601-1; 256x4; PC0I and PC1I decoding
966    * <PRE>
967    * Replacement for u51, which is used in 1KCTL
968    *
969    *           SN74387
970    *         +---+-+---+
971    *         |   +-+   |
972    *    A6  -|1      16|-  Vcc
973    *         |         |
974    *    A5  -|2      15|-  A7
975    *         |         |
976    *    A4  -|3      14|-  FE1'
977    *         |         |
978    *    A3  -|4      13|-  FE2'
979    *         |         |
980    *    A0  -|5      12|-  D0
981    *         |         |
982    *    A1  -|6      11|-  D1
983    *         |         |
984    *    A2  -|7      10|-  D2
985    *         |         |
986    *   GND  -|8       9|-  D3
987    *         |         |
988    *         +---------+
989    *
990    *   input line    signal
991    *   ----------------------------
992    *   A7    15      EMACT'
993    *   A6    1       F1(0)
994    *   A5    2       F1(1)'
995    *   A4    3       F1(2)'
996    *   A3    4       F1(3)'
997    *   A2    7       0 (GND)
998    *   A1    6       PC1O
999    *   A0    5       PC0O
1000    *
1001    *   output line   signal
1002    *   ----------------------------
1003    *   D0     12     PC1T
1004    *   D1     11     PC1F
1005    *   D2     10     PC0T
1006    *   D3     9      PC0F
1007    *
1008    * The outputs are connected to a dual 4:1 demultiplexer 74S153, so that
1009    * depending on NEXT01' and RESET the following signals are passed through:
1010    *
1011    *   RESET  NEXT[01]'  PC0I    PC1I
1012    *   --------------------------------------
1013    *   0      0          PC0T    PC1T
1014    *   0      1          PC0F    PC1F
1015    *   1      0          PC0I4   T14 (?)
1016    *   1      1          -"-     -"-
1017    *
1018    * This selects the microcode "page" to jump to on SWMODE (F1 = 010)
1019    * depending on the current NEXT[01]' level.
1020    * </PRE>
1021    */
1022   UINT8* m_ctl2k_u76;
1023
1024   /**
1025    * @brief 3k CRAM PROM a37
1026    */
1027   UINT8* m_cram3k_a37;
1028
1029   /**
1030    * @brief memory addressing PROM a64
1031    */
1032   UINT8* m_madr_a64;
1033
1034   /**
1035    * @brief memory addressing PROM a65
1036    */
1037   UINT8* m_madr_a65;
1038
1039   /**
1040    * @brief unused PROM a90
1041    */
1042   UINT8* m_madr_a90;
1043
1044   /**
1045    * @brief unused PROM a91
1046    */
1047   UINT8* m_madr_a91;
1048
1049   //! no operating function to put in the m_bs, m_f1 and m_f2 slots
1050   void noop() {}
1051
1052   //! per task bus source function pointers, early (0) and late (1)
1053   a2func m_bs[2][ALTO2_TASKS][ALTO2_BUSSRC];
1054   void set_bs(UINT8 task, UINT8 fn, a2func f0, a2func f1) {
1055      m_bs[0][task][fn] = f0 ? f0 : &alto2_cpu_device::noop;
1056      m_bs[1][task][fn] = f1 ? f1 : &alto2_cpu_device::noop;
1057   }
1058
1059   //! per task f1 function pointers, early (0) and late (1)
1060   a2func m_f1[2][ALTO2_TASKS][ALTO2_F1MAX];
1061   void set_f1(UINT8 task, UINT8 fn, a2func f0, a2func f1) {
1062      m_f1[0][task][fn] = f0 ? f0 : &alto2_cpu_device::noop;
1063      m_f1[1][task][fn] = f1 ? f1 : &alto2_cpu_device::noop;
1064   }
1065
1066   //! per task f2 function pointers, early (0) and late (1)
1067   a2func m_f2[2][ALTO2_TASKS][ALTO2_F2MAX];
1068   void set_f2(UINT8 task, UINT8 fn, a2func f0, a2func f1) {
1069      m_f2[0][task][fn] = f0 ? f0 : &alto2_cpu_device::noop;
1070      m_f2[1][task][fn] = f1 ? f1 : &alto2_cpu_device::noop;
1071   }
1072
1073   bool m_ram_related[ALTO2_TASKS];            //!< set when task is RAM related
1074
1075   UINT64 m_cycle;                           //!< number of cycles executed in the current slice
1076
1077   UINT64 cycle() { return m_cycle; }            //!< return the current CPU cycle
1078   UINT64 ntime() { return m_cycle*ALTO2_UCYCLE/1000; }   //!< return the current nano seconds
1079
1080   void hard_reset();                        //!< reset the various registers
1081   int soft_reset();                        //!< soft reset
1082
1083   void fn_bs_bad_0();                        //! bs dummy early function
1084   void fn_bs_bad_1();                        //! bs dummy late function
1085
1086   void fn_f1_bad_0();                        //! f1 dummy early function
1087   void fn_f1_bad_1();                        //! f1 dummy late function
1088
1089   void fn_f2_bad_0();                        //! f2 dummy early function
1090   void fn_f2_bad_1();                        //! f2 dummy late function
1091
1092   DECLARE_READ16_MEMBER( noop_r );            //!< read open bus (0177777)
1093   DECLARE_WRITE16_MEMBER( noop_w );            //!< write open bus
1094
1095   DECLARE_READ16_MEMBER( bank_reg_r );         //!< read bank register in memory mapped I/O range
1096   DECLARE_WRITE16_MEMBER( bank_reg_w );         //!< write bank register in memory mapped I/O range
1097
1098   void bs_read_r_0();                        //!< bs_read_r early: drive bus by R register
1099   void bs_load_r_0();                        //!< bs_load_r early: load R places 0 on the BUS
1100   void bs_load_r_1();                        //!< bs_load_r late: load R from SHIFTER
1101   void bs_read_md_0();                     //!< bs_read_md early: drive BUS from read memory data
1102   void bs_mouse_0();                        //!< bs_mouse early: drive bus by mouse
1103   void bs_disp_0();                        //!< bs_disp early: drive bus by displacement (which?)
1104   void f1_load_mar_1();                     //!< f1_load_mar late: load memory address register
1105   void f1_task_0();                        //!< f1_task early: task switch
1106   void f2_bus_eq_zero_1();                  //!< f2_bus_eq_zero late: branch on bus equals zero
1107   void f2_shifter_lt_zero_1();               //!< f2_shifter_lt_zero late: branch on shifter less than zero
1108   void f2_shifter_eq_zero_1();               //!< f2_shifter_eq_zero late: branch on shifter equals zero
1109   void f2_bus_1();                        //!< f2_bus late: branch on bus bits BUS[6-15]
1110   void f2_alucy_1();                        //!< f2_alucy late: branch on latched ALU carry
1111   void f2_load_md_1();                     //!< f2_load_md late: load memory data
1112
1113   UINT8* m_alu_a10;                        //!< ALU function to 74181 operation lookup PROM
1114   UINT32 alu_74181(UINT32 a, UINT32 b, UINT8 smc);
1115
1116   void rdram();                           //!< read the microcode ROM/RAM halfword
1117   void wrtram();                           //!< write the microcode RAM from M register and ALU
1118
1119   // ************************************************
1120   // ram related stuff
1121   // ************************************************
1122   void bs_read_sreg_0();                     //!< bs_read_sreg early: drive bus by S register or M (MYL), if rsel is = 0
1123   void bs_load_sreg_0();                     //!< bs_load_sreg early: load S register puts garbage on the bus
1124   void bs_load_sreg_1();                     //!< bs_load_sreg late: load S register from M
1125   void branch_ROM(const char *from, int page);   //!< branch to ROM page
1126   void branch_RAM(const char *from, int page);   //!< branch to RAM page
1127   void f1_swmode_1();                        //!< f1_swmode early: switch to micro program counter BUS[6-15] in other bank
1128   void f1_wrtram_1();                        //!< f1_wrtram late: start WRTRAM cycle
1129   void f1_rdram_1();                        //!< f1_rdram late: start RDRAM cycle
1130#if   (ALTO2_UCODE_RAM_PAGES == 3)
1131   void f1_load_rmr_1();                     //!< f1_load_rmr late: load the reset mode register
1132#else   // ALTO2_UCODE_RAM_PAGES != 3
1133   void f1_load_srb_1();                     //!< f1_load_srb late: load the S register bank from BUS[12-14]
1134#endif
1135   void init_ram(int task);                  //!< called by RAM related tasks
1136   void exit_ram();
1137
1138   // ************************************************
1139   // memory mapped i/o stuff
1140   // ************************************************
1141   /**
1142    * @brief get printer paper ready bit
1143    * Paper ready bit. 0 when the printer is ready for a paper scrolling operation.
1144    */
1145   static inline UINT16 GET_PPRDY(UINT16 utilin) { return A2_GET16(utilin,16,0,0); }
1146
1147   /** @brief put printer paper ready bit */
1148   static inline void PUT_PPRDY(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,0,0,val); }
1149
1150   /**
1151    * @brief get printer check bit
1152    * Printer check bit bit. Should the printer find itself in an abnormal state,
1153    * it sets this bit to 0
1154    */
1155   static inline UINT16 GET_PCHECK(UINT16 utilin) { return A2_GET16(utilin,16,1,1); }
1156
1157   /** @brief put printer check bit */
1158   static inline void PUT_PCHECK(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,1,1,val); }
1159
1160   /** @brief get unused bit 2 */
1161   static inline UINT16 GET_UNUSED_2(UINT16 utilin) { return A2_GET16(utilin,16,2,2); }
1162
1163   /** @brief put unused bit 2 */
1164   static inline void PUT_UNUSED_2(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,2,2,val); }
1165
1166   /**
1167    * @brief get printer daisy ready bit
1168    * Daisy ready bit. 0 when the printer is ready to print a character.
1169    */
1170   static inline UINT16 GET_PCHRDY(UINT16 utilin) { return A2_GET16(utilin,16,3,3); }
1171
1172   /** @brief put printer daisy ready bit */
1173   static inline void PUT_PCHRDY(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,3,3,val); }
1174
1175   /**
1176    * @brief get printer carriage ready bit
1177    * Carriage ready bit. 0 when the printer is ready for horizontal positioning.
1178    */
1179   static inline UINT16 GET_PCARRDY(UINT16 utilin) { return A2_GET16(utilin,16,4,4); }
1180
1181   /** @brief put printer carriage ready bit */
1182   static inline void PUT_PCARRDY(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,4,4,val); }
1183
1184   /**
1185    * @brief get printer ready bit
1186    * Ready bit. Both this bit and the appropriate other ready bit (carriage,
1187    * daisy, etc.) must be 0 before attempting any output operation.
1188    */
1189   static inline UINT16 GET_PREADY(UINT16 utilin) { return A2_GET16(utilin,16,5,5); }
1190
1191   /** @brief put printer ready bit */
1192   static inline void PUT_PREADY(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,5,5,val); }
1193
1194   /**
1195    * @brief memory configuration switch
1196    */
1197   static inline UINT16 GET_MEMCONFIG(UINT16 utilin) { return A2_GET16(utilin,16,6,6); }
1198
1199   /** @brief put memory configuration switch */
1200   static inline void PUT_MEMCONFIG(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,6,6,val); }
1201
1202   /** @brief get unused bit 7 */
1203   static inline UINT16 GET_UNUSED_7(UINT16 utilin) { return A2_GET16(utilin,16,7,7); }
1204   /** @brief put unused bit 7 */
1205   static inline void PUT_UNUSED_7(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,7,7,val); }
1206
1207   /** @brief get key set key 0 */
1208   static inline UINT16 GET_KEYSET_KEY0(UINT16 utilin) { return A2_GET16(utilin,16,8,8); }
1209   /** @brief put key set key 0 */
1210   static inline void PUT_KEYSET_KEY0(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,8,8,val); }
1211
1212   /** @brief get key set key 1 */
1213   static inline UINT16 GET_KEYSET_KEY1(UINT16 utilin) { return A2_GET16(utilin,16,9,9); }
1214   /** @brief put key set key 1 */
1215   static inline void PUT_KEYSET_KEY1(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,9,9,val); }
1216
1217   /** @brief get key set key 2 */
1218   static inline UINT16 GET_KEYSET_KEY2(UINT16 utilin) { return A2_GET16(utilin,16,10,10); }
1219   /** @brief put key set key 2 */
1220   static inline void PUT_KEYSET_KEY2(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,10,10,val); }
1221
1222   /** @brief get key set key 3 */
1223   static inline UINT16 GET_KEYSET_KEY3(UINT16 utilin) { return A2_GET16(utilin,16,11,11); }
1224   /** @brief put key set key 3 */
1225   static inline void PUT_KEYSET_KEY3(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,11,11,val); }
1226
1227   /** @brief get key set key 4 */
1228   static inline UINT16 GET_KEYSET_KEY4(UINT16 utilin) { return A2_GET16(utilin,16,12,12); }
1229   /** @brief put key set key 4 */
1230   static inline void PUT_KEYSET_KEY4(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,12,12,val); }
1231
1232   /** @brief get mouse red button bit */
1233   static inline UINT16 GET_MOUSE_RED(UINT16 utilin) { return A2_GET16(utilin,16,13,13); }
1234   /** @brief put mouse red button bit */
1235   static inline void PUT_MOUSE_RED(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,13,13,val); }
1236
1237   /** @brief get mouse blue button bit */
1238   static inline UINT16 GET_MOUSE_BLUE(UINT16 utilin) { return A2_GET16(utilin,16,14,14); }
1239   /** @brief put mouse blue button bit */
1240   static inline void PUT_MOUSE_BLUE(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,14,14,val); }
1241
1242   /** @brief get mouse yellow button bit */
1243   static inline UINT16 GET_MOUSE_YELLOW(UINT16 utilin) { return A2_GET16(utilin,16,15,15); }
1244   /** @brief put mouse yellow button bit */
1245   static inline void PUT_MOUSE_YELLOW(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,15,15,val); }
1246
1247   /** @brief put mouse bits */
1248   static inline void PUT_MOUSE(UINT16& utilin, UINT16 val) { A2_PUT16(utilin,16,13,15,val); }
1249
1250   /**
1251    * @brief printer paper strobe bit
1252    * Paper strobe bit. Toggling this bit causes a paper scrolling operation.
1253    */
1254   static inline UINT16 GET_PPPSTR(UINT16 utilout) { return A2_GET16(utilout,16,0,0); }
1255
1256   /**
1257    * @brief printer retstore bit
1258    * Restore bit. Toggling this bit resets the printer (including clearing
1259    * the "check" condition if present) and moves the carriage to the
1260    * left margin.
1261    */
1262   static inline UINT16 GET_PREST(UINT16 utilout) { return A2_GET16(utilout,16,1,1); }
1263
1264   /**
1265    * @brief printer ribbon bit
1266    * Ribbon bit. When this bit is 1 the ribbon is up (in printing
1267    * position); when 0, it is down.
1268    */
1269   static inline UINT16 GET_PRIB(UINT16 utilout) { return A2_GET16(utilout,16,2,2); }
1270
1271   /**
1272    * @brief printer daisy strobe bit
1273    * Daisy strobe bit. Toggling this bit causes a character to be printed.
1274    */
1275   static inline UINT16 GET_PCHSTR(UINT16 utilout) { return A2_GET16(utilout,16,3,3); }
1276
1277   /**
1278    * @brief printer carriage strobe bit
1279    * Carriage strobe bit. Toggling this bit causes a horizontal position operation.
1280    */
1281   static inline UINT16 GET_PCARSTR(UINT16 utilout) { return A2_GET16(utilout,16,4,4); }
1282
1283   /**
1284    * @brief printer data
1285    * Argument to various output operations:
1286    * 1. Printing characters. When the daisy bit is toggled bits 9-15 of this field
1287    * are interpreted as an ASCII character code to be printed (it should be noted
1288    * that all codes less than 040 print as lower case "w").
1289    * 2. For paper and carriage operations the field is interpreted as a displacement
1290    * (-1024 to +1023), in units of 1/48 inch for paper and 1/60 inch for carriage.
1291    * Positive is down or to the right, negative up or to the left. The value is
1292    * represented as sign-magnitude (i.e., bit 5 is 1 for negative numbers, 0 for
1293    * positive; bits 6-15 are the absolute value of the number).
1294    */
1295   static inline UINT16 GET_PDATA(UINT16 utilout) { return A2_GET16(utilout,16,5,15); }
1296
1297   /** @brief miscellaneous hardware registers in the memory mapped I/O range */
1298   struct {
1299      UINT16 eia;            //!< the EIA port at 0177001
1300      UINT16 utilout;         //!< the UTILOUT port at 0177016 (active-low outputs) */
1301      UINT16 xbus[4];         //!< the XBUS port at 0177020 to 0177023
1302      UINT16 utilin;         //!< the UTILIN port at 0177030 to 0177033 (same value on all addresses)
1303   }   m_hw;
1304
1305   DECLARE_READ16_MEMBER( utilin_r );         //!< read an UTILIN address
1306   DECLARE_READ16_MEMBER( utilout_r );         //!< read the UTILOUT address
1307   DECLARE_WRITE16_MEMBER( utilout_w );      //!< write the UTILOUT address
1308   DECLARE_READ16_MEMBER( xbus_r );         //!< read an XBUS address
1309   DECLARE_WRITE16_MEMBER( xbus_w );         //!< write an XBUS address (?)
1310   void init_hw();                        //!< initialize miscellaneous hardware
1311   void exit_hw();                        //!< deinitialize miscellaneous hardware
1312
1313   // ************************************************
1314   // keyboard stuff
1315   // ************************************************
1316   struct {
1317      UINT16 bootkey;                     //!< boot key - key code pressed before power on
1318      UINT16 matrix[4];                  //!< a bit map of the keys pressed (ioports ROW0 ... ROW3)
1319   }   m_kbd;
1320   DECLARE_READ16_MEMBER( kbd_ad_r );         //!< read the keyboard matrix
1321   void init_kbd(UINT16 bootkey = 0177777);   //!< initialize the keyboard hardware, optinally set the boot key
1322   void exit_kbd();                     //!< deinitialize the keyboard hardware
1323
1324   // ************************************************
1325   // mouse stuff
1326   // ************************************************
1327   /**
1328    * @brief PROM madr.a32 contains a lookup table to translate mouse motions
1329    *
1330    * <PRE>
1331    * The 4 mouse motion signals MX1, MX2, MY1, and MY2 are connected
1332    * to a 256x4 PROM's (3601, SN74387) address lines A0, A2, A4, and A6.
1333    * The previous (latched) state of the 4 signals is connected to the
1334    * address lines A1, A3, A5, and A7.
1335    *
1336    *                  SN74387
1337    *               +---+--+---+
1338    *               |   +--+   |
1339    *  MY2     A6  -|1       16|-  Vcc
1340    *               |          |
1341    *  LMY1    A5  -|2       15|-  A7     LMY2
1342    *               |          |
1343    *  MY1     A4  -|3       14|-  FE1'   0
1344    *               |          |
1345    *  LMX2    A3  -|4       13|-  FE2'   0
1346    *               |          |
1347    *  MX1     A0  -|5       12|-  D0     BUS[12]
1348    *               |          |
1349    *  LMX1    A1  -|6       11|-  D1     BUS[13]
1350    *               |          |
1351    *  MX2     A2  -|7       10|-  D2     BUS[14]
1352    *               |          |
1353    *         GND  -|8        9|-  D3     BUS[15]
1354    *               |          |
1355    *               +----------+
1356    *
1357    * A motion to the west will first toggle MX2, then MX1.
1358    * sequence: 04 -> 0d -> 0b -> 02
1359    * A motion to the east will first toggle MX1, then MX2.
1360    * sequence: 01 -> 07 -> 0e -> 08
1361    *
1362    * A motion to the north will first toggle MY2, then MY1.
1363    * sequence: 40 -> d0 -> b0 -> 20
1364    * A motion to the south will first toggle MY1, then MY2.
1365    * sequence: 10 -> 70 -> e0 -> 80
1366    *
1367    * This dump is from PROM madr.a32:
1368    * 0000: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1369    * 0020: 003,015,005,003,005,003,003,015,015,003,003,005,003,005,015,003,
1370    * 0040: 011,001,016,011,016,011,011,001,001,011,011,016,011,016,001,011,
1371    * 0060: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1372    * 0100: 011,001,016,011,016,011,011,001,001,011,011,016,011,016,001,011,
1373    * 0120: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1374    * 0140: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1375    * 0160: 003,015,005,003,005,003,003,015,015,003,003,005,003,005,015,003,
1376    * 0200: 003,015,005,003,005,003,003,015,015,003,003,005,003,005,015,003,
1377    * 0220: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1378    * 0240: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1379    * 0260: 011,001,016,011,016,011,011,001,001,011,011,016,011,016,001,011,
1380    * 0300: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017,
1381    * 0320: 011,001,016,011,016,011,011,001,001,011,011,016,011,016,001,011,
1382    * 0340: 003,015,005,003,005,003,003,015,015,003,003,005,003,005,015,003,
1383    * 0360: 017,007,013,017,013,017,017,007,007,017,017,013,017,013,007,017
1384    * </PRE>
1385    */
1386   UINT8* m_madr_a32;
1387
1388   //! mouse context
1389   struct {
1390      int x;                              //!< current X coordinate
1391      int y;                              //!< current Y coordinate
1392      int dx;                              //!< destination X coordinate (real mouse X)
1393      int dy;                              //!< destination Y coordinate (real mouse Y)
1394      UINT8 latch;                        //!< current latch value
1395      UINT8 phase;                        //!< current read latch phase
1396   }   m_mouse;
1397
1398   UINT16 mouse_read();                     //!< return the mouse motion flags
1399   void init_mouse();                        //!< initialize the mouse context to useful values
1400   void exit_mouse();                        //!< deinitialize the mouse
1401
1402   // ************************************************
1403   // disk controller stuff
1404   // ************************************************
1405   diablo_hd_device* m_drive[2];      //!< two diablo_hd_device drives
1406
1407   //! disk controller context
1408   struct {
1409      UINT8 drive;               //!< selected drive from KADDR[14] (written to data out with SENDADR)
1410      UINT16 kaddr;               //!< A[0-15] disk hardware address (sector, cylinder, head, drive, restore)
1411      UINT16 kadr;               //!< C[0-15] with read/write/check modes for header, label and data
1412      UINT16 kstat;               //!< S[0-15] disk status
1413      UINT16 kcom;               //!< disk command (5 bits kcom[1-5])
1414      UINT8 krecno;               //!< record number (2 bits indexing header, label, data, -/-)
1415      UINT8 egate;               //!< current erase gate signal to the DIABLO hd
1416      UINT8 wrgate;               //!< current write gate signal to the DIABLO hd
1417      UINT8 rdgate;               //!< current read gate signal to the DIABLO hd
1418      UINT32 shiftin;               //!< input shift register
1419      UINT32 shiftout;            //!< output shift register
1420      UINT32 datain;               //!< disk data in latch
1421      UINT32 dataout;               //!< disk data out latch
1422      UINT8 krwc;                  //!< read/write/check for current record
1423      UINT8 kfer;                  //!< disk fatal error signal state
1424      UINT8 wdtskena;               //!< disk word task enable (active low)
1425      UINT8 wddone;               //!< previous state of WDDONE
1426      UINT8 wdinit0;               //!< disk word task init at the early microcycle
1427      UINT8 wdinit;               //!< disk word task init at the late microcycle
1428      UINT8 strobe;               //!< strobe (still) active
1429      emu_timer* strobon_timer;      //!< set strobe on timer
1430      UINT8 bitclk;               //!< current bitclk state (either crystal clock, or rdclk from the drive)
1431#if   USE_BITCLK_TIMER
1432      emu_timer* bitclk_timer;      //!< bit clock timer
1433#else
1434      int bitclk_time;            //!< time in clocks per bit
1435#endif
1436      UINT8 datin;               //!< current datin from the drive
1437      UINT8 bitcount;               //!< bit counter
1438      UINT8 carry;               //!< carry output of the bitcounter
1439      UINT8 seclate;               //!< sector late (monoflop output)
1440      emu_timer* seclate_timer;      //!< sector late timer
1441      UINT8 seekok;               //!< seekok state (SKINC' & LAI' & ff_44a.Q')
1442      UINT8 ok_to_run;            //!< ok to run signal (set to 1 some time after reset)
1443      emu_timer* ok_to_run_timer;      //!< ok to run timer
1444      UINT8 ready_mf31a;            //!< ready monoflop 31a
1445      emu_timer* ready_timer;         //!< ready timer
1446      UINT8 seclate_mf31b;         //!< seclate monoflop 31b
1447      jkff_t ff_21a;               //!< JK flip-flop 21a (sector task)
1448      jkff_t ff_21a_old;            //!< -"- previous state
1449      jkff_t ff_21b;               //!< JK flip-flop 21b (sector task)
1450      jkff_t ff_22a;               //!< JK flip-flop 22a (sector task)
1451      jkff_t ff_22b;               //!< JK flip-flop 22b (sector task)
1452      jkff_t ff_43b;               //!< JK flip-flop 43b (word task)
1453      jkff_t ff_53a;               //!< JK flip-flop 53a (word task)
1454      jkff_t ff_43a;               //!< JK flip-flop 43a (word task)
1455      jkff_t ff_53b;               //!< brief JK flip-flop 53b (word task)
1456      jkff_t ff_44a;               //!< JK flip-flop 44a (LAI' clocked)
1457      jkff_t ff_44b;               //!< JK flip-flop 44b (CKSUM)
1458      jkff_t ff_45a;               //!< JK flip-flop 45a (ready latch)
1459      jkff_t ff_45b;               //!< JK flip-flop 45b (seqerr latch)
1460   }   m_dsk;
1461
1462   jkff_t m_sysclka0[4];            //!< simulate previous sysclka
1463   jkff_t m_sysclka1[4];            //!< simulate current sysclka
1464   jkff_t m_sysclkb0[4];            //!< simulate previous sysclkb
1465   jkff_t m_sysclkb1[4];            //!< simulate current sysclkb
1466   //! lookup JK flip-flop state change from s0 to s1
1467   inline jkff_t update_jkff(UINT8 s0, UINT8 s1);
1468
1469   void kwd_timing(int bitclk, int datin, int block);   //!< disk word timing
1470   TIMER_CALLBACK_MEMBER( disk_seclate );         //!< timer callback to take away the SECLATE pulse (monoflop)
1471   TIMER_CALLBACK_MEMBER( disk_ok_to_run );      //!< timer callback to take away the OK TO RUN pulse (reset)
1472   TIMER_CALLBACK_MEMBER( disk_strobon );         //!< timer callback to pulse the STROBE' signal to the drive
1473   TIMER_CALLBACK_MEMBER( disk_ready_mf31a );      //!< timer callback to change the READY monoflop 31a
1474#if   USE_BITCLK_TIMER
1475   TIMER_CALLBACK_MEMBER( disk_bitclk );         //!< callback to update the disk controller with a new bitclk
1476#else
1477   void disk_bitclk(void *ptr, int arg);         //!< function to update the disk controller with a new bitclk
1478#endif
1479   void disk_block(int task);                  //!< called if one of the disk tasks (task_kwd or task_ksec) blocks
1480   void bs_read_kstat_0();                     //!< bs_read_kstat early: bus driven by disk status register KSTAT
1481   void bs_read_kdata_0();                     //!< bs_read_kdata early: bus driven by disk data register KDATA input
1482   void f1_strobe_1();                        //!< f1_strobe late: initiates a disk seek
1483   void f1_load_kstat_1();                     //!< f1_load_kstat late: load disk status register
1484   void f1_load_kdata_1();                     //!< f1_load_kdata late: load data out register, or the disk address register
1485   void f1_increcno_1();                     //!< f1_increcno late: advances shift registers holding KADR
1486   void f1_clrstat_1();                     //!< f1_clrstat late: reset all error latches
1487   void f1_load_kcom_1();                     //!< f1_load_kcom late: load the KCOM register from bus
1488   void f1_load_kadr_1();                     //!< f1_load_kadr late: load the KADR register from bus
1489   void f2_init_1();                        //!< f2_init late: branch on disk word task active and init
1490   void f2_rwc_1();                        //!< f2_rwc late: branch on read/write/check state of the current record
1491   void f2_recno_1();                        //!< f2_recno late: branch on the current record number by a lookup table
1492   void f2_xfrdat_1();                        //!< f2_xfrdat late: branch on the data transfer state
1493   void f2_swrnrdy_1();                     //!< f2_swrnrdy late: branch on the disk ready signal
1494   void f2_nfer_1();                        //!< f2_nfer late: branch on the disk fatal error condition
1495   void f2_strobon_1();                     //!< f2_strobon late: branch on the seek busy status
1496   void init_disk();                        //!< initialize the disk context
1497   void exit_disk();                        //!< deinitialize the disk context
1498
1499   // ************************************************
1500   // display stuff
1501   // ************************************************
1502   /**
1503    * @brief structure of the display context
1504    *
1505    * Schematics of the task clear and wakeup signal generators
1506    * <PRE>
1507    * A quote (') appended to a signal name means inverted signal.
1508    *
1509    *  AND |     NAND|      NOR |       FF | Q    N174
1510    * -----+--- -----+---  -----+---  -----+---   -----
1511    *  0 0 | 0   0 0 | 1    0 0 | 1    S'\0| 1    delay
1512    *  0 1 | 0   0 1 | 1    0 1 | 0    R'\0| 0
1513    *  1 0 | 0   1 0 | 1    1 0 | 0
1514    *  1 1 | 1   1 1 | 0    1 1 | 0
1515    *
1516    *
1517    *                                                       DVTAC'
1518    *                                                      >-------·  +-----+
1519    *                                                              |  |  FF |
1520    * VBLANK'+----+ DELVBLANK' +---+  DELVBLANK   +----+           ·--|S'   |
1521    * >------|N174|------+-----|inv|--------------|NAND| VBLANKPULSE  |     |              WAKEDVT'
1522    *        +----+      |     +---+              |    o--+-----------|R'  Q|---------------------->
1523    *                    |                      ·-|    |  |           |     |
1524    *        +----+      |     DDELVBLANK'      | +----+  |           +-----+
1525    *      ·-|N174|-----------------------------·         |      +---+
1526    *      | +----+      |                                +------oAND|
1527    *      |             |                      DSP07.01  |      |   o----------·
1528    *      ·-------------·                      >---------|------o   |          |
1529    *                                                     |      +---+          |
1530    *                                                     |                     |
1531    *                                                     | +-----+             |
1532    *                                                     | |  FF |             |  +-----+
1533    *        DHTAC'       +---+                           | |     |             |  |  FF |
1534    *      >--------------oNOR|  *07.25       +----+      ·-|S'   |   DHTBLK'   |  |     |
1535    *        BLOCK'       |   |---------------|NAND|        |    Q|--+----------|--|S1'  | WAKEDHT'
1536    *      >--------------o   |     DCSYSCLK  |    o--------|R'   |  | >--------|--|S2' Q|--------->
1537    *                     +---+     >---------|    |        +-----+  |  DHTAC'  ·--|R'   |
1538    *                                         +----+                 |             +-----+
1539    *                                                   ·------------·
1540    *                                                   |
1541    *        DWTAC'       +---+                         |   +-----+
1542    *      >--------------oNOR|  *07.26 +----+          |   |  FF |
1543    *        BLOCK'       |   |---------|NAND| DSP07.01 |   |     |
1544    *      >--------------o   | DCSYSCLK|    o----------|---|S1'  | DWTCN' +---+        DWTCN
1545    *                     +---+ >-------|    |          ·---|S2' Q|--------|inv|-----------+----
1546    *                                   +----+          ·---|R'   |        +---+           |
1547    *                                                   |   +-----+                        |
1548    *                 SCANEND     +----+                |                                  |
1549    *               >-------------|NAND|  CLRBUF'       |           .----------------------·
1550    *                 DCLK        |    o----------------·           |
1551    *               >-------------|    |                            |  +-----+
1552    *                             +----+                            ·--| NAND|
1553    *                                                       STOPWAKE'  |     |preWake +----+ WAKEDWT'
1554    *                                                      >-----------|     o--------|N174|--------->
1555    *                                                        VBLANK'   |     |        +----+
1556    *                                                      >-----------|     |
1557    *                                                                  +-----+
1558    *                                                     a40c
1559    *                                        VBLANKPULSE +----+
1560    *                                       -------------|NAND|
1561    *                                                    |    o--·
1562    *                                                 ·--|    |  |
1563    *                                                 |  +----+  |
1564    *                                                 ·----------|-·
1565    *                                                 ·----------· |
1566    *        CURTAC'      +---+                       |  +----+    |     a20d
1567    *      >--------------oNOR|  *07.27 +----+        ·--|NAND|    |    +----+
1568    *        BLOCK'       |   |---------|NAND| DSP07.07  |    o----+----o NOR| preWK  +----+ WAKECURT'
1569    *      >--------------o   | DCSYSCLK|    o-----------|    |         |    |--------|N174|--------->
1570    *                     +---+ >-------|    |           +----+    +----o    |        +----+
1571    *                                   +----+            a40d     |    +----+
1572    *                                          a30c                |
1573    *                              CURTAC'    +----+               |
1574    *                            >------------|NAND|    DSP07.03   |
1575    *                                         |    o--+------------·
1576    *                                      ·--|    |  |
1577    *                                      |  +----+  |
1578    *                                      ·----------|-·
1579    *                                      ·----------· |
1580    *                                      |  +----+    |
1581    *                                      ·--|NAND|    |
1582    *                              CLRBUF'    |    o----·
1583    *                            >------------|    |
1584    *                                         +----+
1585    *                                          a30d
1586    * </PRE>
1587    */
1588   struct {
1589      UINT16 hlc;                     //!< horizontal line counter
1590      UINT8 a63;                     //!< most recent value read from the PROM a63
1591      UINT8 a66;                     //!< most recent value read from the PROM a66
1592      UINT16 setmode;                  //!< value written by last SETMODE<-
1593      UINT16 inverse;                  //!< set to 0xffff if line is inverse, 0x0000 otherwise
1594      UINT8 halfclock;               //!< set 0 for normal pixel clock, 1 for half pixel clock
1595      UINT8 clr;                     //!< set non-zero if any of VBLANK or HBLANK is active (a39a 74S08)
1596      UINT16 fifo[ALTO2_DISPLAY_FIFO];   //!< display word fifo
1597      UINT8 fifo_wr;                  //!< fifo input pointer (4-bit)
1598      UINT8 fifo_rd;                  //!< fifo output pointer (4-bit)
1599      UINT8 dht_blocks;               //!< set non-zero, if the DHT executed BLOCK
1600      UINT8 dwt_blocks;               //!< set non-zero, if the DWT executed BLOCK
1601      UINT8 curt_blocks;               //!< set non-zero, if the CURT executed BLOCK
1602      UINT8 curt_wakeup;               //!< set non-zero, if CURT wakeups are generated
1603      UINT16 vblank;                  //!< most recent HLC with VBLANK still high (11-bit)
1604      UINT16 xpreg;                  //!< cursor cursor x position register (10-bit)
1605      UINT16 csr;                     //!< cursor shift register (16-bit)
1606      UINT32 curword;                  //!< helper: first cursor word in current scanline
1607      UINT32 curdata;                  //!< helper: shifted cursor data (32-bit)
1608      UINT16 *raw_bitmap;               //!< array of words of the raw bitmap that is displayed
1609      UINT16 **scanline;               //!< array of pointers to the scanlines
1610   }   m_dsp;
1611
1612   /**
1613    * @brief PROM a38 contains the STOPWAKE' and MBEMBPTY' signals for the FIFO
1614    * <PRE>
1615    * The inputs to a38 are the UNLOAD counter RA[0-3] and the DDR<- counter
1616    * WA[0-3], and the designer decided to reverse the address lines :-)
1617    *
1618    *   a38  counter FIFO counter
1619    *   --------------------------
1620    *    A0  RA[0]   fifo_rd
1621    *    A1  RA[1]
1622    *    A2  RA[2]
1623    *    A3  RA[3]
1624    *    A4  WA[0]   fifo_wr
1625    *    A5  WA[1]
1626    *    A6  WA[2]
1627    *    A7  WA[3]
1628    *
1629    * Only two bits of a38 are used:
1630    *    O1 (002) = STOPWAKE'
1631    *    O3 (010) = MBEMPTY'
1632    * </PRE>
1633    */
1634   UINT8* m_disp_a38;
1635
1636   //! output bits of PROM A38
1637   enum {
1638      A38_STOPWAKE   = (1 << 1),
1639      A38_MBEMPTY      = (1 << 3)
1640   };
1641
1642   //! PROM a38 bit O1 is STOPWAKE' (stop DWT if bit is zero)
1643   inline UINT8 FIFO_STOPWAKE_0() { return m_disp_a38[m_dsp.fifo_rd * 16 + m_dsp.fifo_wr] & A38_STOPWAKE; }
1644
1645   //! PROM a38 bit O3 is MBEMPTY' (FIFO is empty if bit is zero)
1646   inline UINT8 FIFO_MBEMPTY_0() { return m_disp_a38[m_dsp.fifo_rd * 16 + m_dsp.fifo_wr] & A38_MBEMPTY; }
1647
1648   /**
1649    * @brief emulation of PROM a63 in the display schematics page 8
1650    * <PRE>
1651    * The PROM's address lines are driven by a clock CLK, which is
1652    * pixel clock / 24, and an inverted half-scanline signal H[1]'.
1653    *
1654    * It is 32x8 bits and its output bits (B) are connected to the
1655    * signals, as well as its own address lines (A) through a latch
1656    * of the type SN74774 like this:
1657    *
1658    * B    174     A   others
1659    * ------------------------
1660    * 0     5      -   HBLANK
1661    * 1     0      -   HSYNC
1662    * 2     4      0
1663    * 3     1      1
1664    * 4     3      2
1665    * 5     2      3
1666    * 6     -      -   SCANEND
1667    * 7     -      -   HLCGATE
1668    * ------------------------
1669    * H[1]' -      4
1670    *
1671    * The display_state_machine() is called by the CPU at a rate of pixelclock/24,
1672    * which happens to be very close to every 7th CPU micrcocycle.
1673    * </PRE>
1674    */
1675   UINT8* m_disp_a63;
1676
1677   enum {
1678      A63_HBLANK   = (1 << 0),            //!< PROM a63 B0 is latched as HBLANK signal
1679      A63_HSYNC   = (1 << 1),            //!< PROM a63 B1 is latched as HSYNC signal
1680      A63_A0      = (1 << 2),            //!< PROM a63 B2 is the latched next address bit A0
1681      A63_A1      = (1 << 3),            //!< PROM a63 B3 is the latched next address bit A1
1682      A63_A2      = (1 << 4),            //!< PROM a63 B4 is the latched next address bit A2
1683      A63_A3      = (1 << 5),            //!< PROM a63 B5 is the latched next address bit A3
1684      A63_SCANEND   = (1 << 6),            //!< PROM a63 B6 SCANEND signal, which resets the FIFO counters
1685      A63_HLCGATE   = (1 << 7)            //!< PROM a63 B7 HLCGATE signal, which enables counting the HLC
1686   };
1687
1688   /**
1689    * @brief vertical blank and synch PROM
1690    *
1691    * PROM a66 is a 256x4 bit (type 3601), containing the vertical blank + synch.
1692    * Address lines are driven by H[1] to H[128] of the the horz. line counters.
1693    * The PROM is enabled whenever H[256] and H[512] are both 0.
1694    *
1695    * Q1 (001) is VSYNC for the odd field (with H1024=1)
1696    * Q2 (002) is VSYNC for the even field (with H1024=0)
1697    * Q3 (004) is VBLANK for the odd field (with H1024=1)
1698    * Q4 (010) is VBLANK for the even field (with H1024=0)
1699    */
1700   UINT8* m_disp_a66;
1701
1702   enum {
1703      A66_VSYNC_ODD   = (1 << 0),
1704      A66_VSYNC_EVEN   = (1 << 1),
1705      A66_VBLANK_ODD   = (1 << 2),
1706      A66_VBLANK_EVEN   = (1 << 3)
1707   };
1708
1709   //! test the VSYNC (vertical synchronisation) signal in PROM a66 being high
1710   static inline bool A66_VSYNC_HI(UINT8 a, int hlc1024) { return a & (hlc1024 ? A66_VSYNC_ODD : A66_VSYNC_EVEN) ? false : true; }
1711   //! test the VSYNC (vertical synchronisation) signal in PROM a66 being low
1712   static inline bool A66_VSYNC_LO(UINT8 a, int hlc1024) { return a & (hlc1024 ? A66_VSYNC_ODD : A66_VSYNC_EVEN) ? true : false; }
1713   //! test the VBLANK (vertical blanking) signal in PROM a66 being high
1714   static inline bool A66_VBLANK_HI(UINT8 a, int hlc1024) { return a & (hlc1024 ? A66_VBLANK_ODD : A66_VBLANK_EVEN) ? false : true; }
1715   //! test the VBLANK (vertical blanking) signal in PROM a66 being low
1716   static inline bool A66_VBLANK_LO(UINT8 a, int hlc1024) { return a & (hlc1024 ? A66_VBLANK_ODD : A66_VBLANK_EVEN) ? true : false; }
1717
1718   //! screen bitmap
1719   bitmap_ind16* m_displ_bitmap;
1720
1721   //! update a word in the screen bitmap
1722   void update_bitmap_word(int x, int y, UINT16 word);
1723
1724   //! unload the next word from the display FIFO and shift it to the screen
1725   void unload_word();
1726
1727   /**
1728    * @brief function called by the CPU to enter the next display state
1729    *
1730    * There are 32 states per scanline and 875 scanlines per frame.
1731    *
1732    * @param arg the current m_disp_a63 PROM address
1733    * @return next state of the display state machine
1734    */
1735   void display_state_machine();
1736
1737   //! branch on the evenfield flip-flop
1738   void f2_evenfield_1(void);
1739
1740   //! initialize the display context
1741   void init_disp();
1742   //! deinitialize the display context
1743   void exit_disp();
1744
1745   // ************************************************
1746   // memory stuff
1747   // ************************************************
1748
1749   enum {
1750      ALTO2_MEM_NONE,
1751      ALTO2_MEM_ODD   = (1 << 0),
1752      ALTO2_MEM_RAM   = (1 << 1),
1753      ALTO2_MEM_NIRVANA   = (1 << 2)
1754   };
1755
1756   struct {
1757      UINT32* ram;                  //!< main memory organized as double-words
1758      UINT8* hpb;                     //!< Hamming Code bits (6) and Parity bits (1) per double word
1759      UINT32 mar;                     //!< memory address register
1760      UINT32 rmdd;                  //!< read memory data double-word
1761      UINT32 wmdd;                  //!< write memory data double-word
1762      UINT16 md;                     //!< memory data register
1763      UINT64 cycle;                  //!< cycle when the memory address register was loaded
1764
1765      /**
1766       * @brief memory access under the way if non-zero
1767       * 0: no memory access (MEM_NONE)
1768       * 1: invalid
1769       * 2: memory access even word (MEM_RAM)
1770       * 3: memory access odd word (MEM_RAM | MEM_ODD)
1771       * 4: refresh even word (MEM_REFRESH)
1772       * 5: refresh odd word (MEM_REFRESH | MEM_ODD)
1773       */
1774      int access;
1775      int error;                     //!< non-zero after a memory error was detected
1776      int mear;                     //!< memory error address register
1777      UINT16 mesr;                  //!< memory error status register
1778      UINT16 mecr;                  //!< memory error control register
1779   }   m_mem;
1780
1781   /**
1782    * @brief check if memory address register load is yet possible
1783    * suspend if accessing RAM and previous MAR<- was less than 5 cycles ago
1784    *
1785    * 1.  MAR<- ANY
1786    * 2.  REQUIRED
1787    * 3.  MD<- whatever
1788    * 4.  SUSPEND
1789    * 5.  SUSPEND
1790    * 6.  MAR<- ANY
1791    *
1792    * @result returns 0, if memory address can be loaded
1793    */
1794   inline bool check_mem_load_mar_stall(UINT8 rsel) {
1795      return (ALTO2_MEM_NONE == m_mem.access ? false : cycle() < m_mem.cycle+5);
1796   }
1797
1798   /**
1799    * @brief check if memory read is yet possible
1800    * MAR<- = cycle #1, earliest read at cycle #5, i.e. + 4
1801    *
1802    * 1.  MAR<- ANY
1803    * 2.  REQUIRED
1804    * 3.  SUSPEND
1805    * 4.  SUSPEND
1806    * 5.  whereever <-MD
1807    *
1808    * @result returns 0, if memory can be read without wait cycle
1809    */
1810   inline bool check_mem_read_stall() {
1811      return (ALTO2_MEM_NONE == m_mem.access ? false : cycle() < m_mem.cycle+4);
1812   }
1813
1814   /**
1815    * @brief check if memory write is yet possible
1816    * MAR<- = cycle #1, earliest write at cycle #3, i.e. + 2
1817    *
1818    * 1.  MAR<- ANY
1819    * 2.  REQUIRED
1820    * 3.  OPTIONAL
1821    * 4.  MD<- whatever
1822    *
1823    * @result returns 0, if memory can be written without wait cycle
1824    */
1825   inline bool check_mem_write_stall() {
1826      return (ALTO2_MEM_NONE == m_mem.access ? false : cycle() < m_mem.cycle+2);
1827   }
1828
1829   //! memory error address register read
1830   DECLARE_READ16_MEMBER( mear_r );
1831
1832   //! memory error status register read
1833   DECLARE_READ16_MEMBER( mesr_r );
1834
1835   //! memory error status register write (clear)
1836   DECLARE_WRITE16_MEMBER( mesr_w );
1837
1838   //! memory error control register read
1839   DECLARE_READ16_MEMBER( mecr_r );
1840
1841   //! memory error control register write
1842   DECLARE_WRITE16_MEMBER( mecr_w );
1843
1844   //! read or write a memory double-word and caluclate its Hamming code
1845   UINT32 hamming_code(int write, UINT32 dw_addr, UINT32 dw_data);
1846
1847   //! load the memory address register with some value
1848   void load_mar(UINT8 rsel, UINT32 addr);
1849
1850   //! read memory or memory mapped I/O from the address in mar to md
1851   UINT16 read_mem();
1852
1853   //! write memory or memory mapped I/O from md to the address in mar
1854   void write_mem(UINT16 data);
1855
1856   //! debugger interface to read memory
1857   UINT16 debug_read_mem(UINT32 addr);
1858
1859   //! debugger interface to write memory
1860   void debug_write_mem(UINT32 addr, UINT16 data);
1861
1862#if   ALTO2_DEBUG
1863   void watch_write(UINT32 addr, UINT32 data);
1864   void watch_read(UINT32 addr, UINT32 data);
1865#endif
1866   void init_memory();                        //!< initialize the memory system
1867   void exit_memory();                        //!< deinitialize the memory system
1868
1869   // ************************************************
1870   // emulator task
1871   // ************************************************
1872   struct {
1873      UINT16 ir;                           //!< emulator instruction register
1874      UINT8 skip;                           //!< emulator skip
1875      UINT8 cy;                           //!< emulator carry
1876   }   m_emu;
1877   void bs_emu_disp_0();                     //!< bs_emu_disp early: drive bus by IR[8-15], possibly sign extended
1878   void f1_emu_block_0();                     //!< f1_block early: block task
1879   void f1_emu_load_rmr_1();                  //!< f1_load_rmr late: load the reset mode register
1880   void f1_emu_load_esrb_1();                  //!< f1_load_esrb late: load the extended S register bank from BUS[12-14]
1881   void f1_rsnf_0();                        //!< f1_rsnf early: drive the bus from the Ethernet node ID
1882   void f1_startf_0();                        //!< f1_startf early: defines commands for for I/O hardware, including Ethernet
1883   void f2_busodd_1();                        //!< f2_busodd late: branch on odd bus
1884   void f2_magic_1();                        //!< f2_magic late: shift and use T
1885   void f2_load_dns_0();                     //!< f2_load_dns early: modify RESELECT with DstAC = (3 - IR[3-4])
1886   void f2_load_dns_1();                     //!< f2_load_dns late: do novel shifts
1887   void f2_acdest_0();                        //!< f2_acdest early: modify RSELECT with DstAC = (3 - IR[3-4])
1888   void bitblt_info();                        //!< debug bitblt opcode
1889   void f2_load_ir_1();                     //!< f2_load_ir late: load instruction register IR and branch on IR[0,5-7]
1890   void f2_idisp_1();                        //!< f2_idisp late: branch on: arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
1891   void f2_acsource_0();                     //!< f2_acsource early: modify RSELECT with SrcAC = (3 - IR[1-2])
1892   void f2_acsource_1();                     //!< f2_acsource late: branch on arithmetic IR_SH, others PROM ctl2k_u3[IR[1-7]]
1893   void init_emu(int task);                  //!< 000 initialize emulator task
1894   void exit_emu();                        //!< deinitialize emulator task
1895
1896   // ************************************************
1897   // ksec task
1898   // ************************************************
1899   void f1_ksec_block_0(void);
1900   void init_ksec(int task);                  //!< 004 initialize disk sector task
1901   void exit_ksec();
1902
1903   // ************************************************
1904   // ethernet task
1905   // ************************************************
1906   /**
1907    * @brief BPROMs P3601-1; 256x4; enet.a41 "PE1" and enet.a42 "PE2"
1908    *
1909    * Phase encoder
1910    *
1911    * a41: P3601-1; 256x4; "PE1"
1912    * a42: P3601-1; 256x4; "PE2"
1913    *
1914    * PE1/PE2 inputs
1915    * ----------------
1916    * A0  (5) OUTGO
1917    * A1  (6) XDATA
1918    * A2  (7) OSDATAG
1919    * A3  (4) XCLOCK
1920    * A4  (3) OCNTR0
1921    * A5  (2) OCNTR1
1922    * A6  (1) OCNTR2
1923    * A7 (15) OCNTR3
1924    *
1925    * PE1 outputs
1926    * ----------------
1927    * D0 (12) OCNTR0
1928    * D1 (11) OCNTR1
1929    * D2 (10) OCNTR2
1930    * D3  (9) OCNTR3
1931    *
1932    * PE2 outputs
1933    * ----------------
1934    * D0 (12) n.c.
1935    * D1 (11) to OSLOAD flip flop J and K'
1936    * D2 (10) XDATA
1937    * D3  (9) XCLOCK
1938    */
1939   UINT8* m_ether_a41;
1940   UINT8* m_ether_a42;
1941
1942   /**
1943    * @brief BPROM; P3601-1; 265x4 enet.a49 "AFIFO"
1944    *
1945    * Perhaps try with the contents of the display FIFO, as it is
1946    * the same type and the display FIFO has the same size.
1947    *
1948    * FIFO control
1949    *
1950    * a49: P3601-1; 256x4; "AFIFO"
1951    *
1952    * inputs
1953    * ----------------
1954    * A0  (5) fifo_wr[0]
1955    * A1  (6) fifo_wr[1]
1956    * A2  (7) fifo_wr[2]
1957    * A3  (4) fifo_wr[3]
1958    * A4  (3) fifo_rd[0]
1959    * A5  (2) fifo_rd[1]
1960    * A6  (1) fifo_rd[2]
1961    * A7 (15) fifo_rd[3]
1962    *
1963    * outputs active low
1964    * ----------------------------
1965    * D0 (12) BE'    (buffer empty)
1966    * D1 (11) BNE'   (buffer next empty ?)
1967    * D2 (10) BNNE'  (buffer next next empty ?)
1968    * D3  (9) BF'    (buffer full)
1969    *
1970    * Data from enet.a49 after address line reversal:
1971    * 000: 010 007 017 017 017 017 017 017 017 017 017 017 017 017 013 011
1972    * 020: 011 010 007 017 017 017 017 017 017 017 017 017 017 017 017 013
1973    * 040: 013 011 010 007 017 017 017 017 017 017 017 017 017 017 017 017
1974    * 060: 017 013 011 010 007 017 017 017 017 017 017 017 017 017 017 017
1975    * 100: 017 017 013 011 010 007 017 017 017 017 017 017 017 017 017 017
1976    * 120: 017 017 017 013 011 010 007 017 017 017 017 017 017 017 017 017
1977    * 140: 017 017 017 017 013 011 010 007 017 017 017 017 017 017 017 017
1978    * 160: 017 017 017 017 017 013 011 010 007 017 017 017 017 017 017 017
1979    * 200: 017 017 017 017 017 017 013 011 010 007 017 017 017 017 017 017
1980    * 220: 017 017 017 017 017 017 017 013 011 010 007 017 017 017 017 017
1981    * 240: 017 017 017 017 017 017 017 017 013 011 010 007 017 017 017 017
1982    * 260: 017 017 017 017 017 017 017 017 017 013 011 010 007 017 017 017
1983    * 300: 017 017 017 017 017 017 017 017 017 017 013 011 010 007 017 017
1984    * 320: 017 017 017 017 017 017 017 017 017 017 017 013 011 010 007 017
1985    * 340: 017 017 017 017 017 017 017 017 017 017 017 017 013 011 010 007
1986    * 360: 007 017 017 017 017 017 017 017 017 017 017 017 017 013 011 010
1987    */
1988   UINT8* m_ether_a49;
1989
1990   static const int m_duckbreath_sec = 15;         //!< send duckbreath every 15 seconds
1991
1992   struct {
1993      UINT16 fifo[ALTO2_ETHER_FIFO_SIZE];         //!< FIFO buffer
1994      UINT16 fifo_rd;                        //!< FIFO input pointer
1995      UINT16 fifo_wr;                        //!< FIFO output pointer
1996      UINT16 status;                        //!< status word
1997      UINT32 rx_crc;                        //!< receiver CRC
1998      UINT32 tx_crc;                        //!< transmitter CRC
1999      UINT32 rx_count;                     //!< received words count
2000      UINT32 tx_count;                     //!< transmitted words count
2001      emu_timer* tx_timer;                  //!< transmitter timer
2002      int duckbreath;                        //!< if non-zero, interval in seconds at which to broadcast the duckbreath
2003   }   m_eth;
2004
2005   TIMER_CALLBACK_MEMBER( rx_duckbreath );         //!< HACK: pull the next word from the duckbreath in the fifo
2006   TIMER_CALLBACK_MEMBER( tx_packet );            //!< transmit data from the FIFO to <nirvana for now>
2007   void eth_wakeup();                        //!< check for the various reasons to wakeup the Ethernet task
2008   void eth_startf();                        //!< start input or output depending on m_bus
2009   void bs_eidfct_0();                        //!< bs_eidfct early: Ethernet input data function
2010   void f1_eth_block_0();                     //!< f1_eth_block early: block the Ether task
2011   void f1_eilfct_0();                        //!< f1_eilfct early: Ethernet input look function
2012   void f1_epfct_0();                        //!< f1_epfct early: Ethernet post function
2013   void f1_ewfct_1();                        //!< f1_ewfct late: Ethernet countdown wakeup function
2014   void f2_eodfct_1();                        //!< f2_eodfct late: Ethernet output data function
2015   void f2_eosfct_1();                        //!< f2_eosfct late: Ethernet output start function
2016   void f2_erbfct_1();                        //!< f2_erbfct late: Ethernet reset branch function
2017   void f2_eefct_1();                        //!< f2_eefct late: Ethernet end of transmission function
2018   void f2_ebfct_1();                        //!< f2_ebfct late: Ethernet branch function
2019   void f2_ecbfct_1();                        //!< f2_ecbfct late: Ethernet countdown branch function
2020   void f2_eisfct_1();                        //!< f2_eisfct late: Ethernet input start function
2021   void activate_eth();                     //!< called by the CPU when the Ethernet task becomes active
2022   void init_ether(int task);                  //!< 007 initialize ethernet task
2023   void exit_ether();                        //!< deinitialize ethernet task
2024
2025   // ************************************************
2026   // memory refresh task
2027   // ************************************************
2028   void f1_mrt_block_0();                     //!< f1_mrt_block early: block the display word task
2029   void activate_mrt();                     //!< called by the CPU when MRT becomes active
2030   void init_mrt(int task);                  //!< 010 initialize memory refresh task
2031   void exit_mrt();                        //!< deinitialize memory refresh task
2032
2033   // ************************************************
2034   // display word task
2035   // ************************************************
2036   void f1_dwt_block_0();                     //!< f1_dwt_block early: block the display word task
2037   void f2_dwt_load_ddr_1();                  //!< f2_dwt_load_ddr late: load the display data register
2038   void init_dwt(int task);                  //!< 011 initialize display word task
2039   void exit_dwt();                        //!< deinitialize display word task
2040
2041   // ************************************************
2042   // cursor task
2043   // ************************************************
2044   void f1_curt_block_0();                     //!< f1_curt_block early: disable the cursor task and set the curt_blocks flag
2045   void f2_load_xpreg_1();                     //!< f2_load_xpreg late: load the x position register from BUS[6-15]
2046   void f2_load_csr_1();                     //!< f2_load_csr late: load the cursor shift register from BUS[0-15]
2047   void activate_curt();                     //!< curt_activate: called by the CPU when the cursor task becomes active
2048   void init_curt(int task);                   //!< 012 initialize cursor task
2049   void exit_curt();                        //!< deinitialize cursor task
2050
2051   // ************************************************
2052   // display horizontal task
2053   // ************************************************
2054   void f1_dht_block_0();                     //!< f1_dht_block early: disable the display word task
2055   void f2_dht_setmode_1();                  //!< f2_dht_setmode late: set the next scanline's mode inverse and half clock and branch
2056   void activate_dht();                     //!< called by the CPU when the display horizontal task becomes active
2057   void init_dht(int task);                  //!< 013 initialize display horizontal task
2058   void exit_dht();                        //!< deinitialize display horizontal task
2059
2060   // ************************************************
2061   // display vertical task
2062   // ************************************************
2063   void f1_dvt_block_0();                     //!< f1_dvt_block early: disable the display word task
2064   void activate_dvt();                     //!< called by the CPU when the display vertical task becomes active
2065   void init_dvt(int task);                  //!< 014 initialize display vertical task
2066   void exit_dvt();                        //!< deinitialize display vertical task
2067
2068   // ************************************************
2069   // parity task
2070   // ************************************************
2071   void activate_part();
2072   void init_part(int task);                  //!< 015 initialize parity task
2073   void exit_part();                        //!< deinitialize parity task
2074
2075   // ************************************************
2076   // disk word task
2077   // ************************************************
2078   void f1_kwd_block_0(void);
2079   void init_kwd(int task);                  //!< 016 initialize disk word task
2080   void exit_kwd();                        //!< deinitialize disk word task
2081};
2082
2083extern const device_type ALTO2;
2084
2085
2086#endif /* _CPU_ALTO2_H_ */
Property changes on: branches/alto2/src/emu/cpu/alto2/alto2cpu.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain
branches/alto2/src/emu/cpu/alto2/a2curt.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/**
1313 * @brief f1_curt_block early: disable the cursor task and set the curt_blocks flag
branches/alto2/src/emu/cpu/alto2/a2mem.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212#define   PUT_EVEN(dword,word)         A2_PUT32(dword,32, 0,15,word)
1313#define   GET_EVEN(dword)               A2_GET32(dword,32, 0,15)
branches/alto2/src/emu/cpu/alto2/a2hw.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/**
1313 * @brief read the UTILIN port
branches/alto2/src/emu/cpu/alto2/a2dht.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/**
1313 * @brief f1_dht_block early: disable the display word task
branches/alto2/src/emu/cpu/alto2/a2ram.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/**
1313 * @brief bs_read_sreg early: drive bus by S register or M (MYL), if rsel is = 0
branches/alto2/src/emu/cpu/alto2/a2roms.c
r26286r26287
1#include "alto2.h"
1/*****************************************************************************
2 *
3 *   Portable Xerox AltoII PROM loading and decoding
4 *
5 *   Copyright: Juergen Buchmueller <pullmoll@t-online.de>
6 *
7 *   Licenses: MAME, GPLv2
8 *
9 *****************************************************************************/
10#include "alto2cpu.h"
211#include "a2roms.h"
312
413#define   DEBUG_PROM_LOAD      0   //!< define to 1 to dump PROMs after loading
branches/alto2/src/emu/cpu/alto2/a2ksec.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212//! f1_ksec_block early: block the disk sector task
1313void alto2_cpu_device::f1_ksec_block_0()
branches/alto2/src/emu/cpu/alto2/a2kwd.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212//! f1_kwd_block early: block the disk word task
1313void alto2_cpu_device::f1_kwd_block_0()
branches/alto2/src/emu/cpu/alto2/a2emu.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/** @brief CTL2K_U3 address line for F2 function */
1313#define   CTL2K_U3(f2) (f2 == f2_emu_idisp ? 0x80 : 0x00)
branches/alto2/src/emu/cpu/alto2/a2mouse.c
r26286r26287
1#include "alto2.h"
1/*****************************************************************************
2 *
3 *   Portable Xerox AltoII mouse interface
4 *
5 *   Copyright: Juergen Buchmueller <pullmoll@t-online.de>
6 *
7 *   Licenses: MAME, GPLv2
8 *
9 *****************************************************************************/
10#include "alto2cpu.h"
211
312#define   MOUSE_DIRTY_HACK   0
413
r26286r26287
151160INPUT_CHANGED_MEMBER( alto2_cpu_device::mouse_motion_x )
152161{
153162   // set new destination (absolute) mouse x coordinate
154   m_mouse.dx = newval;
163   m_mouse.dx += newval - oldval;
164   if (m_mouse.dx < 0)
165      m_mouse.dx = 0;
166   if (m_mouse.dx > 605)
167      m_mouse.dx = 605;
155168#if   MOUSE_DIRTY_HACK
156169   /* XXX: dirty, dirty, hack */
157170#if   ALTO2_HAMMING_CHECK
r26286r26287
172185INPUT_CHANGED_MEMBER( alto2_cpu_device::mouse_motion_y )
173186{
174187   // set new destination (absolute) mouse y coordinate
175   m_mouse.dy = newval;
188   m_mouse.dy += newval - oldval;
189   if (m_mouse.dy < 0)
190      m_mouse.dy = 0;
191   if (m_mouse.dy > 807)
192      m_mouse.dy = 807;
176193#if   MOUSE_DIRTY_HACK
177194   /* XXX: dirty, dirty, hack */
178195#if   ALTO2_HAMMING_CHECK
branches/alto2/src/emu/cpu/alto2/a2disk.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212
1313#define   JKFF_FUNCTION   0   //!< define 1 to debug the JK flip-flops, 0 to use a lookup table
r26286r26287
22642264   }
22652265#else
22662266   if (++arg < dhd->bits_per_sector()) {
2267      if (!m_dsk.bitclk_time)
2268         m_dsk.bitclk_time = static_cast<int>(dhd->bit_time().as_double() * ATTOSECONDS_PER_NANOSECOND);
2267      if (!m_dsk.bitclk_time) {
2268         // get bit time in pico seconds
2269         m_dsk.bitclk_time = static_cast<int>(dhd->bit_time().as_attoseconds() / 1000000);
2270      }
22692271      m_bitclk_time += m_dsk.bitclk_time;
22702272      m_bitclk_index = arg;
22712273   } else {
r26286r26287
23732375   m_dsk.strobon_timer->reset();
23742376
23752377   m_dsk.seclate_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_seclate),this));
2376//   m_dsk.seclate_timer->adjust(attotime::from_nsec(TW_SECLATE), 1);
23772378   m_dsk.seclate_timer->reset();
23782379
23792380   m_dsk.ok_to_run_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_ok_to_run),this));
2380   m_dsk.ok_to_run_timer->adjust(attotime::from_nsec(35 * ALTO2_UCYCLE), 1);
2381   m_dsk.ok_to_run_timer->adjust(attotime::from_nsec(35 * ALTO2_UCYCLE / 1000), 1);
23812382
23822383   m_dsk.ready_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(alto2_cpu_device::disk_ready_mf31a),this));
23832384   m_dsk.ready_timer->reset();
branches/alto2/src/emu/cpu/alto2/a2dvt.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/**
1313 * @brief f1_dvt_block early: disable the display word task
branches/alto2/src/emu/cpu/alto2/a2dwt.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/**
1313 * @brief f1_dwt_block early: block the display word task
branches/alto2/src/emu/cpu/alto2/a2disp.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/**
1313 * @brief PROM a38 contains the STOPWAKE' and MBEMBPTY' signals for the FIFO
r26286r26287
252252/**
253253 * @brief unload the next word from the display FIFO and shift it to the screen
254254 */
255int alto2_cpu_device::unload_word(int x)
255void alto2_cpu_device::unload_word()
256256{
257   int x = m_unload_word;
257258   int y = ((m_dsp.hlc - m_dsp.vblank) & ~(1024|1)) + HLC1024;
258259   UINT16* scanline = m_dsp.scanline[y];
259260
r26286r26287
308309   }
309310   if (x < ALTO2_DISPLAY_VISIBLE_WORDS) {
310311      m_unload_time += ALTO2_DISPLAY_BITTIME(m_dsp.halfclock ? 32 : 16);
311      return x;
312      m_unload_word = x;
313   } else {
314      m_unload_time = -1;
312315   }
313
314   m_unload_time = -1;
315   return -1;
316316}
317317
318318
r26286r26287
324324 * @param arg the current displ_a63 PROM address
325325 * @result returns the next state of the display state machine
326326 */
327UINT8 alto2_cpu_device::display_state_machine(UINT8 arg)
327void alto2_cpu_device::display_state_machine()
328328{
329   LOG((LOG_DISPL,5,"DSP%03o:", arg));
330   if (020 == arg) {
329   LOG((LOG_DISPL,5,"DSP%03o:", m_dsp_state));
330   if (020 == m_dsp_state) {
331331      LOG((LOG_DISPL,2," HLC=%d", m_dsp.hlc));
332332   }
333333
334   UINT8 a63 = m_disp_a63[arg];
334   UINT8 a63 = m_disp_a63[m_dsp_state];
335335   if (A63_HLCGATE_HI(a63)) {
336336      /* reset or count horizontal line counters */
337337      if (m_dsp.hlc == ALTO2_DISPLAY_HLC_END)
r26286r26287
467467
468468   m_dsp.a63 = a63;
469469   m_dsp.a66 = a66;
470
471   return next;
470   m_dsp_state = next;
472471}
473472
474473/**
branches/alto2/src/emu/cpu/alto2/a2kbd.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212/**
1313 * @brief read the keyboard address matrix
branches/alto2/src/emu/cpu/alto2/alto2dsm.c
r26286r26287
55 *
66 *   Licenses: MAME, GPLv2
77 **********************************************************/
8#include "alto2.h"
8#include "alto2cpu.h"
99
1010#define   loc_DASTART      0000420   // display list header
1111#define   loc_DVIBITS      0000421   // display vertical field interrupt bitword
branches/alto2/src/emu/cpu/alto2/a2mrt.c
r26286r26287
77 *   Licenses: MAME, GPLv2
88 *
99 *****************************************************************************/
10#include "alto2.h"
10#include "alto2cpu.h"
1111
1212//! f1_mrt_block early: block the display word task
1313void alto2_cpu_device::f1_mrt_block_0()
branches/alto2/src/emu/cpu/cpu.mak
r26286r26287
22712271
22722272#-------------------------------------------------
22732273# Xerox Alto-II
2274#@src/emu/cpu/alto2/alto2.h,CPUS += ALTO2
2274#@src/emu/cpu/alto2/alto2cpu.h,CPUS += ALTO2
22752275#-------------------------------------------------
22762276
22772277ifneq ($(filter ALTO2,$(CPUS)),)
22782278OBJDIRS += $(CPUOBJ)/alto2
2279CPUOBJS += $(CPUOBJ)/alto2/alto2.o \
2279CPUOBJS += $(CPUOBJ)/alto2/alto2cpu.o \
22802280   $(CPUOBJ)/alto2/a2disk.o \
22812281   $(CPUOBJ)/alto2/a2disp.o \
22822282   $(CPUOBJ)/alto2/a2curt.o \
r26286r26287
22992299DASMOBJS += $(CPUOBJ)/alto2/alto2dsm.o
23002300endif
23012301
2302$(CPUOBJ)/alto2/alto2.o:    $(CPUSRC)/alto2/alto2.c \
2303                     $(CPUSRC)/alto2/alto2.h
2302$(CPUOBJ)/alto2/alto2cpu.o: $(CPUSRC)/alto2/alto2cpu.c \
2303                     $(CPUSRC)/alto2/alto2cpu.h
23042304
23052305$(CPUOBJ)/alto2/a2disk.o:   $(CPUSRC)/alto2/a2disk.c \
2306                     $(CPUSRC)/alto2/alto2.h
2306                     $(CPUSRC)/alto2/alto2cpu.h
23072307
23082308$(CPUOBJ)/alto2/a2disp.o:   $(CPUSRC)/alto2/a2disp.c \
2309                     $(CPUSRC)/alto2/alto2.h
2309                     $(CPUSRC)/alto2/alto2cpu.h
23102310
23112311$(CPUOBJ)/alto2/a2curt.o:   $(CPUSRC)/alto2/a2curt.c \
2312                     $(CPUSRC)/alto2/alto2.h
2312                     $(CPUSRC)/alto2/alto2cpu.h
23132313
23142314$(CPUOBJ)/alto2/a2dht.o:    $(CPUSRC)/alto2/a2dht.c \
2315                     $(CPUSRC)/alto2/alto2.h
2315                     $(CPUSRC)/alto2/alto2cpu.h
23162316
23172317$(CPUOBJ)/alto2/a2dvt.o:    $(CPUSRC)/alto2/a2dvt.c \
2318                     $(CPUSRC)/alto2/alto2.h
2318                     $(CPUSRC)/alto2/alto2cpu.h
23192319
23202320$(CPUOBJ)/alto2/a2dwt.o:    $(CPUSRC)/alto2/a2dwt.c \
2321                     $(CPUSRC)/alto2/alto2.h
2321                     $(CPUSRC)/alto2/alto2cpu.h
23222322
23232323$(CPUOBJ)/alto2/a2emu.o:    $(CPUSRC)/alto2/a2emu.c \
2324                     $(CPUSRC)/alto2/alto2.h
2324                     $(CPUSRC)/alto2/alto2cpu.h
23252325
23262326$(CPUOBJ)/alto2/a2ether.o:  $(CPUSRC)/alto2/a2ether.c \
2327                     $(CPUSRC)/alto2/alto2.h
2327                     $(CPUSRC)/alto2/alto2cpu.h
23282328
23292329$(CPUOBJ)/alto2/a2hw.o:     $(CPUSRC)/alto2/a2hw.c \
2330                     $(CPUSRC)/alto2/alto2.h
2330                     $(CPUSRC)/alto2/alto2cpu.h
23312331
23322332$(CPUOBJ)/alto2/a2kbd.o:    $(CPUSRC)/alto2/a2kbd.c \
2333                     $(CPUSRC)/alto2/alto2.h
2333                     $(CPUSRC)/alto2/alto2cpu.h
23342334
23352335$(CPUOBJ)/alto2/a2ksec.o:   $(CPUSRC)/alto2/a2ksec.c \
2336                     $(CPUSRC)/alto2/alto2.h
2336                     $(CPUSRC)/alto2/alto2cpu.h
23372337
23382338$(CPUOBJ)/alto2/a2kwd.o:    $(CPUSRC)/alto2/a2kwd.c \
2339                     $(CPUSRC)/alto2/alto2.h
2339                     $(CPUSRC)/alto2/alto2cpu.h
23402340
23412341$(CPUOBJ)/alto2/a2mem.o:    $(CPUSRC)/alto2/a2mem.c \
2342                     $(CPUSRC)/alto2/alto2.h
2342                     $(CPUSRC)/alto2/alto2cpu.h
23432343
23442344$(CPUOBJ)/alto2/a2mouse.o:  $(CPUSRC)/alto2/a2mouse.c \
2345                     $(CPUSRC)/alto2/alto2.h
2345                     $(CPUSRC)/alto2/alto2cpu.h
23462346
23472347$(CPUOBJ)/alto2/a2mrt.o:    $(CPUSRC)/alto2/a2mrt.c \
2348                     $(CPUSRC)/alto2/alto2.h
2348                     $(CPUSRC)/alto2/alto2cpu.h
23492349
23502350$(CPUOBJ)/alto2/a2part.o:   $(CPUSRC)/alto2/a2part.c \
2351                     $(CPUSRC)/alto2/alto2.h
2351                     $(CPUSRC)/alto2/alto2cpu.h
23522352
23532353$(CPUOBJ)/alto2/a2ram.o:    $(CPUSRC)/alto2/a2ram.c \
2354                     $(CPUSRC)/alto2/alto2.h
2354                     $(CPUSRC)/alto2/alto2cpu.h
23552355
23562356$(CPUOBJ)/alto2/a2roms.o:   $(CPUSRC)/alto2/a2roms.c \
23572357                     $(CPUSRC)/alto2/a2roms.h \
2358                     $(CPUSRC)/alto2/alto2.h
2358                     $(CPUSRC)/alto2/alto2cpu.h
23592359
23602360$(CPUOBJ)/alto2/alto2dsm.o: $(CPUSRC)/alto2/alto2dsm.c \
2361                     $(CPUSRC)/alto2/alto2.h
2361                     $(CPUSRC)/alto2/alto2cpu.h
23622362
branches/alto2/src/mess/includes/alto2.h
r26286r26287
88#define _INCLUDES_ALTO2_H_
99
1010#include "emu.h"
11#include "cpu/alto2/alto2.h"
11#include "cpu/alto2/alto2cpu.h"
1212#include "machine/diablo_hd.h"
1313
1414class alto2_state : public driver_device
1515{
1616public:
17   alto2_state(const machine_config &mconfig, device_type type, const char *tag)
18      : driver_device(mconfig, type, tag),
17   alto2_state(const machine_config &mconfig, device_type type, const char *tag) :
18      driver_device(mconfig, type, tag),
1919      m_maincpu(*this, "maincpu"),
2020      m_io_row0(*this, "ROW0"),
2121      m_io_row1(*this, "ROW1"),
r26286r26287
2626      m_io_row6(*this, "ROW6"),
2727      m_io_row7(*this, "ROW7"),
2828      m_io_config(*this, "CONFIG")
29      { }
29   { }
3030
3131   UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
3232
33   bitmap_ind16* m_bitmap;
34
3533   DECLARE_DRIVER_INIT(alto2);
3634
3735   virtual void palette_init();
3836   DECLARE_MACHINE_RESET(alto2);
39   void screen_eof_alto2(screen_device &screen, bool state);
4037
4138protected:
4239   required_device<cpu_device> m_maincpu;
r26286r26287
4946   required_ioport m_io_row6;
5047   required_ioport m_io_row7;
5148   optional_ioport m_io_config;
52
53   // FIXME: use device timers instead of individual emu_timer* in alto2 code(?)
54//   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
5549};
5650
5751#endif /* _INCLUDES_ALTO2_H_ */
branches/alto2/src/mess/drivers/alto2.c
r26286r26287
1919   return 0;
2020}
2121
22void alto2_state::screen_eof_alto2(screen_device &screen, bool state)
23{
24   // TODO: anything?
25}
26
2722/* Input Ports */
2823
2924/** @brief make an Alto key int from 1 << bit */
r26286r26287
211206   PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3) PORT_NAME("Mouse YELLOW (middel)") PORT_CODE(MOUSECODE_BUTTON3) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_buttons, 0 )
212207
213208   PORT_START("mousex")   // Mouse - X AXIS
214   PORT_BIT( 0xffff, 0x0000, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_motion_x, 0 )
209   PORT_BIT( 0xffff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(2) PORT_PLAYER(1) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_motion_x, 0 )
215210
216211   PORT_START("mousey")   // Mouse - Y AXIS
217   PORT_BIT( 0xffff, 0x0000, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_motion_y, 0 )
212   PORT_BIT( 0xffff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(2) PORT_PLAYER(1) PORT_CHANGED_MEMBER( ":maincpu", alto2_cpu_device, mouse_motion_y, 0 )
218213
219214PORT_START("CONFIG")    /* config diode on main board */
220215   PORT_CONFNAME( 0x40, 0x40, "TV system")
r26286r26287
224219
225220/* ROM */
226221ROM_START( alto2 )
227   // dummy region for the maincpu
228   ROM_REGION( 1, "maincpu", 0 )
229   ROM_FILL(0, 1, ALTO2_UCODE_INVERTED)
222   // dummy region for the maincpu - this is not used in any way
223   ROM_REGION( 0400, "maincpu", 0 )
224   ROM_FILL(0, 0400, ALTO2_UCODE_INVERTED)
230225ROM_END
231226
232227//**************************************************************************
r26286r26287
269264                     ALTO2_DISPLAY_TOTAL_WIDTH,   0, ALTO2_DISPLAY_WIDTH,
270265                     ALTO2_DISPLAY_TOTAL_HEIGHT,  0, ALTO2_DISPLAY_HEIGHT)
271266   MCFG_SCREEN_UPDATE_DRIVER(alto2_state, screen_update)
272   MCFG_SCREEN_VBLANK_DRIVER(alto2_state, screen_eof_alto2)
267//   MCFG_SCREEN_VBLANK_DRIVER(alto2_state, screen_eof_alto2)
273268
274269   MCFG_PALETTE_LENGTH(2)
275270
r26286r26287
289284/* Game Drivers */
290285
291286//    YEAR  NAME    PARENT  COMPAT  MACHINE  INPUT  CLASS        INIT   COMPANY  FULLNAME   FLAGS
292COMP( 1974, alto2,  0,      0,      alto2,   alto2, alto2_state, alto2, "Xerox", "Alto-II", GAME_NOT_WORKING | GAME_NO_SOUND )
287COMP( 1974, alto2,  0,      0,      alto2,   alto2, alto2_state, alto2, "Xerox", "Alto-II", GAME_NO_SOUND )

Previous 199869 Revisions Next


© 1997-2024 The MAME Team