1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /**********************************************************************
4 
5 RCA "COSMAC" CDP1800 series CPU emulation
6 CDP1801, CDP1802, CDP1804, CDP1805, CDP1806
7 
8 TODO:
9 - does CDP1803 exist?
10 - is it useful to emulate I and N registers or can they just be defined as (m_op >> x & 0xf)?
11 - 1804/5/6: extended opcode timing is wrong, multiple execute states
12 - 1804/5/6: add more extended opcodes (05/06 supports more than 04)
13 - 1804/5/6: add counter/timer
14 - 1804/5: add internal address map (ram/rom)
15 
16 **********************************************************************/
17 
18 #include "emu.h"
19 #include "debugger.h"
20 #include "cosmac.h"
21 #include "coreutil.h"
22 
23 // permit our enums to be saved
24 ALLOW_SAVE_TYPE(cosmac_device::cosmac_mode);
25 ALLOW_SAVE_TYPE(cosmac_device::cosmac_state);
26 
27 
28 //**************************************************************************
29 //  CONSTANTS
30 //**************************************************************************
31 
32 #define CLOCKS_INIT         8 // really 9, but needs to be 8 to synchronize cdp1861 video timings
33 #define CLOCKS_FETCH        8
34 #define CLOCKS_EXECUTE      8
35 #define CLOCKS_DMA          8
36 #define CLOCKS_INTERRUPT    8
37 
38 
39 
40 //**************************************************************************
41 //  MACROS
42 //**************************************************************************
43 
44 #define OPCODE_R(addr)      read_opcode(addr)
45 #define RAM_R(addr)         read_byte(addr)
46 #define RAM_W(addr, data)   write_byte(addr, data)
47 #define IO_R(addr)          read_io_byte(addr)
48 #define IO_W(addr, data)    write_io_byte(addr, data)
49 
50 #define P   m_p
51 #define X   m_x
52 #define D   m_d
53 #define B   m_b
54 #define T   m_t
55 #define R   m_r
56 #define DF  m_df
57 #define IE  m_ie
58 #define Q   m_q
59 #define N   m_n
60 #define I   m_i
61 #define EF  m_ef
62 
63 #define GET_FLAGS()             ((m_df << 2) | (m_ie << 1) | m_q)
64 
65 #define SET_FLAGS(v)            do { \
66 									m_df = BIT(v, 2); \
67 									m_ie = BIT(v, 1); \
68 									m_q = BIT(v, 0); \
69 								} while (0);
70 
71 
72 
73 //**************************************************************************
74 //  STATIC OPCODE TABLES
75 //**************************************************************************
76 
77 const cosmac_device::ophandler cdp1801_device::s_opcodetable[256] =
78 {
79 	&cdp1801_device::idl,    &cdp1801_device::ldn,    &cdp1801_device::ldn,    &cdp1801_device::ldn,
80 	&cdp1801_device::ldn,    &cdp1801_device::ldn,    &cdp1801_device::ldn,    &cdp1801_device::ldn,
81 	&cdp1801_device::ldn,    &cdp1801_device::ldn,    &cdp1801_device::ldn,    &cdp1801_device::ldn,
82 	&cdp1801_device::ldn,    &cdp1801_device::ldn,    &cdp1801_device::ldn,    &cdp1801_device::ldn,
83 
84 	&cdp1801_device::inc,    &cdp1801_device::inc,    &cdp1801_device::inc,    &cdp1801_device::inc,
85 	&cdp1801_device::inc,    &cdp1801_device::inc,    &cdp1801_device::inc,    &cdp1801_device::inc,
86 	&cdp1801_device::inc,    &cdp1801_device::inc,    &cdp1801_device::inc,    &cdp1801_device::inc,
87 	&cdp1801_device::inc,    &cdp1801_device::inc,    &cdp1801_device::inc,    &cdp1801_device::inc,
88 
89 	&cdp1801_device::dec,    &cdp1801_device::dec,    &cdp1801_device::dec,    &cdp1801_device::dec,
90 	&cdp1801_device::dec,    &cdp1801_device::dec,    &cdp1801_device::dec,    &cdp1801_device::dec,
91 	&cdp1801_device::dec,    &cdp1801_device::dec,    &cdp1801_device::dec,    &cdp1801_device::dec,
92 	&cdp1801_device::dec,    &cdp1801_device::dec,    &cdp1801_device::dec,    &cdp1801_device::dec,
93 
94 	&cdp1801_device::br,     &cdp1801_device::und,    &cdp1801_device::bz,     &cdp1801_device::bdf,
95 	&cdp1801_device::b,      &cdp1801_device::b,      &cdp1801_device::b,      &cdp1801_device::b,
96 	&cdp1801_device::nbr,    &cdp1801_device::und,    &cdp1801_device::bnz,    &cdp1801_device::bnf,
97 	&cdp1801_device::bn,     &cdp1801_device::bn,     &cdp1801_device::bn,     &cdp1801_device::bn,
98 
99 	&cdp1801_device::lda,    &cdp1801_device::lda,    &cdp1801_device::lda,    &cdp1801_device::lda,
100 	&cdp1801_device::lda,    &cdp1801_device::lda,    &cdp1801_device::lda,    &cdp1801_device::lda,
101 	&cdp1801_device::lda,    &cdp1801_device::lda,    &cdp1801_device::lda,    &cdp1801_device::lda,
102 	&cdp1801_device::lda,    &cdp1801_device::lda,    &cdp1801_device::lda,    &cdp1801_device::lda,
103 
104 	&cdp1801_device::str,    &cdp1801_device::str,    &cdp1801_device::str,    &cdp1801_device::str,
105 	&cdp1801_device::str,    &cdp1801_device::str,    &cdp1801_device::str,    &cdp1801_device::str,
106 	&cdp1801_device::str,    &cdp1801_device::str,    &cdp1801_device::str,    &cdp1801_device::str,
107 	&cdp1801_device::str,    &cdp1801_device::str,    &cdp1801_device::str,    &cdp1801_device::str,
108 
109 	// OUT 0 and INP 0 are valid on the CDP1801
110 	&cdp1801_device::out,    &cdp1801_device::out,    &cdp1801_device::out,    &cdp1801_device::out,
111 	&cdp1801_device::out,    &cdp1801_device::out,    &cdp1801_device::out,    &cdp1801_device::out,
112 	&cdp1801_device::inp,    &cdp1801_device::inp,    &cdp1801_device::inp,    &cdp1801_device::inp,
113 	&cdp1801_device::inp,    &cdp1801_device::inp,    &cdp1801_device::inp,    &cdp1801_device::inp,
114 
115 	&cdp1801_device::ret,    &cdp1801_device::dis,    &cdp1801_device::und,    &cdp1801_device::und,
116 	&cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,
117 	&cdp1801_device::sav,    &cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,
118 	&cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,
119 
120 	&cdp1801_device::glo,    &cdp1801_device::glo,    &cdp1801_device::glo,    &cdp1801_device::glo,
121 	&cdp1801_device::glo,    &cdp1801_device::glo,    &cdp1801_device::glo,    &cdp1801_device::glo,
122 	&cdp1801_device::glo,    &cdp1801_device::glo,    &cdp1801_device::glo,    &cdp1801_device::glo,
123 	&cdp1801_device::glo,    &cdp1801_device::glo,    &cdp1801_device::glo,    &cdp1801_device::glo,
124 
125 	&cdp1801_device::ghi,    &cdp1801_device::ghi,    &cdp1801_device::ghi,    &cdp1801_device::ghi,
126 	&cdp1801_device::ghi,    &cdp1801_device::ghi,    &cdp1801_device::ghi,    &cdp1801_device::ghi,
127 	&cdp1801_device::ghi,    &cdp1801_device::ghi,    &cdp1801_device::ghi,    &cdp1801_device::ghi,
128 	&cdp1801_device::ghi,    &cdp1801_device::ghi,    &cdp1801_device::ghi,    &cdp1801_device::ghi,
129 
130 	&cdp1801_device::plo,    &cdp1801_device::plo,    &cdp1801_device::plo,    &cdp1801_device::plo,
131 	&cdp1801_device::plo,    &cdp1801_device::plo,    &cdp1801_device::plo,    &cdp1801_device::plo,
132 	&cdp1801_device::plo,    &cdp1801_device::plo,    &cdp1801_device::plo,    &cdp1801_device::plo,
133 	&cdp1801_device::plo,    &cdp1801_device::plo,    &cdp1801_device::plo,    &cdp1801_device::plo,
134 
135 	&cdp1801_device::phi,    &cdp1801_device::phi,    &cdp1801_device::phi,    &cdp1801_device::phi,
136 	&cdp1801_device::phi,    &cdp1801_device::phi,    &cdp1801_device::phi,    &cdp1801_device::phi,
137 	&cdp1801_device::phi,    &cdp1801_device::phi,    &cdp1801_device::phi,    &cdp1801_device::phi,
138 	&cdp1801_device::phi,    &cdp1801_device::phi,    &cdp1801_device::phi,    &cdp1801_device::phi,
139 
140 	&cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,
141 	&cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,
142 	&cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,
143 	&cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,    &cdp1801_device::und,
144 
145 	&cdp1801_device::sep,    &cdp1801_device::sep,    &cdp1801_device::sep,    &cdp1801_device::sep,
146 	&cdp1801_device::sep,    &cdp1801_device::sep,    &cdp1801_device::sep,    &cdp1801_device::sep,
147 	&cdp1801_device::sep,    &cdp1801_device::sep,    &cdp1801_device::sep,    &cdp1801_device::sep,
148 	&cdp1801_device::sep,    &cdp1801_device::sep,    &cdp1801_device::sep,    &cdp1801_device::sep,
149 
150 	&cdp1801_device::sex,    &cdp1801_device::sex,    &cdp1801_device::sex,    &cdp1801_device::sex,
151 	&cdp1801_device::sex,    &cdp1801_device::sex,    &cdp1801_device::sex,    &cdp1801_device::sex,
152 	&cdp1801_device::sex,    &cdp1801_device::sex,    &cdp1801_device::sex,    &cdp1801_device::sex,
153 	&cdp1801_device::sex,    &cdp1801_device::sex,    &cdp1801_device::sex,    &cdp1801_device::sex,
154 
155 	&cdp1801_device::ldx,    &cdp1801_device::_or,    &cdp1801_device::_and,   &cdp1801_device::_xor,
156 	&cdp1801_device::add,    &cdp1801_device::sd,     &cdp1801_device::shr,    &cdp1801_device::sm,
157 	&cdp1801_device::ldi,    &cdp1801_device::ori,    &cdp1801_device::ani,    &cdp1801_device::xri,
158 	&cdp1801_device::adi,    &cdp1801_device::sdi,    &cdp1801_device::und,    &cdp1801_device::smi
159 };
160 
get_ophandler(uint16_t opcode) const161 cosmac_device::ophandler cdp1801_device::get_ophandler(uint16_t opcode) const
162 {
163 	return s_opcodetable[opcode & 0xff];
164 }
165 
166 const cosmac_device::ophandler cdp1802_device::s_opcodetable[256] =
167 {
168 	&cdp1802_device::idl,    &cdp1802_device::ldn,    &cdp1802_device::ldn,    &cdp1802_device::ldn,
169 	&cdp1802_device::ldn,    &cdp1802_device::ldn,    &cdp1802_device::ldn,    &cdp1802_device::ldn,
170 	&cdp1802_device::ldn,    &cdp1802_device::ldn,    &cdp1802_device::ldn,    &cdp1802_device::ldn,
171 	&cdp1802_device::ldn,    &cdp1802_device::ldn,    &cdp1802_device::ldn,    &cdp1802_device::ldn,
172 
173 	&cdp1802_device::inc,    &cdp1802_device::inc,    &cdp1802_device::inc,    &cdp1802_device::inc,
174 	&cdp1802_device::inc,    &cdp1802_device::inc,    &cdp1802_device::inc,    &cdp1802_device::inc,
175 	&cdp1802_device::inc,    &cdp1802_device::inc,    &cdp1802_device::inc,    &cdp1802_device::inc,
176 	&cdp1802_device::inc,    &cdp1802_device::inc,    &cdp1802_device::inc,    &cdp1802_device::inc,
177 
178 	&cdp1802_device::dec,    &cdp1802_device::dec,    &cdp1802_device::dec,    &cdp1802_device::dec,
179 	&cdp1802_device::dec,    &cdp1802_device::dec,    &cdp1802_device::dec,    &cdp1802_device::dec,
180 	&cdp1802_device::dec,    &cdp1802_device::dec,    &cdp1802_device::dec,    &cdp1802_device::dec,
181 	&cdp1802_device::dec,    &cdp1802_device::dec,    &cdp1802_device::dec,    &cdp1802_device::dec,
182 
183 	&cdp1802_device::br,     &cdp1802_device::bq,     &cdp1802_device::bz,     &cdp1802_device::bdf,
184 	&cdp1802_device::b,      &cdp1802_device::b,      &cdp1802_device::b,      &cdp1802_device::b,
185 	&cdp1802_device::nbr,    &cdp1802_device::bnq,    &cdp1802_device::bnz,    &cdp1802_device::bnf,
186 	&cdp1802_device::bn,     &cdp1802_device::bn,     &cdp1802_device::bn,     &cdp1802_device::bn,
187 
188 	&cdp1802_device::lda,    &cdp1802_device::lda,    &cdp1802_device::lda,    &cdp1802_device::lda,
189 	&cdp1802_device::lda,    &cdp1802_device::lda,    &cdp1802_device::lda,    &cdp1802_device::lda,
190 	&cdp1802_device::lda,    &cdp1802_device::lda,    &cdp1802_device::lda,    &cdp1802_device::lda,
191 	&cdp1802_device::lda,    &cdp1802_device::lda,    &cdp1802_device::lda,    &cdp1802_device::lda,
192 
193 	&cdp1802_device::str,    &cdp1802_device::str,    &cdp1802_device::str,    &cdp1802_device::str,
194 	&cdp1802_device::str,    &cdp1802_device::str,    &cdp1802_device::str,    &cdp1802_device::str,
195 	&cdp1802_device::str,    &cdp1802_device::str,    &cdp1802_device::str,    &cdp1802_device::str,
196 	&cdp1802_device::str,    &cdp1802_device::str,    &cdp1802_device::str,    &cdp1802_device::str,
197 
198 	&cdp1802_device::irx,    &cdp1802_device::out,    &cdp1802_device::out,    &cdp1802_device::out,
199 	&cdp1802_device::out,    &cdp1802_device::out,    &cdp1802_device::out,    &cdp1802_device::out,
200 	&cdp1802_device::inp,    &cdp1802_device::inp,    &cdp1802_device::inp,    &cdp1802_device::inp,
201 	&cdp1802_device::inp,    &cdp1802_device::inp,    &cdp1802_device::inp,    &cdp1802_device::inp,
202 
203 	&cdp1802_device::ret,    &cdp1802_device::dis,    &cdp1802_device::ldxa,   &cdp1802_device::stxd,
204 	&cdp1802_device::adc,    &cdp1802_device::sdb,    &cdp1802_device::shrc,   &cdp1802_device::smb,
205 	&cdp1802_device::sav,    &cdp1802_device::mark,   &cdp1802_device::req,    &cdp1802_device::seq,
206 	&cdp1802_device::adci,   &cdp1802_device::sdbi,   &cdp1802_device::shlc,   &cdp1802_device::smbi,
207 
208 	&cdp1802_device::glo,    &cdp1802_device::glo,    &cdp1802_device::glo,    &cdp1802_device::glo,
209 	&cdp1802_device::glo,    &cdp1802_device::glo,    &cdp1802_device::glo,    &cdp1802_device::glo,
210 	&cdp1802_device::glo,    &cdp1802_device::glo,    &cdp1802_device::glo,    &cdp1802_device::glo,
211 	&cdp1802_device::glo,    &cdp1802_device::glo,    &cdp1802_device::glo,    &cdp1802_device::glo,
212 
213 	&cdp1802_device::ghi,    &cdp1802_device::ghi,    &cdp1802_device::ghi,    &cdp1802_device::ghi,
214 	&cdp1802_device::ghi,    &cdp1802_device::ghi,    &cdp1802_device::ghi,    &cdp1802_device::ghi,
215 	&cdp1802_device::ghi,    &cdp1802_device::ghi,    &cdp1802_device::ghi,    &cdp1802_device::ghi,
216 	&cdp1802_device::ghi,    &cdp1802_device::ghi,    &cdp1802_device::ghi,    &cdp1802_device::ghi,
217 
218 	&cdp1802_device::plo,    &cdp1802_device::plo,    &cdp1802_device::plo,    &cdp1802_device::plo,
219 	&cdp1802_device::plo,    &cdp1802_device::plo,    &cdp1802_device::plo,    &cdp1802_device::plo,
220 	&cdp1802_device::plo,    &cdp1802_device::plo,    &cdp1802_device::plo,    &cdp1802_device::plo,
221 	&cdp1802_device::plo,    &cdp1802_device::plo,    &cdp1802_device::plo,    &cdp1802_device::plo,
222 
223 	&cdp1802_device::phi,    &cdp1802_device::phi,    &cdp1802_device::phi,    &cdp1802_device::phi,
224 	&cdp1802_device::phi,    &cdp1802_device::phi,    &cdp1802_device::phi,    &cdp1802_device::phi,
225 	&cdp1802_device::phi,    &cdp1802_device::phi,    &cdp1802_device::phi,    &cdp1802_device::phi,
226 	&cdp1802_device::phi,    &cdp1802_device::phi,    &cdp1802_device::phi,    &cdp1802_device::phi,
227 
228 	&cdp1802_device::lbr,    &cdp1802_device::lbq,    &cdp1802_device::lbz,    &cdp1802_device::lbdf,
229 	&cdp1802_device::nop,    &cdp1802_device::lsnq,   &cdp1802_device::lsnz,   &cdp1802_device::lsnf,
230 	&cdp1802_device::nlbr,   &cdp1802_device::lbnq,   &cdp1802_device::lbnz,   &cdp1802_device::lbnf,
231 	&cdp1802_device::lsie,   &cdp1802_device::lsq,    &cdp1802_device::lsz,    &cdp1802_device::lsdf,
232 
233 	&cdp1802_device::sep,    &cdp1802_device::sep,    &cdp1802_device::sep,    &cdp1802_device::sep,
234 	&cdp1802_device::sep,    &cdp1802_device::sep,    &cdp1802_device::sep,    &cdp1802_device::sep,
235 	&cdp1802_device::sep,    &cdp1802_device::sep,    &cdp1802_device::sep,    &cdp1802_device::sep,
236 	&cdp1802_device::sep,    &cdp1802_device::sep,    &cdp1802_device::sep,    &cdp1802_device::sep,
237 
238 	&cdp1802_device::sex,    &cdp1802_device::sex,    &cdp1802_device::sex,    &cdp1802_device::sex,
239 	&cdp1802_device::sex,    &cdp1802_device::sex,    &cdp1802_device::sex,    &cdp1802_device::sex,
240 	&cdp1802_device::sex,    &cdp1802_device::sex,    &cdp1802_device::sex,    &cdp1802_device::sex,
241 	&cdp1802_device::sex,    &cdp1802_device::sex,    &cdp1802_device::sex,    &cdp1802_device::sex,
242 
243 	&cdp1802_device::ldx,    &cdp1802_device::_or,    &cdp1802_device::_and,   &cdp1802_device::_xor,
244 	&cdp1802_device::add,    &cdp1802_device::sd,     &cdp1802_device::shr,    &cdp1802_device::sm,
245 	&cdp1802_device::ldi,    &cdp1802_device::ori,    &cdp1802_device::ani,    &cdp1802_device::xri,
246 	&cdp1802_device::adi,    &cdp1802_device::sdi,    &cdp1802_device::shl,    &cdp1802_device::smi
247 };
248 
get_ophandler(uint16_t opcode) const249 cosmac_device::ophandler cdp1802_device::get_ophandler(uint16_t opcode) const
250 {
251 	return s_opcodetable[opcode & 0xff];
252 }
253 
254 const cosmac_device::ophandler cdp1804_device::s_opcodetable_ex[256] =
255 {
256 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
257 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::ldc,    &cdp1804_device::und,
258 	&cdp1804_device::gec,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
259 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
260 
261 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
262 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
263 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
264 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
265 
266 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
267 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
268 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
269 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
270 
271 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
272 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
273 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
274 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::bci,    &cdp1804_device::bxi,
275 
276 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
277 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
278 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
279 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
280 
281 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
282 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
283 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
284 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
285 
286 	&cdp1804_device::rlxa,   &cdp1804_device::rlxa,   &cdp1804_device::rlxa,   &cdp1804_device::rlxa,
287 	&cdp1804_device::rlxa,   &cdp1804_device::rlxa,   &cdp1804_device::rlxa,   &cdp1804_device::rlxa,
288 	&cdp1804_device::rlxa,   &cdp1804_device::rlxa,   &cdp1804_device::rlxa,   &cdp1804_device::rlxa,
289 	&cdp1804_device::rlxa,   &cdp1804_device::rlxa,   &cdp1804_device::rlxa,   &cdp1804_device::rlxa,
290 
291 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
292 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
293 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
294 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
295 
296 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
297 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
298 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
299 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
300 
301 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
302 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
303 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
304 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
305 
306 	&cdp1804_device::rsxd,   &cdp1804_device::rsxd,   &cdp1804_device::rsxd,   &cdp1804_device::rsxd,
307 	&cdp1804_device::rsxd,   &cdp1804_device::rsxd,   &cdp1804_device::rsxd,   &cdp1804_device::rsxd,
308 	&cdp1804_device::rsxd,   &cdp1804_device::rsxd,   &cdp1804_device::rsxd,   &cdp1804_device::rsxd,
309 	&cdp1804_device::rsxd,   &cdp1804_device::rsxd,   &cdp1804_device::rsxd,   &cdp1804_device::rsxd,
310 
311 	&cdp1804_device::rnx,    &cdp1804_device::rnx,    &cdp1804_device::rnx,    &cdp1804_device::rnx,
312 	&cdp1804_device::rnx,    &cdp1804_device::rnx,    &cdp1804_device::rnx,    &cdp1804_device::rnx,
313 	&cdp1804_device::rnx,    &cdp1804_device::rnx,    &cdp1804_device::rnx,    &cdp1804_device::rnx,
314 	&cdp1804_device::rnx,    &cdp1804_device::rnx,    &cdp1804_device::rnx,    &cdp1804_device::rnx,
315 
316 	&cdp1804_device::rldi,   &cdp1804_device::rldi,   &cdp1804_device::rldi,   &cdp1804_device::rldi,
317 	&cdp1804_device::rldi,   &cdp1804_device::rldi,   &cdp1804_device::rldi,   &cdp1804_device::rldi,
318 	&cdp1804_device::rldi,   &cdp1804_device::rldi,   &cdp1804_device::rldi,   &cdp1804_device::rldi,
319 	&cdp1804_device::rldi,   &cdp1804_device::rldi,   &cdp1804_device::rldi,   &cdp1804_device::rldi,
320 
321 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
322 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
323 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
324 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
325 
326 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
327 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
328 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
329 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
330 
331 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
332 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
333 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
334 	&cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,    &cdp1804_device::und,
335 };
336 
get_ophandler(uint16_t opcode) const337 cosmac_device::ophandler cdp1804_device::get_ophandler(uint16_t opcode) const
338 {
339 	if ((opcode & 0xff00) == 0x6800)
340 		return s_opcodetable_ex[opcode & 0xff];
341 	else
342 		return cdp1802_device::get_ophandler(opcode);
343 }
344 
345 
346 
347 //**************************************************************************
348 //  DEVICE INTERFACE
349 //**************************************************************************
350 
351 // device type definition
352 DEFINE_DEVICE_TYPE(CDP1801, cdp1801_device, "cdp1801", "RCA CDP1801")
353 DEFINE_DEVICE_TYPE(CDP1802, cdp1802_device, "cdp1802", "RCA CDP1802")
354 DEFINE_DEVICE_TYPE(CDP1804, cdp1804_device, "cdp1804", "RCA CDP1804")
355 DEFINE_DEVICE_TYPE(CDP1805, cdp1805_device, "cdp1805", "RCA CDP1805")
356 DEFINE_DEVICE_TYPE(CDP1806, cdp1806_device, "cdp1806", "RCA CDP1806")
357 
358 
359 //-------------------------------------------------
360 //  cosmac_device - constructor
361 //-------------------------------------------------
362 
cosmac_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)363 cosmac_device::cosmac_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
364 	: cpu_device(mconfig, type, tag, owner, clock),
365 		cosmac_disassembler::config(),
366 		m_program_config("program", ENDIANNESS_LITTLE, 8, 16),
367 		m_io_config("io", ENDIANNESS_LITTLE, 8, 3),
368 		m_read_wait(*this),
369 		m_read_clear(*this),
370 		m_read_ef(*this),
371 		m_write_q(*this),
372 		m_read_dma(*this),
373 		m_write_dma(*this),
374 		m_write_sc(*this),
375 		m_write_tpb(*this),
376 		m_op(0),
377 		m_state(cosmac_state::STATE_1_INIT),
378 		m_mode(cosmac_mode::RESET),
379 		m_pmode(cosmac_mode::RUN),
380 		m_wait(true),
381 		m_clear(true),
382 		m_irq(CLEAR_LINE),
383 		m_dmain(CLEAR_LINE),
384 		m_dmaout(CLEAR_LINE)
385 {
386 	for (auto & elem : m_ef)
387 		elem = CLEAR_LINE;
388 	for (auto & elem : m_ef_line)
389 		elem = CLEAR_LINE;
390 }
391 
392 
393 //-------------------------------------------------
394 //  cdp1801_device - constructor
395 //-------------------------------------------------
396 
cdp1801_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)397 cdp1801_device::cdp1801_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
398 	cosmac_device(mconfig, CDP1801, tag, owner, clock)
399 { }
400 
401 
402 //-------------------------------------------------
403 //  cdp1802_device - constructor
404 //-------------------------------------------------
405 
cdp1802_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)406 cdp1802_device::cdp1802_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
407 	cdp1802_device(mconfig, CDP1802, tag, owner, clock)
408 { }
409 
cdp1802_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)410 cdp1802_device::cdp1802_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
411 	cosmac_device(mconfig, type, tag, owner, clock)
412 { }
413 
414 
415 //-------------------------------------------------
416 //  cdp1804_device - constructor
417 //-------------------------------------------------
418 
cdp1804_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)419 cdp1804_device::cdp1804_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
420 	cdp1804_device(mconfig, CDP1804, tag, owner, clock)
421 { }
422 
cdp1804_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)423 cdp1804_device::cdp1804_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
424 	cdp1802_device(mconfig, type, tag, owner, clock)
425 { }
426 
427 
428 //-------------------------------------------------
429 //  cdp1805_device - constructor
430 //-------------------------------------------------
431 
cdp1805_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)432 cdp1805_device::cdp1805_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
433 	cdp1805_device(mconfig, CDP1805, tag, owner, clock)
434 { }
435 
cdp1805_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)436 cdp1805_device::cdp1805_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
437 	cdp1804_device(mconfig, type, tag, owner, clock)
438 { }
439 
440 
441 //-------------------------------------------------
442 //  cdp1806_device - constructor
443 //-------------------------------------------------
444 
cdp1806_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)445 cdp1806_device::cdp1806_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
446 	cdp1805_device(mconfig, CDP1806, tag, owner, clock)
447 { }
448 
449 
450 //-------------------------------------------------
451 //  device_start - start up the device
452 //-------------------------------------------------
453 
device_start()454 void cosmac_device::device_start()
455 {
456 	// resolve callbacks
457 	m_read_wait.resolve();
458 	m_read_clear.resolve();
459 	m_read_ef.resolve_all();
460 	m_write_q.resolve_safe();
461 	m_read_dma.resolve_safe(0);
462 	m_write_dma.resolve_safe();
463 	m_write_sc.resolve_safe();
464 	m_write_tpb.resolve_safe();
465 
466 	// get our address spaces
467 	space(AS_PROGRAM).cache(m_cache);
468 	space(AS_PROGRAM).specific(m_program);
469 	space(AS_IO).specific(m_io);
470 
471 	// register our state for the debugger
472 	state_add(STATE_GENPC,      "GENPC",        m_pc).callimport().callexport().noshow();
473 	state_add(STATE_GENPCBASE,  "CURPC",        m_pc).callimport().callexport().noshow();
474 	state_add(STATE_GENFLAGS,   "GENFLAGS",     m_flagsio).mask(0x7).callimport().callexport().noshow().formatstr("%3s");
475 
476 	state_add(COSMAC_P,     "P",    m_p).mask(0xf);
477 	state_add(COSMAC_X,     "X",    m_x).mask(0xf);
478 	state_add(COSMAC_D,     "D",    m_d);
479 	state_add(COSMAC_B,     "B",    m_b);
480 	state_add(COSMAC_T,     "T",    m_t);
481 
482 	state_add(COSMAC_I,     "I",    m_i).mask(0xf);
483 	state_add(COSMAC_N,     "N",    m_n).mask(0xf);
484 
485 	for (int regnum = 0; regnum < 16; regnum++)
486 		state_add(COSMAC_R0 + regnum, string_format("R%d", regnum).c_str(), m_r[regnum]);
487 
488 	state_add(COSMAC_DF,    "DF",   m_df).mask(0x1).noshow();
489 	state_add(COSMAC_IE,    "IE",   m_ie).mask(0x1).noshow();
490 	state_add(COSMAC_Q,     "Q",    m_q).mask(0x1).noshow();
491 
492 	// register our state for saving
493 	save_item(NAME(m_op));
494 	save_item(NAME(m_flagsio));
495 	save_item(NAME(m_state));
496 	save_item(NAME(m_mode));
497 	save_item(NAME(m_pmode));
498 	save_item(NAME(m_irq));
499 	save_item(NAME(m_dmain));
500 	save_item(NAME(m_dmaout));
501 	save_item(NAME(m_ef));
502 	save_item(NAME(m_ef_line));
503 	save_item(NAME(m_d));
504 	save_item(NAME(m_b));
505 	save_item(NAME(m_r));
506 	save_item(NAME(m_p));
507 	save_item(NAME(m_x));
508 	save_item(NAME(m_n));
509 	save_item(NAME(m_i));
510 	save_item(NAME(m_t));
511 	save_item(NAME(m_df));
512 	save_item(NAME(m_ie));
513 	save_item(NAME(m_q));
514 
515 	// set our instruction counter
516 	set_icountptr(m_icount);
517 }
518 
519 
520 //-------------------------------------------------
521 //  device_reset - reset the device
522 //-------------------------------------------------
523 
device_reset()524 void cosmac_device::device_reset()
525 {
526 	m_ie = 0;
527 	set_q_flag(0);
528 	m_df = 0;
529 	m_p = 0;
530 
531 	for (int i = 0; i < ARRAY_LENGTH(m_r); i++)
532 		m_r[i] = machine().rand() & 0xffff;
533 }
534 
535 
536 //-------------------------------------------------
537 //  memory_space_config - return the configuration
538 //  of the specified address space, or nullptr if
539 //  the space doesn't exist
540 //-------------------------------------------------
541 
memory_space_config() const542 device_memory_interface::space_config_vector cosmac_device::memory_space_config() const
543 {
544 	return space_config_vector {
545 		std::make_pair(AS_PROGRAM, &m_program_config),
546 		std::make_pair(AS_IO,      &m_io_config)
547 	};
548 }
549 
550 
551 //-------------------------------------------------
552 //  state_import - import state into the device,
553 //  after it has been set
554 //-------------------------------------------------
555 
state_import(const device_state_entry & entry)556 void cosmac_device::state_import(const device_state_entry &entry)
557 {
558 	switch (entry.index())
559 	{
560 		case STATE_GENPC:
561 		case STATE_GENPCBASE:
562 			R[P] = m_pc;
563 			break;
564 
565 		case STATE_GENFLAGS:
566 			SET_FLAGS(m_flagsio);
567 			break;
568 	}
569 }
570 
571 
572 //-------------------------------------------------
573 //  state_export - export state from the device,
574 //  to a known location where it can be read
575 //-------------------------------------------------
576 
state_export(const device_state_entry & entry)577 void cosmac_device::state_export(const device_state_entry &entry)
578 {
579 	switch (entry.index())
580 	{
581 		case STATE_GENPC:
582 		case STATE_GENPCBASE:
583 			m_pc = R[P];
584 			break;
585 
586 		case STATE_GENFLAGS:
587 			m_flagsio = GET_FLAGS();
588 			break;
589 	}
590 }
591 
592 
593 //-------------------------------------------------
594 //  state_string_export - export state as a string
595 //  for the debugger
596 //-------------------------------------------------
597 
state_string_export(const device_state_entry & entry,std::string & str) const598 void cosmac_device::state_string_export(const device_state_entry &entry, std::string &str) const
599 {
600 	switch (entry.index())
601 	{
602 		case STATE_GENFLAGS:
603 			str = string_format("%c%c%c",
604 					m_df ? 'D' : '.',
605 					m_ie ? 'I' : '.',
606 					m_q  ? 'Q' : '.');
607 			break;
608 	}
609 }
610 
611 
612 //-------------------------------------------------
613 //  disassemble - call the disassembly
614 //  helper function
615 //-------------------------------------------------
616 
create_disassembler()617 std::unique_ptr<util::disasm_interface> cdp1801_device::create_disassembler()
618 {
619 	return std::make_unique<cosmac_disassembler>(cosmac_disassembler::TYPE_1801, this);
620 }
621 
622 
create_disassembler()623 std::unique_ptr<util::disasm_interface> cdp1802_device::create_disassembler()
624 {
625 	return std::make_unique<cosmac_disassembler>(cosmac_disassembler::TYPE_1802, this);
626 }
627 
628 
create_disassembler()629 std::unique_ptr<util::disasm_interface> cdp1805_device::create_disassembler()
630 {
631 	return std::make_unique<cosmac_disassembler>(cosmac_disassembler::TYPE_1805, this);
632 }
633 
634 //**************************************************************************
635 //  INLINE HELPERS
636 //**************************************************************************
637 
638 //-------------------------------------------------
639 //  read_opcode - read an opcode at the given address
640 //-------------------------------------------------
641 
read_opcode(offs_t pc)642 inline uint8_t cosmac_device::read_opcode(offs_t pc)
643 {
644 	return m_cache.read_byte(pc);
645 }
646 
647 
648 //-------------------------------------------------
649 //  read_byte - read a byte at the given address
650 //-------------------------------------------------
651 
read_byte(offs_t address)652 inline uint8_t cosmac_device::read_byte(offs_t address)
653 {
654 	return m_program.read_byte(address);
655 }
656 
657 
658 //-------------------------------------------------
659 //  read_io_byte - read an I/O byte at the given
660 //  address
661 //-------------------------------------------------
662 
read_io_byte(offs_t address)663 inline uint8_t cosmac_device::read_io_byte(offs_t address)
664 {
665 	return m_io.read_byte(address);
666 }
667 
668 
669 //-------------------------------------------------
670 //  write_byte - write a byte at the given address
671 //-------------------------------------------------
672 
write_byte(offs_t address,uint8_t data)673 inline void cosmac_device::write_byte(offs_t address, uint8_t data)
674 {
675 	m_program.write_byte(address, data);
676 }
677 
678 
679 //-------------------------------------------------
680 //  write_io_byte - write an I/O byte at the given
681 //  address
682 //-------------------------------------------------
683 
write_io_byte(offs_t address,uint8_t data)684 inline void cosmac_device::write_io_byte(offs_t address, uint8_t data)
685 {
686 	m_io.write_byte(address, data);
687 }
688 
689 
690 
691 //**************************************************************************
692 //  CORE EXECUTION
693 //**************************************************************************
694 
695 //-------------------------------------------------
696 //  get_memory_address - get current memory address
697 //-------------------------------------------------
698 
get_memory_address()699 offs_t cosmac_device::get_memory_address()
700 {
701 	// this is valid for INP/OUT opcodes
702 	return R[X];
703 }
704 
705 //-------------------------------------------------
706 //  execute_min_cycles - return minimum number of
707 //  cycles it takes for one instruction to execute
708 //-------------------------------------------------
709 
execute_min_cycles() const710 uint32_t cosmac_device::execute_min_cycles() const noexcept
711 {
712 	return 8 * 2;
713 }
714 
715 
716 //-------------------------------------------------
717 //  execute_max_cycles - return maximum number of
718 //  cycles it takes for one instruction to execute
719 //-------------------------------------------------
720 
execute_max_cycles() const721 uint32_t cosmac_device::execute_max_cycles() const noexcept
722 {
723 	return 8 * 3;
724 }
725 
726 
727 //-------------------------------------------------
728 //  execute_input_lines - return the number of
729 //  input/interrupt lines
730 //-------------------------------------------------
731 
execute_input_lines() const732 uint32_t cosmac_device::execute_input_lines() const noexcept
733 {
734 	return 7;
735 }
736 
737 
738 //-------------------------------------------------
739 //  execute_set_input -
740 //-------------------------------------------------
741 
execute_set_input(int inputnum,int state)742 void cosmac_device::execute_set_input(int inputnum, int state)
743 {
744 	switch (inputnum)
745 	{
746 	case COSMAC_INPUT_LINE_INT:
747 		m_irq = state;
748 		break;
749 
750 	case COSMAC_INPUT_LINE_DMAIN:
751 		m_dmain = state;
752 		break;
753 
754 	case COSMAC_INPUT_LINE_DMAOUT:
755 		m_dmaout = state;
756 		break;
757 
758 	case COSMAC_INPUT_LINE_EF1:
759 	case COSMAC_INPUT_LINE_EF2:
760 	case COSMAC_INPUT_LINE_EF3:
761 	case COSMAC_INPUT_LINE_EF4:
762 		m_ef_line[inputnum - COSMAC_INPUT_LINE_EF1] = state;
763 		break;
764 
765 	case COSMAC_INPUT_LINE_CLEAR:
766 		m_clear = state;
767 		break;
768 
769 	case COSMAC_INPUT_LINE_WAIT:
770 		m_wait = state;
771 		break;
772 	}
773 }
774 
775 
776 //-------------------------------------------------
777 //  execute_run -
778 //-------------------------------------------------
779 
execute_run()780 void cosmac_device::execute_run()
781 {
782 	do
783 	{
784 		sample_wait_clear();
785 
786 		switch (m_mode)
787 		{
788 		case cosmac_mode::LOAD:
789 			if (m_pmode == cosmac_mode::RESET)
790 			{
791 				m_pmode = cosmac_mode::LOAD;
792 
793 				// execute initialization cycle
794 				m_state = cosmac_state::STATE_1_INIT;
795 				run();
796 
797 				// next state is IDLE
798 				m_state = cosmac_state::STATE_1_EXECUTE;
799 			}
800 			else
801 			{
802 				// idle
803 				m_op = 0;
804 				I = 0;
805 				N = 0;
806 				run_state();
807 			}
808 			break;
809 
810 		case cosmac_mode::RESET:
811 			reset_state();
812 			m_icount--;
813 			break;
814 
815 		case cosmac_mode::PAUSE:
816 			m_icount--;
817 			break;
818 
819 		case cosmac_mode::RUN:
820 			switch (m_pmode)
821 			{
822 			case cosmac_mode::LOAD:
823 				// RUN mode cannot be initiated from LOAD mode
824 				logerror("COSMAC '%s' Tried to initiate RUN mode from LOAD mode\n", tag());
825 				m_mode = cosmac_mode::LOAD;
826 				break;
827 
828 			case cosmac_mode::RESET:
829 				m_pmode = cosmac_mode::RUN;
830 				m_state = cosmac_state::STATE_1_INIT;
831 				run_state();
832 				break;
833 
834 			case cosmac_mode::PAUSE:
835 				m_pmode = cosmac_mode::RUN;
836 				m_state = cosmac_state::STATE_0_FETCH;
837 				run_state();
838 				break;
839 
840 			case cosmac_mode::RUN:
841 				run_state();
842 				break;
843 			}
844 			break;
845 		}
846 	}
847 	while (m_icount > 0);
848 }
849 
850 
851 //-------------------------------------------------
852 //  run_state - run the CPU state machine
853 //-------------------------------------------------
854 
run_state()855 inline void cosmac_device::run_state()
856 {
857 	output_state_code();
858 
859 	switch (m_state)
860 	{
861 	case cosmac_state::STATE_0_FETCH:
862 		m_op = 0;
863 
864 	case cosmac_state::STATE_0_FETCH_2ND:
865 		fetch_instruction();
866 		break;
867 
868 	case cosmac_state::STATE_1_INIT:
869 		initialize();
870 		debug();
871 		break;
872 
873 	case cosmac_state::STATE_1_EXECUTE:
874 		sample_ef_lines();
875 
876 	case cosmac_state::STATE_1_EXECUTE_2ND:
877 		execute_instruction();
878 		debug();
879 		break;
880 
881 	case cosmac_state::STATE_2_DMA_IN:
882 		dma_input();
883 		debug();
884 		break;
885 
886 	case cosmac_state::STATE_2_DMA_OUT:
887 		dma_output();
888 		debug();
889 		break;
890 
891 	case cosmac_state::STATE_3_INT:
892 		interrupt();
893 		debug();
894 		break;
895 	}
896 }
897 
898 
899 //-------------------------------------------------
900 //  debug - hook into debugger
901 //-------------------------------------------------
902 
debug()903 inline void cosmac_device::debug()
904 {
905 	if ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) && m_state == cosmac_state::STATE_0_FETCH)
906 	{
907 		debugger_instruction_hook(R[P]);
908 	}
909 }
910 
911 
912 //-------------------------------------------------
913 //  sample_wait_clear - sample wait/clear lines
914 //-------------------------------------------------
915 
sample_wait_clear()916 inline void cosmac_device::sample_wait_clear()
917 {
918 	if (!m_read_wait.isnull()) m_wait = m_read_wait();
919 	if (!m_read_clear.isnull()) m_clear = m_read_clear();
920 
921 	m_pmode = m_mode;
922 	m_mode = (cosmac_mode) ((m_clear << 1) | m_wait);
923 }
924 
925 
926 //-------------------------------------------------
927 //  sample_ef_lines - sample EF input lines
928 //-------------------------------------------------
929 
sample_ef_lines()930 inline void cosmac_device::sample_ef_lines()
931 {
932 	for (int i = 0; i < 4; i++)
933 		EF[i] = m_read_ef[i].isnull() ? m_ef_line[i] : m_read_ef[i]();
934 }
935 
936 
937 //-------------------------------------------------
938 //  output_state_code - output state code
939 //-------------------------------------------------
940 
output_state_code()941 inline void cosmac_device::output_state_code()
942 {
943 	if (m_state == cosmac_state::STATE_0_FETCH || m_state == cosmac_state::STATE_0_FETCH_2ND)
944 	{
945 		// S0 fetch
946 		m_write_sc(0, COSMAC_STATE_CODE_S0_FETCH);
947 	}
948 	else if (m_state == cosmac_state::STATE_2_DMA_IN || m_state == cosmac_state::STATE_2_DMA_OUT)
949 	{
950 		// S2 DMA
951 		m_write_sc(0, COSMAC_STATE_CODE_S2_DMA);
952 	}
953 	else if (m_state == cosmac_state::STATE_3_INT)
954 	{
955 		// S3 interrupt
956 		m_write_sc(0, COSMAC_STATE_CODE_S3_INTERRUPT);
957 	}
958 	else
959 	{
960 		// S1 execute
961 		bool is_io = (m_op >> 4) == 0x6; // (unextended) 0x6N: I/O opcodes
962 		m_write_sc(is_io ? (N & 7) : 0, COSMAC_STATE_CODE_S1_EXECUTE);
963 	}
964 }
965 
output_state_code()966 void cdp1801_device::output_state_code()
967 {
968 	if (m_state == cosmac_state::STATE_0_FETCH || m_state == cosmac_state::STATE_0_FETCH_2ND)
969 	{
970 		// S0 fetch
971 		m_write_sc(0, 4);
972 	}
973 	else if (m_state == cosmac_state::STATE_2_DMA_IN || m_state == cosmac_state::STATE_2_DMA_OUT)
974 	{
975 		// S2 DMA
976 		m_write_sc(0, 2);
977 	}
978 	else if (m_state == cosmac_state::STATE_3_INT)
979 	{
980 		// S3 interrupt
981 		m_write_sc(0, 3);
982 	}
983 	else if ((m_op >> 4) == 0x6)
984 	{
985 		// S1 execute (I/O)
986 		m_write_sc(N, 1);
987 	}
988 	else
989 	{
990 		// S1 execute (non-I/O)
991 		m_write_sc(0, 0);
992 	}
993 }
994 
995 
996 //-------------------------------------------------
997 //  set_q_flag - set Q flag state and output it
998 //-------------------------------------------------
999 
set_q_flag(int state)1000 inline void cosmac_device::set_q_flag(int state)
1001 {
1002 	Q = state;
1003 
1004 	m_write_q(Q);
1005 }
1006 
1007 
1008 //-------------------------------------------------
1009 //  put_low_reg - set the low byte of a register
1010 //-------------------------------------------------
1011 
put_low_reg(int reg,uint8_t data)1012 inline void cosmac_device::put_low_reg(int reg, uint8_t data)
1013 {
1014 	R[reg] = (R[reg] & 0xff00) | data;
1015 }
1016 
1017 
1018 //-------------------------------------------------
1019 //  put_high_reg - set the high byte of a register
1020 //-------------------------------------------------
1021 
put_high_reg(int reg,uint8_t data)1022 inline void cosmac_device::put_high_reg(int reg, uint8_t data)
1023 {
1024 	R[reg] = (R[reg] & 0x00ff) | data << 8;
1025 }
1026 
1027 
1028 //-------------------------------------------------
1029 //  fetch_instruction - fetch instruction from
1030 //  the program memory
1031 //-------------------------------------------------
1032 
fetch_instruction()1033 inline void cosmac_device::fetch_instruction()
1034 {
1035 	// instruction fetch
1036 	offs_t addr = R[P]++;
1037 	m_write_tpb(1);
1038 	m_op = m_op << 8 | read_opcode(addr);
1039 	m_write_tpb(0);
1040 
1041 	I = m_op >> 4 & 0x0f;
1042 	N = m_op & 0x0f;
1043 
1044 	m_icount -= CLOCKS_FETCH;
1045 
1046 	// CDP1804 and up: 0x68 for extended opcodes
1047 	if (m_op == 0x68 && has_extended_opcodes())
1048 		m_state = cosmac_state::STATE_0_FETCH_2ND;
1049 	else
1050 		m_state = cosmac_state::STATE_1_EXECUTE;
1051 }
1052 
1053 
1054 //-------------------------------------------------
1055 //  reset_state - handle reset state
1056 //-------------------------------------------------
1057 
reset_state()1058 inline void cosmac_device::reset_state()
1059 {
1060 	m_state = cosmac_state::STATE_1_INIT;
1061 
1062 	m_op = 0;
1063 	I = 0;
1064 	N = 0;
1065 	set_q_flag(0);
1066 	IE = 1;
1067 
1068 	if (m_pmode != cosmac_mode::RESET)
1069 		output_state_code();
1070 }
1071 
1072 
1073 //-------------------------------------------------
1074 //  initialize - handle initialization state
1075 //-------------------------------------------------
1076 
initialize()1077 inline void cosmac_device::initialize()
1078 {
1079 	X = 0;
1080 	P = 0;
1081 	R[0] = 0;
1082 
1083 	m_write_tpb(1);
1084 	m_write_tpb(0);
1085 
1086 	m_icount -= CLOCKS_INIT;
1087 
1088 	if (m_dmain)
1089 	{
1090 		m_state = cosmac_state::STATE_2_DMA_IN;
1091 	}
1092 	else if (m_dmaout)
1093 	{
1094 		m_state = cosmac_state::STATE_2_DMA_OUT;
1095 	}
1096 	else
1097 	{
1098 		m_state = cosmac_state::STATE_0_FETCH;
1099 	}
1100 }
1101 
1102 
1103 //-------------------------------------------------
1104 //  execute_instruction - execute instruction
1105 //-------------------------------------------------
1106 
execute_instruction()1107 inline void cosmac_device::execute_instruction()
1108 {
1109 	// parse the instruction
1110 	m_write_tpb(1);
1111 	(this->*this->get_ophandler(m_op))();
1112 	m_write_tpb(0);
1113 
1114 	m_icount -= CLOCKS_EXECUTE;
1115 
1116 	if (m_state == cosmac_state::STATE_1_EXECUTE && (m_op >> 4) == 0xc) // "long" opcodes
1117 	{
1118 		m_state = cosmac_state::STATE_1_EXECUTE_2ND;
1119 	}
1120 	else if (m_dmain)
1121 	{
1122 		m_state = cosmac_state::STATE_2_DMA_IN;
1123 	}
1124 	else if (m_dmaout)
1125 	{
1126 		m_state = cosmac_state::STATE_2_DMA_OUT;
1127 	}
1128 	else if (IE && m_irq)
1129 	{
1130 		m_state = cosmac_state::STATE_3_INT;
1131 	}
1132 	else if (m_op != 0) // not idling
1133 	{
1134 		m_state = cosmac_state::STATE_0_FETCH;
1135 	}
1136 }
1137 
1138 
1139 //-------------------------------------------------
1140 //  dma_input - handle DMA input state
1141 //-------------------------------------------------
1142 
dma_input()1143 inline void cosmac_device::dma_input()
1144 {
1145 	offs_t addr = R[0]++;
1146 	m_write_tpb(1);
1147 	RAM_W(addr, m_read_dma(addr));
1148 	m_write_tpb(0);
1149 
1150 	m_icount -= CLOCKS_DMA;
1151 
1152 	if (m_dmain)
1153 	{
1154 		m_state = cosmac_state::STATE_2_DMA_IN;
1155 	}
1156 	else if (m_dmaout)
1157 	{
1158 		m_state = cosmac_state::STATE_2_DMA_OUT;
1159 	}
1160 	else if (IE && m_irq)
1161 	{
1162 		m_state = cosmac_state::STATE_3_INT;
1163 	}
1164 	else if (m_mode == cosmac_mode::LOAD)
1165 	{
1166 		m_state = cosmac_state::STATE_1_EXECUTE;
1167 	}
1168 	else
1169 	{
1170 		m_state = cosmac_state::STATE_0_FETCH;
1171 	}
1172 
1173 	standard_irq_callback(COSMAC_INPUT_LINE_DMAIN);
1174 }
1175 
1176 
1177 //-------------------------------------------------
1178 //  dma_output - handle DMA output state
1179 //-------------------------------------------------
1180 
dma_output()1181 inline void cosmac_device::dma_output()
1182 {
1183 	offs_t addr = R[0]++;
1184 	m_write_tpb(1);
1185 	m_write_dma(addr, RAM_R(addr));
1186 	m_write_tpb(0);
1187 
1188 	m_icount -= CLOCKS_DMA;
1189 
1190 	if (m_dmain)
1191 	{
1192 		m_state = cosmac_state::STATE_2_DMA_IN;
1193 	}
1194 	else if (m_dmaout)
1195 	{
1196 		m_state = cosmac_state::STATE_2_DMA_OUT;
1197 	}
1198 	else if (IE && m_irq)
1199 	{
1200 		m_state = cosmac_state::STATE_3_INT;
1201 	}
1202 	else
1203 	{
1204 		m_state = cosmac_state::STATE_0_FETCH;
1205 	}
1206 
1207 	standard_irq_callback(COSMAC_INPUT_LINE_DMAOUT);
1208 }
1209 
1210 
1211 //-------------------------------------------------
1212 //  interrupt - handle interrupt state
1213 //-------------------------------------------------
1214 
interrupt()1215 inline void cosmac_device::interrupt()
1216 {
1217 	T = (X << 4) | P;
1218 	X = 2;
1219 	P = 1;
1220 	IE = 0;
1221 
1222 	m_write_tpb(1);
1223 	m_write_tpb(0);
1224 
1225 	m_icount -= CLOCKS_INTERRUPT;
1226 
1227 	if (m_dmain)
1228 	{
1229 		m_state = cosmac_state::STATE_2_DMA_IN;
1230 	}
1231 	else if (m_dmaout)
1232 	{
1233 		m_state = cosmac_state::STATE_2_DMA_OUT;
1234 	}
1235 	else
1236 	{
1237 		m_state = cosmac_state::STATE_0_FETCH;
1238 	}
1239 
1240 	standard_irq_callback(COSMAC_INPUT_LINE_INT);
1241 }
1242 
1243 
1244 
1245 //**************************************************************************
1246 //  OPCODE IMPLEMENTATIONS
1247 //**************************************************************************
1248 
1249 // memory reference opcode handlers
ldn()1250 void cosmac_device::ldn()   { D = RAM_R(R[N]); }
lda()1251 void cosmac_device::lda()   { D = RAM_R(R[N]); R[N]++; }
ldx()1252 void cosmac_device::ldx()   { D = RAM_R(R[X]); }
ldxa()1253 void cosmac_device::ldxa()  { D = RAM_R(R[X]); R[X]++; }
ldi()1254 void cosmac_device::ldi()   { D = RAM_R(R[P]); R[P]++; }
str()1255 void cosmac_device::str()   { RAM_W(R[N], D); }
stxd()1256 void cosmac_device::stxd()  { RAM_W(R[X], D); R[X]--; }
1257 
1258 // register operations opcode handlers
inc()1259 void cosmac_device::inc()   { R[N]++; }
dec()1260 void cosmac_device::dec()   { R[N]--; }
irx()1261 void cosmac_device::irx()   { R[X]++; }
glo()1262 void cosmac_device::glo()   { D = R[N] & 0xff; }
plo()1263 void cosmac_device::plo()   { put_low_reg(N, D); }
ghi()1264 void cosmac_device::ghi()   { D = R[N] >> 8; }
phi()1265 void cosmac_device::phi()   { put_high_reg(N, D); }
1266 
1267 // logic operations opcode handlers
_or()1268 void cosmac_device::_or()   { D = RAM_R(R[X]) | D; }
ori()1269 void cosmac_device::ori()   { D = RAM_R(R[P]) | D; R[P]++; }
_xor()1270 void cosmac_device::_xor()  { D = RAM_R(R[X]) ^ D; }
xri()1271 void cosmac_device::xri()   { D = RAM_R(R[P]) ^ D; R[P]++; }
_and()1272 void cosmac_device::_and()  { D = RAM_R(R[X]) & D; }
ani()1273 void cosmac_device::ani()   { D = RAM_R(R[P]) & D; R[P]++; }
shr()1274 void cosmac_device::shr()   { DF = BIT(D, 0); D >>= 1; }
shrc()1275 void cosmac_device::shrc()  { int b = DF; DF = BIT(D, 0); D >>= 1; D |= b << 7; }
shl()1276 void cosmac_device::shl()   { DF = BIT(D, 7); D <<= 1; }
shlc()1277 void cosmac_device::shlc()  { int b = DF; DF = BIT(D, 7); D <<= 1; D |= b; }
1278 
1279 // arithmetic operations opcode handlers
add(int left,int right)1280 void cosmac_device::add(int left, int right)
1281 {
1282 	int result = left + right;
1283 
1284 	D = result & 0xff;
1285 	DF = result > 0xff;
1286 }
1287 
add_with_carry(int left,int right)1288 void cosmac_device::add_with_carry(int left, int right)
1289 {
1290 	int result = left + right + DF;
1291 
1292 	D = result & 0xff;
1293 	DF = result > 0xff;
1294 }
1295 
subtract(int left,int right)1296 void cosmac_device::subtract(int left, int right)
1297 {
1298 	int result = left + (right ^ 0xff) + 1;
1299 
1300 	D = result & 0xff;
1301 	DF = result > 0xff;
1302 }
1303 
subtract_with_borrow(int left,int right)1304 void cosmac_device::subtract_with_borrow(int left, int right)
1305 {
1306 	int result = left + (right ^ 0xff) + DF;
1307 
1308 	D = result & 0xff;
1309 	DF = result > 0xff;
1310 }
1311 
add()1312 void cosmac_device::add()   { add(RAM_R(R[X]), D); }
adi()1313 void cosmac_device::adi()   { add(RAM_R(R[P]), D); R[P]++; }
adc()1314 void cosmac_device::adc()   { add_with_carry(RAM_R(R[X]), D); }
adci()1315 void cosmac_device::adci()  { add_with_carry(RAM_R(R[P]), D); R[P]++; }
sd()1316 void cosmac_device::sd()    { subtract(RAM_R(R[X]), D); }
sdi()1317 void cosmac_device::sdi()   { subtract(RAM_R(R[P]), D); R[P]++; }
sdb()1318 void cosmac_device::sdb()   { subtract_with_borrow(RAM_R(R[X]), D); }
sdbi()1319 void cosmac_device::sdbi()  { subtract_with_borrow(RAM_R(R[P]), D); R[P]++; }
sm()1320 void cosmac_device::sm()    { subtract(D, RAM_R(R[X])); }
smi()1321 void cosmac_device::smi()   { subtract(D, RAM_R(R[P])); R[P]++; }
smb()1322 void cosmac_device::smb()   { subtract_with_borrow(D, RAM_R(R[X])); }
smbi()1323 void cosmac_device::smbi()  { subtract_with_borrow(D, RAM_R(R[P])); R[P]++; }
1324 
1325 // short branch instructions opcode handlers
short_branch(int taken)1326 void cosmac_device::short_branch(int taken)
1327 {
1328 	if (taken)
1329 	{
1330 		put_low_reg(P, OPCODE_R(R[P]));
1331 	}
1332 	else
1333 	{
1334 		R[P]++;
1335 	}
1336 }
1337 
br()1338 void cosmac_device::br()    { short_branch(1); }
nbr()1339 void cosmac_device::nbr()   { short_branch(0); }
bz()1340 void cosmac_device::bz()    { short_branch(D == 0); }
bnz()1341 void cosmac_device::bnz()   { short_branch(D != 0); }
bdf()1342 void cosmac_device::bdf()   { short_branch(DF); }
bnf()1343 void cosmac_device::bnf()   { short_branch(!DF); }
bq()1344 void cosmac_device::bq()    { short_branch(Q); }
bnq()1345 void cosmac_device::bnq()   { short_branch(!Q); }
b()1346 void cosmac_device::b()     { short_branch(EF[N & 0x03]); }
bn()1347 void cosmac_device::bn()    { short_branch(!EF[N & 0x03]); }
1348 
1349 // long branch instructions opcode handlers
long_branch(int taken)1350 void cosmac_device::long_branch(int taken)
1351 {
1352 	if (taken)
1353 	{
1354 		if (m_state == cosmac_state::STATE_1_EXECUTE)
1355 		{
1356 			// S1#1
1357 			B = OPCODE_R(R[P]++);
1358 		}
1359 		else
1360 		{
1361 			// S1#2
1362 			R[P] = (B << 8) | OPCODE_R(R[P]);
1363 		}
1364 	}
1365 	else
1366 	{
1367 		// S1#1, S1#2
1368 		R[P]++;
1369 	}
1370 }
1371 
lbr()1372 void cosmac_device::lbr()   { long_branch(1); }
nlbr()1373 void cosmac_device::nlbr()  { long_skip(1); }
lbz()1374 void cosmac_device::lbz()   { long_branch(D == 0); }
lbnz()1375 void cosmac_device::lbnz()  { long_branch(D != 0); }
lbdf()1376 void cosmac_device::lbdf()  { long_branch(DF); }
lbnf()1377 void cosmac_device::lbnf()  { long_branch(!DF); }
lbq()1378 void cosmac_device::lbq()   { long_branch(Q); }
lbnq()1379 void cosmac_device::lbnq()  { long_branch(!Q); }
1380 
1381 // skip instructions opcode handlers
long_skip(int taken)1382 void cosmac_device::long_skip(int taken)
1383 {
1384 	if (taken)
1385 	{
1386 		// S1#1, S1#2
1387 		R[P]++;
1388 	}
1389 }
1390 
lsz()1391 void cosmac_device::lsz()   { long_skip(D == 0); }
lsnz()1392 void cosmac_device::lsnz()  { long_skip(D != 0); }
lsdf()1393 void cosmac_device::lsdf()  { long_skip(DF); }
lsnf()1394 void cosmac_device::lsnf()  { long_skip(!DF); }
lsq()1395 void cosmac_device::lsq()   { long_skip(Q); }
lsnq()1396 void cosmac_device::lsnq()  { long_skip(!Q); }
lsie()1397 void cosmac_device::lsie()  { long_skip(IE); }
1398 
1399 // control instructions opcode handlers
idl()1400 void cosmac_device::idl()   { /* idle */ }
nop()1401 void cosmac_device::nop()   { }
und()1402 void cosmac_device::und()   { /* undefined opcode in CDP1801 */ }
sep()1403 void cosmac_device::sep()   { P = N; }
sex()1404 void cosmac_device::sex()   { X = N; }
seq()1405 void cosmac_device::seq()   { set_q_flag(1); }
req()1406 void cosmac_device::req()   { set_q_flag(0); }
sav()1407 void cosmac_device::sav()   { RAM_W(R[X], T); }
1408 
mark()1409 void cosmac_device::mark()
1410 {
1411 	T = (X << 4) | P;
1412 	RAM_W(R[2], T);
1413 	X = P;
1414 	R[2]--;
1415 }
1416 
return_from_interrupt(int ie)1417 void cosmac_device::return_from_interrupt(int ie)
1418 {
1419 	uint8_t data = RAM_R(R[X]);
1420 	R[X]++;
1421 	P = data & 0xf;
1422 	X = data >> 4;
1423 	IE = ie;
1424 }
1425 
ret()1426 void cosmac_device::ret()   { return_from_interrupt(1); }
dis()1427 void cosmac_device::dis()   { return_from_interrupt(0); }
1428 
1429 // input/output byte transfer opcode handlers
out()1430 void cosmac_device::out()   { IO_W(N, RAM_R(R[X])); R[X]++; }
1431 
1432 /*
1433 
1434     A note about INP 0 (0x68) from Tom Pittman's "A Short Course in Programming":
1435 
1436     If you look carefully, you will notice that we never studied the opcode "68".
1437     That's because it is not a defined 1802 instruction. It has the form of an INP
1438     instruction, but 0 is not a defined input port, so if you execute it (try it!)
1439     nothing is input. "Nothing" is the answer to a question; it is data, and something
1440     will be put in the accumulator and memory (so now you know what the computer uses
1441     to mean "nothing").
1442 
1443     However, since the result of the "68" opcode is unpredictable, it should not be
1444     used in your programs. In fact, "68" is the first byte of a series of additional
1445     instructions for the 1804 and 1805 microprocessors.
1446 
1447     http://www.ittybittycomputers.com/IttyBitty/ShortCor.htm
1448 
1449 */
inp()1450 void cosmac_device::inp()   { D = IO_R(N & 0x07); RAM_W(R[X], D); }
1451 
1452 // CDP1804(and up) extended opcodes
rldi()1453 void cosmac_device::rldi()  { put_high_reg(N, RAM_R(R[P])); R[P]++; put_low_reg(N, RAM_R(R[P])); R[P]++; }
rlxa()1454 void cosmac_device::rlxa()  { put_high_reg(N, RAM_R(R[X])); R[X]++; put_low_reg(N, RAM_R(R[X])); R[X]++; }
rsxd()1455 void cosmac_device::rsxd()  { RAM_W(R[X], R[N] & 0xff); R[X]--; RAM_W(R[X], R[N] >> 8 & 0xff); R[X]--; }
1456 
rnx()1457 void cosmac_device::rnx()   { R[X] = R[N]; }
1458 
bci()1459 void cosmac_device::bci()   { short_branch(1); } // wrong! tests CI flag
bxi()1460 void cosmac_device::bxi()   { short_branch(0); } // wrong! tests XI flag
1461 
ldc()1462 void cosmac_device::ldc()   { /* logerror("LDC counter set: %X\n", D); */ }
gec()1463 void cosmac_device::gec()   { D = machine().rand() & 0xf; } // wrong!
1464 
1465 // CDP1805/06 additional extended opcodes
1466 // TODO
1467