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