1 // license:BSD-3-Clause
2 // copyright-holders:Mirko Buffoni
3 /***************************************************************************
4 
5     Intel MCS-48/UPI-41 Portable Emulator
6 
7     Copyright Mirko Buffoni
8     Based on the original work Copyright Dan Boris, an 8048 emulator
9 
10     TODO:
11     - EA pin - defined by architecture, must implement:
12       1 means external access, bypassing internal ROM
13       reimplement as a push, not a pull
14     - add CMOS devices, 1 new opcode (01 IDL)
15     - add special 8022 opcodes (RAD, SEL AN0, SEL AN1, RETI)
16     - according to the user manual, some opcodes(dis/enable timer/interrupt)
17       don't increment the timer, does it affect the prescaler too?
18     - IRQ timing is hacked due to WY-100 needing to take JNI branch before servicing interrupt
19 
20 ****************************************************************************
21 
22     Note that the default internal divisor for this chip is by 3 and
23     then again by 5, or by 15 total.
24 
25     Chip   RAM  ROM  I/O
26     ----   ---  ---  ---
27     8021    64   1k   21  (ROM, reduced instruction set)
28     8022    64   2k   26  (ROM, reduced instruction set, analog comparator)
29 
30     8035    64    0   27  (external ROM)
31     8048    64   1k   27  (ROM)
32     8648    64   1k   27  (OTPROM)
33     8748    64   1k   27  (EPROM)
34     8884    64   1k
35     N7751  128   2k
36 
37     8039   128    0   27  (external ROM)
38     8049   128   2k   27  (ROM)
39     8749   128   2k   27  (EPROM)
40     M58715 128    0       (external ROM)
41 
42     8040   256   4k   27  (external ROM)
43     8050   256   4k   27  (ROM)
44 
45 ****************************************************************************
46 
47     UPI-41/42 chips are MCS-48 derived, with some opcode changes:
48 
49             MCS-48 opcode       UPI-41/42 opcode
50             -------------       ----------------
51         02: OUTL BUS,A          OUT  DBB,A
52         08: INS  BUS,A          <illegal>
53         22: <illegal>           IN   DBB,A
54         75: ENT0 CLK            <illegal>
55         80: MOVX A,@R0          <illegal>
56         81: MOVX A,@R1          <illegal>
57         86: JNI  <dest>         JOBF <dest>
58         88: ORL  BUS,#n         <illegal>
59         90: MOVX @R0,A          MOV  STS,A
60         91: MOVX @R1,A          <illegal>
61         98: ANL  BUS,#n         <illegal>
62         D6: <illegal>           JNIBF <dest>
63         E5: SEL  MB0            EN   DMA
64         F5: SEL  MB1            EN   FLAGS
65 
66     Chip numbers are similar to the MCS-48 series:
67 
68     Chip   RAM  ROM  I/O
69     ----   ---  ---  ---
70     8041A   64   1k       (ROM)
71     8041AH 128   1k       (ROM)
72     8641A   64   1k       (OTPROM)
73     8741A   64   1k       (EPROM)
74     8741AH 128   1k       (EPROM)
75 
76     8042   128   2k       (ROM)
77     8042AH 256   2k       (ROM)
78     8642   128   2k       (OTPROM)
79     8742   128   2k       (EPROM)
80     8742AH 256   2k       (EPROM)
81 
82 ***************************************************************************/
83 
84 #include "emu.h"
85 #include "mcs48.h"
86 #include "mcs48dsm.h"
87 
88 #include "debugger.h"
89 
90 
91 /***************************************************************************
92     CONSTANTS
93 ***************************************************************************/
94 
95 /* timer/counter enable bits */
96 #define TIMER_ENABLED   0x01
97 #define COUNTER_ENABLED 0x02
98 
99 /* flag bits */
100 #define C_FLAG          0x80
101 #define A_FLAG          0x40
102 #define F_FLAG          0x20
103 #define B_FLAG          0x10
104 
105 /* status bits (UPI-41) */
106 #define STS_F1          0x08
107 #define STS_F0          0x04
108 #define STS_IBF         0x02
109 #define STS_OBF         0x01
110 
111 /* port 2 bits (UPI-41) */
112 #define P2_OBF          0x10
113 #define P2_NIBF         0x20
114 #define P2_DRQ          0x40
115 #define P2_NDACK        0x80
116 
117 /* enable bits (UPI-41) */
118 #define ENABLE_FLAGS    0x01
119 #define ENABLE_DMA      0x02
120 
121 /* feature masks */
122 #define MB_FEATURE      0x01
123 #define EXT_BUS_FEATURE 0x02
124 #define UPI41_FEATURE   0x04
125 #define I802X_FEATURE   0x08
126 #define I8048_FEATURE   (MB_FEATURE | EXT_BUS_FEATURE)
127 
128 
129 /***************************************************************************
130     MACROS
131 ***************************************************************************/
132 
133 /* r0-r7 map to memory via the regptr */
134 #define R0              m_regptr[0]
135 #define R1              m_regptr[1]
136 #define R2              m_regptr[2]
137 #define R3              m_regptr[3]
138 #define R4              m_regptr[4]
139 #define R5              m_regptr[5]
140 #define R6              m_regptr[6]
141 #define R7              m_regptr[7]
142 
143 
144 
145 DEFINE_DEVICE_TYPE(I8021,   i8021_device,   "i8021",   "Intel 8021")
146 DEFINE_DEVICE_TYPE(I8022,   i8022_device,   "i8022",   "Intel 8022")
147 DEFINE_DEVICE_TYPE(I8035,   i8035_device,   "i8035",   "Intel 8035")
148 DEFINE_DEVICE_TYPE(I8048,   i8048_device,   "i8048",   "Intel 8048")
149 DEFINE_DEVICE_TYPE(I8648,   i8648_device,   "i8648",   "Intel 8648")
150 DEFINE_DEVICE_TYPE(I8748,   i8748_device,   "i8748",   "Intel 8748")
151 DEFINE_DEVICE_TYPE(I8039,   i8039_device,   "i8039",   "Intel 8039")
152 DEFINE_DEVICE_TYPE(I8049,   i8049_device,   "i8049",   "Intel 8049")
153 DEFINE_DEVICE_TYPE(I8749,   i8749_device,   "i8749",   "Intel 8749")
154 DEFINE_DEVICE_TYPE(I8040,   i8040_device,   "i8040",   "Intel 8040")
155 DEFINE_DEVICE_TYPE(I8050,   i8050_device,   "i8050",   "Intel 8050")
156 DEFINE_DEVICE_TYPE(I8041A,  i8041a_device,  "i8041a",  "Intel 8041A")
157 DEFINE_DEVICE_TYPE(I8741A,  i8741a_device,  "i8741a",  "Intel 8741A")
158 DEFINE_DEVICE_TYPE(I8041AH, i8041ah_device, "i8041ah", "Intel 8041AH")
159 DEFINE_DEVICE_TYPE(I8741AH, i8741ah_device, "i8741ah", "Intel 8741AH")
160 DEFINE_DEVICE_TYPE(I8042,   i8042_device,   "i8042",   "Intel 8042")
161 DEFINE_DEVICE_TYPE(I8742,   i8742_device,   "i8742",   "Intel 8742")
162 DEFINE_DEVICE_TYPE(I8042AH, i8042ah_device, "i8042ah", "Intel 8042AH")
163 DEFINE_DEVICE_TYPE(I8742AH, i8742ah_device, "i8742ah", "Intel 8742AH")
164 DEFINE_DEVICE_TYPE(MB8884,  mb8884_device,  "mb8884",  "MB8884")
165 DEFINE_DEVICE_TYPE(N7751,   n7751_device,   "n7751",   "N7751")
166 DEFINE_DEVICE_TYPE(M58715,  m58715_device,  "m58715",  "M58715")
167 
168 
169 /***************************************************************************
170     ADDRESS MAPS
171 ***************************************************************************/
172 
173 /* FIXME: the memory maps should probably support rom banking for EA */
program_10bit(address_map & map)174 void mcs48_cpu_device::program_10bit(address_map &map)
175 {
176 	map(0x000, 0x3ff).rom();
177 }
178 
program_11bit(address_map & map)179 void mcs48_cpu_device::program_11bit(address_map &map)
180 {
181 	map(0x000, 0x7ff).rom();
182 }
183 
program_12bit(address_map & map)184 void mcs48_cpu_device::program_12bit(address_map &map)
185 {
186 	map(0x000, 0xfff).rom();
187 }
188 
data_6bit(address_map & map)189 void mcs48_cpu_device::data_6bit(address_map &map)
190 {
191 	map(0x00, 0x3f).ram().share("data");
192 }
193 
data_7bit(address_map & map)194 void mcs48_cpu_device::data_7bit(address_map &map)
195 {
196 	map(0x00, 0x7f).ram().share("data");
197 }
198 
data_8bit(address_map & map)199 void mcs48_cpu_device::data_8bit(address_map &map)
200 {
201 	map(0x00, 0xff).ram().share("data");
202 }
203 
204 
mcs48_cpu_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,int rom_size,int ram_size,uint8_t feature_mask,const mcs48_cpu_device::mcs48_ophandler * opcode_table)205 mcs48_cpu_device::mcs48_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int rom_size, int ram_size, uint8_t feature_mask, const mcs48_cpu_device::mcs48_ophandler *opcode_table)
206 	: cpu_device(mconfig, type, tag, owner, clock)
207 	, m_program_config("program", ENDIANNESS_LITTLE, 8, (feature_mask & MB_FEATURE) != 0 ? 12 : 11, 0
208 					   , (rom_size == 1024) ? address_map_constructor(FUNC(mcs48_cpu_device::program_10bit), this) : (rom_size == 2048) ? address_map_constructor(FUNC(mcs48_cpu_device::program_11bit), this) : (rom_size == 4096) ? address_map_constructor(FUNC(mcs48_cpu_device::program_12bit), this) : address_map_constructor())
209 	, m_data_config("data", ENDIANNESS_LITTLE, 8, ( ( ram_size == 64 ) ? 6 : ( ( ram_size == 128 ) ? 7 : 8 ) ), 0
210 					, (ram_size == 64) ? address_map_constructor(FUNC(mcs48_cpu_device::data_6bit), this) : (ram_size == 128) ? address_map_constructor(FUNC(mcs48_cpu_device::data_7bit), this) : address_map_constructor(FUNC(mcs48_cpu_device::data_8bit), this))
211 	, m_io_config("io", ENDIANNESS_LITTLE, 8, 8, 0)
212 	, m_port_in_cb(*this)
213 	, m_port_out_cb(*this)
214 	, m_bus_in_cb(*this)
215 	, m_bus_out_cb(*this)
216 	, m_test_in_cb(*this)
217 	, m_t0_clk_func(*this)
218 	, m_prog_out_cb(*this)
219 	, m_psw(0)
220 	, m_dataptr(*this, "data")
221 	, m_feature_mask(feature_mask)
222 	, m_int_rom_size(rom_size)
223 	, m_opcode_table(opcode_table)
224 {
225 	// Sanity checks
226 	if ( ram_size != 64 && ram_size != 128 && ram_size != 256 )
227 	{
228 		fatalerror("mcs48: Invalid RAM size\n");
229 	}
230 
231 	if ( rom_size != 0 && rom_size != 1024 && rom_size != 2048 && rom_size != 4096 )
232 	{
233 		fatalerror("mcs48: Invalid ROM size\n");
234 	}
235 }
236 
i8021_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)237 i8021_device::i8021_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
238 	: mcs48_cpu_device(mconfig, I8021, tag, owner, clock, 1024, 64, I802X_FEATURE, s_i8021_opcodes)
239 {
240 }
241 
i8022_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)242 i8022_device::i8022_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
243 	: mcs48_cpu_device(mconfig, I8022, tag, owner, clock, 2048, 128, I802X_FEATURE, s_i8022_opcodes)
244 {
245 }
246 
i8035_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)247 i8035_device::i8035_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
248 	: mcs48_cpu_device(mconfig, I8035, tag, owner, clock, 0, 64, I8048_FEATURE, s_mcs48_opcodes)
249 {
250 }
251 
i8048_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)252 i8048_device::i8048_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
253 	: mcs48_cpu_device(mconfig, I8048, tag, owner, clock, 1024, 64, I8048_FEATURE, s_mcs48_opcodes)
254 {
255 }
256 
i8648_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)257 i8648_device::i8648_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
258 	: mcs48_cpu_device(mconfig, I8648, tag, owner, clock, 1024, 64, I8048_FEATURE, s_mcs48_opcodes)
259 {
260 }
261 
i8748_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)262 i8748_device::i8748_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
263 	: mcs48_cpu_device(mconfig, I8748, tag, owner, clock, 1024, 64, I8048_FEATURE, s_mcs48_opcodes)
264 {
265 }
266 
i8039_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)267 i8039_device::i8039_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
268 	: mcs48_cpu_device(mconfig, I8039, tag, owner, clock, 0, 128, I8048_FEATURE, s_mcs48_opcodes)
269 {
270 }
271 
i8049_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)272 i8049_device::i8049_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
273 	: mcs48_cpu_device(mconfig, I8049, tag, owner, clock, 2048, 128, I8048_FEATURE, s_mcs48_opcodes)
274 {
275 }
276 
i8749_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)277 i8749_device::i8749_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
278 	: mcs48_cpu_device(mconfig, I8749, tag, owner, clock, 2048, 128, I8048_FEATURE, s_mcs48_opcodes)
279 {
280 }
281 
i8040_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)282 i8040_device::i8040_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
283 	: mcs48_cpu_device(mconfig, I8040, tag, owner, clock, 0, 256, I8048_FEATURE, s_mcs48_opcodes)
284 {
285 }
286 
i8050_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)287 i8050_device::i8050_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
288 	: mcs48_cpu_device(mconfig, I8050, tag, owner, clock, 4096, 256, I8048_FEATURE, s_mcs48_opcodes)
289 {
290 }
291 
mb8884_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)292 mb8884_device::mb8884_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
293 	: mcs48_cpu_device(mconfig, MB8884, tag, owner, clock, 0, 64, I8048_FEATURE, s_mcs48_opcodes)
294 {
295 }
296 
n7751_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)297 n7751_device::n7751_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
298 	: mcs48_cpu_device(mconfig, N7751, tag, owner, clock, 1024, 64, I8048_FEATURE, s_mcs48_opcodes)
299 {
300 }
301 
m58715_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)302 m58715_device::m58715_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
303 	: mcs48_cpu_device(mconfig, M58715, tag, owner, clock, 2048, 128, I8048_FEATURE, s_mcs48_opcodes)
304 {
305 }
306 
upi41_cpu_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,int rom_size,int ram_size)307 upi41_cpu_device::upi41_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int rom_size, int ram_size)
308 	: mcs48_cpu_device(mconfig, type, tag, owner, clock, rom_size, ram_size, UPI41_FEATURE, s_upi41_opcodes)
309 {
310 }
311 
i8041a_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)312 i8041a_device::i8041a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
313 	: upi41_cpu_device(mconfig, I8041A, tag, owner, clock, 1024, 64)
314 {
315 }
316 
i8741a_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)317 i8741a_device::i8741a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
318 	: upi41_cpu_device(mconfig, I8741A, tag, owner, clock, 1024, 64)
319 {
320 }
321 
i8041ah_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)322 i8041ah_device::i8041ah_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
323 	: upi41_cpu_device(mconfig, I8041AH, tag, owner, clock, 1024, 128)
324 {
325 }
326 
i8741ah_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)327 i8741ah_device::i8741ah_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
328 	: upi41_cpu_device(mconfig, I8741AH, tag, owner, clock, 1024, 128)
329 {
330 }
331 
i8042_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)332 i8042_device::i8042_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
333 	: upi41_cpu_device(mconfig, I8042, tag, owner, clock, 2048, 128)
334 {
335 }
336 
i8742_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)337 i8742_device::i8742_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
338 	: upi41_cpu_device(mconfig, I8742, tag, owner, clock, 2048, 128)
339 {
340 }
341 
i8042ah_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)342 i8042ah_device::i8042ah_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
343 	: upi41_cpu_device(mconfig, I8042AH, tag, owner, clock, 2048, 256)
344 {
345 }
346 
i8742ah_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)347 i8742ah_device::i8742ah_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
348 	: upi41_cpu_device(mconfig, I8742AH, tag, owner, clock, 2048, 256)
349 {
350 }
351 
memory_space_config() const352 device_memory_interface::space_config_vector mcs48_cpu_device::memory_space_config() const
353 {
354 	if ((m_feature_mask & EXT_BUS_FEATURE) != 0)
355 		return space_config_vector {
356 			std::make_pair(AS_PROGRAM, &m_program_config),
357 			std::make_pair(AS_DATA,    &m_data_config),
358 			std::make_pair(AS_IO,      &m_io_config)
359 		};
360 	else
361 		return space_config_vector {
362 			std::make_pair(AS_PROGRAM, &m_program_config),
363 			std::make_pair(AS_DATA,    &m_data_config)
364 		};
365 }
366 
create_disassembler()367 std::unique_ptr<util::disasm_interface> mcs48_cpu_device::create_disassembler()
368 {
369 	return std::make_unique<mcs48_disassembler>((m_feature_mask & UPI41_FEATURE) != 0, (m_feature_mask & I802X_FEATURE) != 0);
370 }
371 
372 /***************************************************************************
373     INLINE FUNCTIONS
374 ***************************************************************************/
375 
376 /*-------------------------------------------------
377     opcode_fetch - fetch an opcode byte
378 -------------------------------------------------*/
379 
opcode_fetch()380 uint8_t mcs48_cpu_device::opcode_fetch()
381 {
382 	uint16_t address = m_pc;
383 	m_pc = ((m_pc + 1) & 0x7ff) | (m_pc & 0x800);
384 	return m_program.read_byte(address);
385 }
386 
387 
388 /*-------------------------------------------------
389     argument_fetch - fetch an opcode argument
390     byte
391 -------------------------------------------------*/
392 
argument_fetch()393 uint8_t mcs48_cpu_device::argument_fetch()
394 {
395 	uint16_t address = m_pc;
396 	m_pc = ((m_pc + 1) & 0x7ff) | (m_pc & 0x800);
397 	return m_program.read_byte(address);
398 }
399 
400 
401 /*-------------------------------------------------
402     update_regptr - update the regptr member to
403     point to the appropriate register bank
404 -------------------------------------------------*/
405 
update_regptr()406 void mcs48_cpu_device::update_regptr()
407 {
408 	m_regptr = &m_dataptr[(m_psw & B_FLAG) ? 24 : 0];
409 }
410 
411 
412 /*-------------------------------------------------
413     push_pc_psw - push the m_pc and m_psw values onto
414     the stack
415 -------------------------------------------------*/
416 
push_pc_psw()417 void mcs48_cpu_device::push_pc_psw()
418 {
419 	uint8_t sp = m_psw & 0x07;
420 	ram_w(8 + 2*sp, m_pc);
421 	ram_w(9 + 2*sp, ((m_pc >> 8) & 0x0f) | (m_psw & 0xf0));
422 	m_psw = (m_psw & 0xf0) | ((sp + 1) & 0x07);
423 }
424 
425 
426 /*-------------------------------------------------
427     pull_pc_psw - pull the PC and PSW values from
428     the stack
429 -------------------------------------------------*/
430 
pull_pc_psw()431 void mcs48_cpu_device::pull_pc_psw()
432 {
433 	uint8_t sp = (m_psw - 1) & 0x07;
434 	m_pc = ram_r(8 + 2*sp);
435 	m_pc |= ram_r(9 + 2*sp) << 8;
436 	m_psw = ((m_pc >> 8) & 0xf0) | sp;
437 	m_pc &= 0xfff;
438 	update_regptr();
439 }
440 
441 
442 /*-------------------------------------------------
443     pull_pc - pull the PC value from the stack,
444     leaving the upper part of PSW intact
445 -------------------------------------------------*/
446 
pull_pc()447 void mcs48_cpu_device::pull_pc()
448 {
449 	uint8_t sp = (m_psw - 1) & 0x07;
450 	m_pc = ram_r(8 + 2*sp);
451 	m_pc |= ram_r(9 + 2*sp) << 8;
452 	m_pc &= 0xfff;
453 	m_psw = (m_psw & 0xf0) | sp;
454 }
455 
456 
457 /*-------------------------------------------------
458     execute_add - perform the logic of an ADD
459     instruction
460 -------------------------------------------------*/
461 
execute_add(uint8_t dat)462 void mcs48_cpu_device::execute_add(uint8_t dat)
463 {
464 	uint16_t temp = m_a + dat;
465 	uint16_t temp4 = (m_a & 0x0f) + (dat & 0x0f);
466 
467 	m_psw &= ~(C_FLAG | A_FLAG);
468 	m_psw |= (temp4 << 2) & A_FLAG;
469 	m_psw |= (temp >> 1) & C_FLAG;
470 	m_a = temp;
471 }
472 
473 
474 /*-------------------------------------------------
475     execute_addc - perform the logic of an ADDC
476     instruction
477 -------------------------------------------------*/
478 
execute_addc(uint8_t dat)479 void mcs48_cpu_device::execute_addc(uint8_t dat)
480 {
481 	uint8_t carryin = (m_psw & C_FLAG) >> 7;
482 	uint16_t temp = m_a + dat + carryin;
483 	uint16_t temp4 = (m_a & 0x0f) + (dat & 0x0f) + carryin;
484 
485 	m_psw &= ~(C_FLAG | A_FLAG);
486 	m_psw |= (temp4 << 2) & A_FLAG;
487 	m_psw |= (temp >> 1) & C_FLAG;
488 	m_a = temp;
489 }
490 
491 
492 /*-------------------------------------------------
493     execute_jmp - perform the logic of a JMP
494     instruction
495 -------------------------------------------------*/
496 
execute_jmp(uint16_t address)497 void mcs48_cpu_device::execute_jmp(uint16_t address)
498 {
499 	uint16_t a11 = (m_irq_in_progress) ? 0 : m_a11;
500 	m_pc = address | a11;
501 }
502 
503 
504 /*-------------------------------------------------
505     execute_call - perform the logic of a CALL
506     instruction
507 -------------------------------------------------*/
508 
execute_call(uint16_t address)509 void mcs48_cpu_device::execute_call(uint16_t address)
510 {
511 	push_pc_psw();
512 	execute_jmp(address);
513 }
514 
515 
516 /*-------------------------------------------------
517     execute_jcc - perform the logic of a
518     conditional jump instruction
519 -------------------------------------------------*/
520 
execute_jcc(bool result)521 void mcs48_cpu_device::execute_jcc(bool result)
522 {
523 	uint16_t pch = m_pc & 0xf00;
524 	uint8_t offset = argument_fetch();
525 	if (result != 0)
526 		m_pc = pch | offset;
527 }
528 
529 
530 /*-------------------------------------------------
531     p2_mask - return the mask of bits that the
532     code can directly affect
533 -------------------------------------------------*/
534 
p2_mask()535 uint8_t mcs48_cpu_device::p2_mask()
536 {
537 	uint8_t result = 0xff;
538 	if ((m_feature_mask & UPI41_FEATURE) == 0)
539 		return result;
540 	if (m_flags_enabled)
541 		result &= ~(P2_OBF | P2_NIBF);
542 	if (m_dma_enabled)
543 		result &= ~(P2_DRQ | P2_NDACK);
544 	return result;
545 }
546 
547 
548 /*-------------------------------------------------
549     expander_operation - perform an operation via
550     the 8243 expander chip
551 -------------------------------------------------*/
552 
expander_operation(expander_op operation,uint8_t port)553 void mcs48_cpu_device::expander_operation(expander_op operation, uint8_t port)
554 {
555 	// put opcode on low 4 bits of P2 (overwriting latch)
556 	port_w(2, m_p2 = (m_p2 & 0xf0) | (uint8_t(operation) << 2) | (port & 3));
557 
558 	// generate high-to-low transition on PROG line
559 	prog_w(0);
560 
561 	// transfer data on low 4 bits of P2
562 	if (operation != EXPANDER_OP_READ)
563 		port_w(2, m_p2 = (m_p2 & 0xf0) | (m_a & 0x0f));
564 	else
565 	{
566 		// place P20-P23 in input mode
567 		port_w(2, m_p2 |= 0x0f);
568 
569 		// input data to lower 4 bits of A (upper 4 bits are cleared)
570 		m_a = port_r(2) & 0x0f;
571 	}
572 
573 	// generate low-to-high transition on PROG line
574 	prog_w(1);
575 }
576 
577 
578 
579 /***************************************************************************
580     OPCODE HANDLERS
581 ***************************************************************************/
582 
583 #define OPHANDLER(_name) void mcs48_cpu_device::_name()
584 
585 
OPHANDLER(illegal)586 OPHANDLER( illegal )
587 {
588 	burn_cycles(1);
589 	logerror("MCS-48 PC:%04X - Illegal opcode = %02x\n", m_prevpc, program_r(m_prevpc));
590 }
591 
OPHANDLER(add_a_r0)592 OPHANDLER( add_a_r0 )       { burn_cycles(1); execute_add(R0); }
OPHANDLER(add_a_r1)593 OPHANDLER( add_a_r1 )       { burn_cycles(1); execute_add(R1); }
OPHANDLER(add_a_r2)594 OPHANDLER( add_a_r2 )       { burn_cycles(1); execute_add(R2); }
OPHANDLER(add_a_r3)595 OPHANDLER( add_a_r3 )       { burn_cycles(1); execute_add(R3); }
OPHANDLER(add_a_r4)596 OPHANDLER( add_a_r4 )       { burn_cycles(1); execute_add(R4); }
OPHANDLER(add_a_r5)597 OPHANDLER( add_a_r5 )       { burn_cycles(1); execute_add(R5); }
OPHANDLER(add_a_r6)598 OPHANDLER( add_a_r6 )       { burn_cycles(1); execute_add(R6); }
OPHANDLER(add_a_r7)599 OPHANDLER( add_a_r7 )       { burn_cycles(1); execute_add(R7); }
OPHANDLER(add_a_xr0)600 OPHANDLER( add_a_xr0 )      { burn_cycles(1); execute_add(ram_r(R0)); }
OPHANDLER(add_a_xr1)601 OPHANDLER( add_a_xr1 )      { burn_cycles(1); execute_add(ram_r(R1)); }
OPHANDLER(add_a_n)602 OPHANDLER( add_a_n )        { burn_cycles(2); execute_add(argument_fetch()); }
603 
OPHANDLER(adc_a_r0)604 OPHANDLER( adc_a_r0 )       { burn_cycles(1); execute_addc(R0); }
OPHANDLER(adc_a_r1)605 OPHANDLER( adc_a_r1 )       { burn_cycles(1); execute_addc(R1); }
OPHANDLER(adc_a_r2)606 OPHANDLER( adc_a_r2 )       { burn_cycles(1); execute_addc(R2); }
OPHANDLER(adc_a_r3)607 OPHANDLER( adc_a_r3 )       { burn_cycles(1); execute_addc(R3); }
OPHANDLER(adc_a_r4)608 OPHANDLER( adc_a_r4 )       { burn_cycles(1); execute_addc(R4); }
OPHANDLER(adc_a_r5)609 OPHANDLER( adc_a_r5 )       { burn_cycles(1); execute_addc(R5); }
OPHANDLER(adc_a_r6)610 OPHANDLER( adc_a_r6 )       { burn_cycles(1); execute_addc(R6); }
OPHANDLER(adc_a_r7)611 OPHANDLER( adc_a_r7 )       { burn_cycles(1); execute_addc(R7); }
OPHANDLER(adc_a_xr0)612 OPHANDLER( adc_a_xr0 )      { burn_cycles(1); execute_addc(ram_r(R0)); }
OPHANDLER(adc_a_xr1)613 OPHANDLER( adc_a_xr1 )      { burn_cycles(1); execute_addc(ram_r(R1)); }
OPHANDLER(adc_a_n)614 OPHANDLER( adc_a_n )        { burn_cycles(2); execute_addc(argument_fetch()); }
615 
OPHANDLER(anl_a_r0)616 OPHANDLER( anl_a_r0 )       { burn_cycles(1); m_a &= R0; }
OPHANDLER(anl_a_r1)617 OPHANDLER( anl_a_r1 )       { burn_cycles(1); m_a &= R1; }
OPHANDLER(anl_a_r2)618 OPHANDLER( anl_a_r2 )       { burn_cycles(1); m_a &= R2; }
OPHANDLER(anl_a_r3)619 OPHANDLER( anl_a_r3 )       { burn_cycles(1); m_a &= R3; }
OPHANDLER(anl_a_r4)620 OPHANDLER( anl_a_r4 )       { burn_cycles(1); m_a &= R4; }
OPHANDLER(anl_a_r5)621 OPHANDLER( anl_a_r5 )       { burn_cycles(1); m_a &= R5; }
OPHANDLER(anl_a_r6)622 OPHANDLER( anl_a_r6 )       { burn_cycles(1); m_a &= R6; }
OPHANDLER(anl_a_r7)623 OPHANDLER( anl_a_r7 )       { burn_cycles(1); m_a &= R7; }
OPHANDLER(anl_a_xr0)624 OPHANDLER( anl_a_xr0 )      { burn_cycles(1); m_a &= ram_r(R0); }
OPHANDLER(anl_a_xr1)625 OPHANDLER( anl_a_xr1 )      { burn_cycles(1); m_a &= ram_r(R1); }
OPHANDLER(anl_a_n)626 OPHANDLER( anl_a_n )        { burn_cycles(2); m_a &= argument_fetch(); }
627 
OPHANDLER(anl_bus_n)628 OPHANDLER( anl_bus_n )      { burn_cycles(2); bus_w(bus_r() & argument_fetch()); }
OPHANDLER(anl_p1_n)629 OPHANDLER( anl_p1_n )       { burn_cycles(2); port_w(1, m_p1 &= argument_fetch()); }
OPHANDLER(anl_p2_n)630 OPHANDLER( anl_p2_n )       { burn_cycles(2); port_w(2, m_p2 &= argument_fetch() | ~p2_mask()); }
OPHANDLER(anld_p4_a)631 OPHANDLER( anld_p4_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_AND, 4); }
OPHANDLER(anld_p5_a)632 OPHANDLER( anld_p5_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_AND, 5); }
OPHANDLER(anld_p6_a)633 OPHANDLER( anld_p6_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_AND, 6); }
OPHANDLER(anld_p7_a)634 OPHANDLER( anld_p7_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_AND, 7); }
635 
OPHANDLER(call_0)636 OPHANDLER( call_0 )         { burn_cycles(2); execute_call(argument_fetch() | 0x000); }
OPHANDLER(call_1)637 OPHANDLER( call_1 )         { burn_cycles(2); execute_call(argument_fetch() | 0x100); }
OPHANDLER(call_2)638 OPHANDLER( call_2 )         { burn_cycles(2); execute_call(argument_fetch() | 0x200); }
OPHANDLER(call_3)639 OPHANDLER( call_3 )         { burn_cycles(2); execute_call(argument_fetch() | 0x300); }
OPHANDLER(call_4)640 OPHANDLER( call_4 )         { burn_cycles(2); execute_call(argument_fetch() | 0x400); }
OPHANDLER(call_5)641 OPHANDLER( call_5 )         { burn_cycles(2); execute_call(argument_fetch() | 0x500); }
OPHANDLER(call_6)642 OPHANDLER( call_6 )         { burn_cycles(2); execute_call(argument_fetch() | 0x600); }
OPHANDLER(call_7)643 OPHANDLER( call_7 )         { burn_cycles(2); execute_call(argument_fetch() | 0x700); }
644 
OPHANDLER(clr_a)645 OPHANDLER( clr_a )          { burn_cycles(1); m_a = 0; }
OPHANDLER(clr_c)646 OPHANDLER( clr_c )          { burn_cycles(1); m_psw &= ~C_FLAG; }
OPHANDLER(clr_f0)647 OPHANDLER( clr_f0 )         { burn_cycles(1); m_psw &= ~F_FLAG; m_sts &= ~STS_F0; }
OPHANDLER(clr_f1)648 OPHANDLER( clr_f1 )         { burn_cycles(1); m_sts &= ~STS_F1; }
649 
OPHANDLER(cpl_a)650 OPHANDLER( cpl_a )          { burn_cycles(1); m_a ^= 0xff; }
OPHANDLER(cpl_c)651 OPHANDLER( cpl_c )          { burn_cycles(1); m_psw ^= C_FLAG; }
OPHANDLER(cpl_f0)652 OPHANDLER( cpl_f0 )         { burn_cycles(1); m_psw ^= F_FLAG; m_sts ^= STS_F0; }
OPHANDLER(cpl_f1)653 OPHANDLER( cpl_f1 )         { burn_cycles(1); m_sts ^= STS_F1; }
654 
OPHANDLER(da_a)655 OPHANDLER( da_a )
656 {
657 	burn_cycles(1);
658 
659 	if ((m_a & 0x0f) > 0x09 || (m_psw & A_FLAG))
660 	{
661 		m_a += 0x06;
662 		if ((m_a & 0xf0) == 0x00)
663 			m_psw |= C_FLAG;
664 	}
665 	if ((m_a & 0xf0) > 0x90 || (m_psw & C_FLAG))
666 	{
667 		m_a += 0x60;
668 		m_psw |= C_FLAG;
669 	}
670 }
671 
OPHANDLER(dec_a)672 OPHANDLER( dec_a )          { burn_cycles(1); m_a--; }
OPHANDLER(dec_r0)673 OPHANDLER( dec_r0 )         { burn_cycles(1); R0--; }
OPHANDLER(dec_r1)674 OPHANDLER( dec_r1 )         { burn_cycles(1); R1--; }
OPHANDLER(dec_r2)675 OPHANDLER( dec_r2 )         { burn_cycles(1); R2--; }
OPHANDLER(dec_r3)676 OPHANDLER( dec_r3 )         { burn_cycles(1); R3--; }
OPHANDLER(dec_r4)677 OPHANDLER( dec_r4 )         { burn_cycles(1); R4--; }
OPHANDLER(dec_r5)678 OPHANDLER( dec_r5 )         { burn_cycles(1); R5--; }
OPHANDLER(dec_r6)679 OPHANDLER( dec_r6 )         { burn_cycles(1); R6--; }
OPHANDLER(dec_r7)680 OPHANDLER( dec_r7 )         { burn_cycles(1); R7--; }
681 
OPHANDLER(dis_i)682 OPHANDLER( dis_i )          { burn_cycles(1); m_xirq_enabled = false; }
OPHANDLER(dis_tcnti)683 OPHANDLER( dis_tcnti )      { burn_cycles(1); m_tirq_enabled = false; m_timer_overflow = false; }
684 
OPHANDLER(djnz_r0)685 OPHANDLER( djnz_r0 )        { burn_cycles(2); execute_jcc(--R0 != 0); }
OPHANDLER(djnz_r1)686 OPHANDLER( djnz_r1 )        { burn_cycles(2); execute_jcc(--R1 != 0); }
OPHANDLER(djnz_r2)687 OPHANDLER( djnz_r2 )        { burn_cycles(2); execute_jcc(--R2 != 0); }
OPHANDLER(djnz_r3)688 OPHANDLER( djnz_r3 )        { burn_cycles(2); execute_jcc(--R3 != 0); }
OPHANDLER(djnz_r4)689 OPHANDLER( djnz_r4 )        { burn_cycles(2); execute_jcc(--R4 != 0); }
OPHANDLER(djnz_r5)690 OPHANDLER( djnz_r5 )        { burn_cycles(2); execute_jcc(--R5 != 0); }
OPHANDLER(djnz_r6)691 OPHANDLER( djnz_r6 )        { burn_cycles(2); execute_jcc(--R6 != 0); }
OPHANDLER(djnz_r7)692 OPHANDLER( djnz_r7 )        { burn_cycles(2); execute_jcc(--R7 != 0); }
693 
OPHANDLER(en_i)694 OPHANDLER( en_i )           { burn_cycles(1); m_xirq_enabled = true; }
OPHANDLER(en_tcnti)695 OPHANDLER( en_tcnti )       { burn_cycles(1); m_tirq_enabled = true; }
OPHANDLER(en_dma)696 OPHANDLER( en_dma )         { burn_cycles(1); m_dma_enabled = true; port_w(2, m_p2); }
OPHANDLER(en_flags)697 OPHANDLER( en_flags )       { burn_cycles(1); m_flags_enabled = true; port_w(2, m_p2); }
OPHANDLER(ent0_clk)698 OPHANDLER( ent0_clk )
699 {
700 	burn_cycles(1);
701 
702 	if (!m_t0_clk_func.isnull())
703 		m_t0_clk_func(clock() / 3);
704 	else
705 		logerror("T0 clock enabled\n");
706 }
707 
OPHANDLER(in_a_p0)708 OPHANDLER( in_a_p0 )        { burn_cycles(2); m_a = bus_r() & m_dbbo; }
OPHANDLER(in_a_p1)709 OPHANDLER( in_a_p1 )        { burn_cycles(2); m_a = port_r(1) & m_p1; }
OPHANDLER(in_a_p2)710 OPHANDLER( in_a_p2 )        { burn_cycles(2); m_a = port_r(2) & m_p2; }
OPHANDLER(ins_a_bus)711 OPHANDLER( ins_a_bus )      { burn_cycles(2); m_a = bus_r(); }
OPHANDLER(in_a_dbb)712 OPHANDLER( in_a_dbb )
713 {
714 	burn_cycles(2);
715 
716 	/* acknowledge the IBF IRQ and clear the bit in STS */
717 	if ((m_sts & STS_IBF) != 0)
718 		standard_irq_callback(UPI41_INPUT_IBF);
719 	m_sts &= ~STS_IBF;
720 
721 	/* if P2 flags are enabled, update the state of P2 */
722 	if (m_flags_enabled && (m_p2 & P2_NIBF) == 0)
723 		port_w(2, m_p2 |= P2_NIBF);
724 	m_a = m_dbbi;
725 }
726 
OPHANDLER(inc_a)727 OPHANDLER( inc_a )          { burn_cycles(1); m_a++; }
OPHANDLER(inc_r0)728 OPHANDLER( inc_r0 )         { burn_cycles(1); R0++; }
OPHANDLER(inc_r1)729 OPHANDLER( inc_r1 )         { burn_cycles(1); R1++; }
OPHANDLER(inc_r2)730 OPHANDLER( inc_r2 )         { burn_cycles(1); R2++; }
OPHANDLER(inc_r3)731 OPHANDLER( inc_r3 )         { burn_cycles(1); R3++; }
OPHANDLER(inc_r4)732 OPHANDLER( inc_r4 )         { burn_cycles(1); R4++; }
OPHANDLER(inc_r5)733 OPHANDLER( inc_r5 )         { burn_cycles(1); R5++; }
OPHANDLER(inc_r6)734 OPHANDLER( inc_r6 )         { burn_cycles(1); R6++; }
OPHANDLER(inc_r7)735 OPHANDLER( inc_r7 )         { burn_cycles(1); R7++; }
OPHANDLER(inc_xr0)736 OPHANDLER( inc_xr0 )        { burn_cycles(1); ram_w(R0, ram_r(R0) + 1); }
OPHANDLER(inc_xr1)737 OPHANDLER( inc_xr1 )        { burn_cycles(1); ram_w(R1, ram_r(R1) + 1); }
738 
OPHANDLER(jb_0)739 OPHANDLER( jb_0 )           { burn_cycles(2); execute_jcc((m_a & 0x01) != 0); }
OPHANDLER(jb_1)740 OPHANDLER( jb_1 )           { burn_cycles(2); execute_jcc((m_a & 0x02) != 0); }
OPHANDLER(jb_2)741 OPHANDLER( jb_2 )           { burn_cycles(2); execute_jcc((m_a & 0x04) != 0); }
OPHANDLER(jb_3)742 OPHANDLER( jb_3 )           { burn_cycles(2); execute_jcc((m_a & 0x08) != 0); }
OPHANDLER(jb_4)743 OPHANDLER( jb_4 )           { burn_cycles(2); execute_jcc((m_a & 0x10) != 0); }
OPHANDLER(jb_5)744 OPHANDLER( jb_5 )           { burn_cycles(2); execute_jcc((m_a & 0x20) != 0); }
OPHANDLER(jb_6)745 OPHANDLER( jb_6 )           { burn_cycles(2); execute_jcc((m_a & 0x40) != 0); }
OPHANDLER(jb_7)746 OPHANDLER( jb_7 )           { burn_cycles(2); execute_jcc((m_a & 0x80) != 0); }
OPHANDLER(jc)747 OPHANDLER( jc )             { burn_cycles(2); execute_jcc((m_psw & C_FLAG) != 0); }
OPHANDLER(jf0)748 OPHANDLER( jf0 )            { burn_cycles(2); execute_jcc((m_psw & F_FLAG) != 0); }
OPHANDLER(jf1)749 OPHANDLER( jf1 )            { burn_cycles(2); execute_jcc((m_sts & STS_F1) != 0); }
OPHANDLER(jnc)750 OPHANDLER( jnc )            { burn_cycles(2); execute_jcc((m_psw & C_FLAG) == 0); }
OPHANDLER(jni)751 OPHANDLER( jni )            { burn_cycles(2); m_irq_polled = (m_irq_state == 0); execute_jcc(m_irq_state != 0); }
OPHANDLER(jnibf)752 OPHANDLER( jnibf )          { burn_cycles(2); m_irq_polled = (m_sts & STS_IBF) != 0; execute_jcc((m_sts & STS_IBF) == 0); }
OPHANDLER(jnt_0)753 OPHANDLER( jnt_0 )          { burn_cycles(2); execute_jcc(test_r(0) == 0); }
OPHANDLER(jnt_1)754 OPHANDLER( jnt_1 )          { burn_cycles(2); execute_jcc(test_r(1) == 0); }
OPHANDLER(jnz)755 OPHANDLER( jnz )            { burn_cycles(2); execute_jcc(m_a != 0); }
OPHANDLER(jobf)756 OPHANDLER( jobf )           { burn_cycles(2); execute_jcc((m_sts & STS_OBF) != 0); }
OPHANDLER(jtf)757 OPHANDLER( jtf )            { burn_cycles(2); execute_jcc(m_timer_flag); m_timer_flag = false; }
OPHANDLER(jt_0)758 OPHANDLER( jt_0 )           { burn_cycles(2); execute_jcc(test_r(0) != 0); }
OPHANDLER(jt_1)759 OPHANDLER( jt_1 )           { burn_cycles(2); execute_jcc(test_r(1) != 0); }
OPHANDLER(jz)760 OPHANDLER( jz )             { burn_cycles(2); execute_jcc(m_a == 0); }
761 
OPHANDLER(jmp_0)762 OPHANDLER( jmp_0 )          { burn_cycles(2); execute_jmp(argument_fetch() | 0x000); }
OPHANDLER(jmp_1)763 OPHANDLER( jmp_1 )          { burn_cycles(2); execute_jmp(argument_fetch() | 0x100); }
OPHANDLER(jmp_2)764 OPHANDLER( jmp_2 )          { burn_cycles(2); execute_jmp(argument_fetch() | 0x200); }
OPHANDLER(jmp_3)765 OPHANDLER( jmp_3 )          { burn_cycles(2); execute_jmp(argument_fetch() | 0x300); }
OPHANDLER(jmp_4)766 OPHANDLER( jmp_4 )          { burn_cycles(2); execute_jmp(argument_fetch() | 0x400); }
OPHANDLER(jmp_5)767 OPHANDLER( jmp_5 )          { burn_cycles(2); execute_jmp(argument_fetch() | 0x500); }
OPHANDLER(jmp_6)768 OPHANDLER( jmp_6 )          { burn_cycles(2); execute_jmp(argument_fetch() | 0x600); }
OPHANDLER(jmp_7)769 OPHANDLER( jmp_7 )          { burn_cycles(2); execute_jmp(argument_fetch() | 0x700); }
OPHANDLER(jmpp_xa)770 OPHANDLER( jmpp_xa )        { burn_cycles(2); m_pc &= 0xf00; m_pc |= program_r(m_pc | m_a); }
771 
OPHANDLER(mov_a_n)772 OPHANDLER( mov_a_n )        { burn_cycles(2); m_a = argument_fetch(); }
OPHANDLER(mov_a_psw)773 OPHANDLER( mov_a_psw )      { burn_cycles(1); m_a = m_psw | 0x08; }
OPHANDLER(mov_a_r0)774 OPHANDLER( mov_a_r0 )       { burn_cycles(1); m_a = R0; }
OPHANDLER(mov_a_r1)775 OPHANDLER( mov_a_r1 )       { burn_cycles(1); m_a = R1; }
OPHANDLER(mov_a_r2)776 OPHANDLER( mov_a_r2 )       { burn_cycles(1); m_a = R2; }
OPHANDLER(mov_a_r3)777 OPHANDLER( mov_a_r3 )       { burn_cycles(1); m_a = R3; }
OPHANDLER(mov_a_r4)778 OPHANDLER( mov_a_r4 )       { burn_cycles(1); m_a = R4; }
OPHANDLER(mov_a_r5)779 OPHANDLER( mov_a_r5 )       { burn_cycles(1); m_a = R5; }
OPHANDLER(mov_a_r6)780 OPHANDLER( mov_a_r6 )       { burn_cycles(1); m_a = R6; }
OPHANDLER(mov_a_r7)781 OPHANDLER( mov_a_r7 )       { burn_cycles(1); m_a = R7; }
OPHANDLER(mov_a_xr0)782 OPHANDLER( mov_a_xr0 )      { burn_cycles(1); m_a = ram_r(R0); }
OPHANDLER(mov_a_xr1)783 OPHANDLER( mov_a_xr1 )      { burn_cycles(1); m_a = ram_r(R1); }
OPHANDLER(mov_a_t)784 OPHANDLER( mov_a_t )        { burn_cycles(1); m_a = m_timer; }
785 
OPHANDLER(mov_psw_a)786 OPHANDLER( mov_psw_a )      { burn_cycles(1); m_psw = m_a & ~0x08; update_regptr(); }
OPHANDLER(mov_sts_a)787 OPHANDLER( mov_sts_a )      { burn_cycles(1); m_sts = (m_sts & 0x0f) | (m_a & 0xf0); }
OPHANDLER(mov_r0_a)788 OPHANDLER( mov_r0_a )       { burn_cycles(1); R0 = m_a; }
OPHANDLER(mov_r1_a)789 OPHANDLER( mov_r1_a )       { burn_cycles(1); R1 = m_a; }
OPHANDLER(mov_r2_a)790 OPHANDLER( mov_r2_a )       { burn_cycles(1); R2 = m_a; }
OPHANDLER(mov_r3_a)791 OPHANDLER( mov_r3_a )       { burn_cycles(1); R3 = m_a; }
OPHANDLER(mov_r4_a)792 OPHANDLER( mov_r4_a )       { burn_cycles(1); R4 = m_a; }
OPHANDLER(mov_r5_a)793 OPHANDLER( mov_r5_a )       { burn_cycles(1); R5 = m_a; }
OPHANDLER(mov_r6_a)794 OPHANDLER( mov_r6_a )       { burn_cycles(1); R6 = m_a; }
OPHANDLER(mov_r7_a)795 OPHANDLER( mov_r7_a )       { burn_cycles(1); R7 = m_a; }
OPHANDLER(mov_r0_n)796 OPHANDLER( mov_r0_n )       { burn_cycles(2); R0 = argument_fetch(); }
OPHANDLER(mov_r1_n)797 OPHANDLER( mov_r1_n )       { burn_cycles(2); R1 = argument_fetch(); }
OPHANDLER(mov_r2_n)798 OPHANDLER( mov_r2_n )       { burn_cycles(2); R2 = argument_fetch(); }
OPHANDLER(mov_r3_n)799 OPHANDLER( mov_r3_n )       { burn_cycles(2); R3 = argument_fetch(); }
OPHANDLER(mov_r4_n)800 OPHANDLER( mov_r4_n )       { burn_cycles(2); R4 = argument_fetch(); }
OPHANDLER(mov_r5_n)801 OPHANDLER( mov_r5_n )       { burn_cycles(2); R5 = argument_fetch(); }
OPHANDLER(mov_r6_n)802 OPHANDLER( mov_r6_n )       { burn_cycles(2); R6 = argument_fetch(); }
OPHANDLER(mov_r7_n)803 OPHANDLER( mov_r7_n )       { burn_cycles(2); R7 = argument_fetch(); }
OPHANDLER(mov_t_a)804 OPHANDLER( mov_t_a )        { burn_cycles(1); m_timer = m_a; }
OPHANDLER(mov_xr0_a)805 OPHANDLER( mov_xr0_a )      { burn_cycles(1); ram_w(R0, m_a); }
OPHANDLER(mov_xr1_a)806 OPHANDLER( mov_xr1_a )      { burn_cycles(1); ram_w(R1, m_a); }
OPHANDLER(mov_xr0_n)807 OPHANDLER( mov_xr0_n )      { burn_cycles(2); ram_w(R0, argument_fetch()); }
OPHANDLER(mov_xr1_n)808 OPHANDLER( mov_xr1_n )      { burn_cycles(2); ram_w(R1, argument_fetch()); }
809 
OPHANDLER(movd_a_p4)810 OPHANDLER( movd_a_p4 )      { burn_cycles(2); expander_operation(EXPANDER_OP_READ, 4); }
OPHANDLER(movd_a_p5)811 OPHANDLER( movd_a_p5 )      { burn_cycles(2); expander_operation(EXPANDER_OP_READ, 5); }
OPHANDLER(movd_a_p6)812 OPHANDLER( movd_a_p6 )      { burn_cycles(2); expander_operation(EXPANDER_OP_READ, 6); }
OPHANDLER(movd_a_p7)813 OPHANDLER( movd_a_p7 )      { burn_cycles(2); expander_operation(EXPANDER_OP_READ, 7); }
OPHANDLER(movd_p4_a)814 OPHANDLER( movd_p4_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_WRITE, 4); }
OPHANDLER(movd_p5_a)815 OPHANDLER( movd_p5_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_WRITE, 5); }
OPHANDLER(movd_p6_a)816 OPHANDLER( movd_p6_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_WRITE, 6); }
OPHANDLER(movd_p7_a)817 OPHANDLER( movd_p7_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_WRITE, 7); }
818 
OPHANDLER(movp_a_xa)819 OPHANDLER( movp_a_xa )      { burn_cycles(2); m_a = program_r((m_pc & 0xf00) | m_a); }
OPHANDLER(movp3_a_xa)820 OPHANDLER( movp3_a_xa )     { burn_cycles(2); m_a = program_r(0x300 | m_a); }
821 
OPHANDLER(movx_a_xr0)822 OPHANDLER( movx_a_xr0 )     { burn_cycles(2); m_a = ext_r(R0); }
OPHANDLER(movx_a_xr1)823 OPHANDLER( movx_a_xr1 )     { burn_cycles(2); m_a = ext_r(R1); }
OPHANDLER(movx_xr0_a)824 OPHANDLER( movx_xr0_a )     { burn_cycles(2); ext_w(R0, m_a); }
OPHANDLER(movx_xr1_a)825 OPHANDLER( movx_xr1_a )     { burn_cycles(2); ext_w(R1, m_a); }
826 
OPHANDLER(nop)827 OPHANDLER( nop )            { burn_cycles(1); }
828 
OPHANDLER(orl_a_r0)829 OPHANDLER( orl_a_r0 )       { burn_cycles(1); m_a |= R0; }
OPHANDLER(orl_a_r1)830 OPHANDLER( orl_a_r1 )       { burn_cycles(1); m_a |= R1; }
OPHANDLER(orl_a_r2)831 OPHANDLER( orl_a_r2 )       { burn_cycles(1); m_a |= R2; }
OPHANDLER(orl_a_r3)832 OPHANDLER( orl_a_r3 )       { burn_cycles(1); m_a |= R3; }
OPHANDLER(orl_a_r4)833 OPHANDLER( orl_a_r4 )       { burn_cycles(1); m_a |= R4; }
OPHANDLER(orl_a_r5)834 OPHANDLER( orl_a_r5 )       { burn_cycles(1); m_a |= R5; }
OPHANDLER(orl_a_r6)835 OPHANDLER( orl_a_r6 )       { burn_cycles(1); m_a |= R6; }
OPHANDLER(orl_a_r7)836 OPHANDLER( orl_a_r7 )       { burn_cycles(1); m_a |= R7; }
OPHANDLER(orl_a_xr0)837 OPHANDLER( orl_a_xr0 )      { burn_cycles(1); m_a |= ram_r(R0); }
OPHANDLER(orl_a_xr1)838 OPHANDLER( orl_a_xr1 )      { burn_cycles(1); m_a |= ram_r(R1); }
OPHANDLER(orl_a_n)839 OPHANDLER( orl_a_n )        { burn_cycles(2); m_a |= argument_fetch(); }
840 
OPHANDLER(orl_bus_n)841 OPHANDLER( orl_bus_n )      { burn_cycles(2); bus_w(bus_r() | argument_fetch()); }
OPHANDLER(orl_p1_n)842 OPHANDLER( orl_p1_n )       { burn_cycles(2); port_w(1, m_p1 |= argument_fetch()); }
OPHANDLER(orl_p2_n)843 OPHANDLER( orl_p2_n )       { burn_cycles(2); port_w(2, m_p2 |= argument_fetch() & p2_mask()); }
OPHANDLER(orld_p4_a)844 OPHANDLER( orld_p4_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_OR, 4); }
OPHANDLER(orld_p5_a)845 OPHANDLER( orld_p5_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_OR, 5); }
OPHANDLER(orld_p6_a)846 OPHANDLER( orld_p6_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_OR, 6); }
OPHANDLER(orld_p7_a)847 OPHANDLER( orld_p7_a )      { burn_cycles(2); expander_operation(EXPANDER_OP_OR, 7); }
848 
OPHANDLER(outl_bus_a)849 OPHANDLER( outl_bus_a )     { burn_cycles(2); bus_w(m_a); }
OPHANDLER(outl_p0_a)850 OPHANDLER( outl_p0_a )      { burn_cycles(2); bus_w(m_dbbo = m_a); }
OPHANDLER(outl_p1_a)851 OPHANDLER( outl_p1_a )      { burn_cycles(2); port_w(1, m_p1 = m_a); }
OPHANDLER(outl_p2_a)852 OPHANDLER( outl_p2_a )      { burn_cycles(2); uint8_t mask = p2_mask(); port_w(2, m_p2 = (m_p2 & ~mask) | (m_a & mask)); }
OPHANDLER(out_dbb_a)853 OPHANDLER( out_dbb_a )
854 {
855 	burn_cycles(2);
856 
857 	/* copy to the DBBO and update the bit in STS */
858 	m_dbbo = m_a;
859 	m_sts |= STS_OBF;
860 
861 	/* if P2 flags are enabled, update the state of P2 */
862 	if (m_flags_enabled && (m_p2 & P2_OBF) == 0)
863 		port_w(2, m_p2 |= P2_OBF);
864 }
865 
866 
OPHANDLER(ret)867 OPHANDLER( ret )            { burn_cycles(2); pull_pc(); }
OPHANDLER(retr)868 OPHANDLER( retr )
869 {
870 	burn_cycles(2);
871 	pull_pc_psw();
872 
873 	/* implicitly clear the IRQ in progress flip flop */
874 	m_irq_in_progress = false;
875 }
876 
OPHANDLER(rl_a)877 OPHANDLER( rl_a )           { burn_cycles(1); m_a = (m_a << 1) | (m_a >> 7); }
OPHANDLER(rlc_a)878 OPHANDLER( rlc_a )          { burn_cycles(1); uint8_t newc = m_a & C_FLAG; m_a = (m_a << 1) | (m_psw >> 7); m_psw = (m_psw & ~C_FLAG) | newc; }
879 
OPHANDLER(rr_a)880 OPHANDLER( rr_a )           { burn_cycles(1); m_a = (m_a >> 1) | (m_a << 7); }
OPHANDLER(rrc_a)881 OPHANDLER( rrc_a )          { burn_cycles(1); uint8_t newc = (m_a << 7) & C_FLAG; m_a = (m_a >> 1) | (m_psw & C_FLAG); m_psw = (m_psw & ~C_FLAG) | newc; }
882 
OPHANDLER(sel_mb0)883 OPHANDLER( sel_mb0 )        { burn_cycles(1); m_a11 = 0x000; }
OPHANDLER(sel_mb1)884 OPHANDLER( sel_mb1 )        { burn_cycles(1); m_a11 = 0x800; }
885 
OPHANDLER(sel_rb0)886 OPHANDLER( sel_rb0 )        { burn_cycles(1); m_psw &= ~B_FLAG; update_regptr(); }
OPHANDLER(sel_rb1)887 OPHANDLER( sel_rb1 )        { burn_cycles(1); m_psw |=  B_FLAG; update_regptr(); }
888 
OPHANDLER(stop_tcnt)889 OPHANDLER( stop_tcnt )      { burn_cycles(1); m_timecount_enabled = 0; }
OPHANDLER(strt_t)890 OPHANDLER( strt_t )         { burn_cycles(1); m_timecount_enabled = TIMER_ENABLED; m_prescaler = 0; }
OPHANDLER(strt_cnt)891 OPHANDLER( strt_cnt )
892 {
893 	burn_cycles(1);
894 	if (!(m_timecount_enabled & COUNTER_ENABLED))
895 		m_t1_history = test_r(1);
896 
897 	m_timecount_enabled = COUNTER_ENABLED;
898 }
899 
OPHANDLER(swap_a)900 OPHANDLER( swap_a )         { burn_cycles(1); m_a = (m_a << 4) | (m_a >> 4); }
901 
OPHANDLER(xch_a_r0)902 OPHANDLER( xch_a_r0 )       { burn_cycles(1); uint8_t tmp = m_a; m_a = R0; R0 = tmp; }
OPHANDLER(xch_a_r1)903 OPHANDLER( xch_a_r1 )       { burn_cycles(1); uint8_t tmp = m_a; m_a = R1; R1 = tmp; }
OPHANDLER(xch_a_r2)904 OPHANDLER( xch_a_r2 )       { burn_cycles(1); uint8_t tmp = m_a; m_a = R2; R2 = tmp; }
OPHANDLER(xch_a_r3)905 OPHANDLER( xch_a_r3 )       { burn_cycles(1); uint8_t tmp = m_a; m_a = R3; R3 = tmp; }
OPHANDLER(xch_a_r4)906 OPHANDLER( xch_a_r4 )       { burn_cycles(1); uint8_t tmp = m_a; m_a = R4; R4 = tmp; }
OPHANDLER(xch_a_r5)907 OPHANDLER( xch_a_r5 )       { burn_cycles(1); uint8_t tmp = m_a; m_a = R5; R5 = tmp; }
OPHANDLER(xch_a_r6)908 OPHANDLER( xch_a_r6 )       { burn_cycles(1); uint8_t tmp = m_a; m_a = R6; R6 = tmp; }
OPHANDLER(xch_a_r7)909 OPHANDLER( xch_a_r7 )       { burn_cycles(1); uint8_t tmp = m_a; m_a = R7; R7 = tmp; }
OPHANDLER(xch_a_xr0)910 OPHANDLER( xch_a_xr0 )      { burn_cycles(1); uint8_t tmp = m_a; m_a = ram_r(R0); ram_w(R0, tmp); }
OPHANDLER(xch_a_xr1)911 OPHANDLER( xch_a_xr1 )      { burn_cycles(1); uint8_t tmp = m_a; m_a = ram_r(R1); ram_w(R1, tmp); }
912 
OPHANDLER(xchd_a_xr0)913 OPHANDLER( xchd_a_xr0 )     { burn_cycles(1); uint8_t oldram = ram_r(R0); ram_w(R0, (oldram & 0xf0) | (m_a & 0x0f)); m_a = (m_a & 0xf0) | (oldram & 0x0f); }
OPHANDLER(xchd_a_xr1)914 OPHANDLER( xchd_a_xr1 )     { burn_cycles(1); uint8_t oldram = ram_r(R1); ram_w(R1, (oldram & 0xf0) | (m_a & 0x0f)); m_a = (m_a & 0xf0) | (oldram & 0x0f); }
915 
OPHANDLER(xrl_a_r0)916 OPHANDLER( xrl_a_r0 )       { burn_cycles(1); m_a ^= R0; }
OPHANDLER(xrl_a_r1)917 OPHANDLER( xrl_a_r1 )       { burn_cycles(1); m_a ^= R1; }
OPHANDLER(xrl_a_r2)918 OPHANDLER( xrl_a_r2 )       { burn_cycles(1); m_a ^= R2; }
OPHANDLER(xrl_a_r3)919 OPHANDLER( xrl_a_r3 )       { burn_cycles(1); m_a ^= R3; }
OPHANDLER(xrl_a_r4)920 OPHANDLER( xrl_a_r4 )       { burn_cycles(1); m_a ^= R4; }
OPHANDLER(xrl_a_r5)921 OPHANDLER( xrl_a_r5 )       { burn_cycles(1); m_a ^= R5; }
OPHANDLER(xrl_a_r6)922 OPHANDLER( xrl_a_r6 )       { burn_cycles(1); m_a ^= R6; }
OPHANDLER(xrl_a_r7)923 OPHANDLER( xrl_a_r7 )       { burn_cycles(1); m_a ^= R7; }
OPHANDLER(xrl_a_xr0)924 OPHANDLER( xrl_a_xr0 )      { burn_cycles(1); m_a ^= ram_r(R0); }
OPHANDLER(xrl_a_xr1)925 OPHANDLER( xrl_a_xr1 )      { burn_cycles(1); m_a ^= ram_r(R1); }
OPHANDLER(xrl_a_n)926 OPHANDLER( xrl_a_n )        { burn_cycles(2); m_a ^= argument_fetch(); }
927 
928 
929 
930 /***************************************************************************
931     OPCODE TABLES
932 ***************************************************************************/
933 
934 #define OP(_a) &mcs48_cpu_device::_a
935 
936 const mcs48_cpu_device::mcs48_ophandler mcs48_cpu_device::s_mcs48_opcodes[256] =
937 {
938 	OP(nop),        OP(illegal),    OP(outl_bus_a),OP(add_a_n),   OP(jmp_0),     OP(en_i),       OP(illegal),   OP(dec_a),         /* 00 */
939 	OP(ins_a_bus),  OP(in_a_p1),    OP(in_a_p2),   OP(illegal),   OP(movd_a_p4), OP(movd_a_p5),  OP(movd_a_p6), OP(movd_a_p7),
940 	OP(inc_xr0),    OP(inc_xr1),    OP(jb_0),      OP(adc_a_n),   OP(call_0),    OP(dis_i),      OP(jtf),       OP(inc_a),         /* 10 */
941 	OP(inc_r0),     OP(inc_r1),     OP(inc_r2),    OP(inc_r3),    OP(inc_r4),    OP(inc_r5),     OP(inc_r6),    OP(inc_r7),
942 	OP(xch_a_xr0),  OP(xch_a_xr1),  OP(illegal),   OP(mov_a_n),   OP(jmp_1),     OP(en_tcnti),   OP(jnt_0),     OP(clr_a),         /* 20 */
943 	OP(xch_a_r0),   OP(xch_a_r1),   OP(xch_a_r2),  OP(xch_a_r3),  OP(xch_a_r4),  OP(xch_a_r5),   OP(xch_a_r6),  OP(xch_a_r7),
944 	OP(xchd_a_xr0), OP(xchd_a_xr1), OP(jb_1),      OP(illegal),   OP(call_1),    OP(dis_tcnti),  OP(jt_0),      OP(cpl_a),         /* 30 */
945 	OP(illegal),    OP(outl_p1_a),  OP(outl_p2_a), OP(illegal),   OP(movd_p4_a), OP(movd_p5_a),  OP(movd_p6_a), OP(movd_p7_a),
946 	OP(orl_a_xr0),  OP(orl_a_xr1),  OP(mov_a_t),   OP(orl_a_n),   OP(jmp_2),     OP(strt_cnt),   OP(jnt_1),     OP(swap_a),        /* 40 */
947 	OP(orl_a_r0),   OP(orl_a_r1),   OP(orl_a_r2),  OP(orl_a_r3),  OP(orl_a_r4),  OP(orl_a_r5),   OP(orl_a_r6),  OP(orl_a_r7),
948 	OP(anl_a_xr0),  OP(anl_a_xr1),  OP(jb_2),      OP(anl_a_n),   OP(call_2),    OP(strt_t),     OP(jt_1),      OP(da_a),          /* 50 */
949 	OP(anl_a_r0),   OP(anl_a_r1),   OP(anl_a_r2),  OP(anl_a_r3),  OP(anl_a_r4),  OP(anl_a_r5),   OP(anl_a_r6),  OP(anl_a_r7),
950 	OP(add_a_xr0),  OP(add_a_xr1),  OP(mov_t_a),   OP(illegal),   OP(jmp_3),     OP(stop_tcnt),  OP(illegal),   OP(rrc_a),         /* 60 */
951 	OP(add_a_r0),   OP(add_a_r1),   OP(add_a_r2),  OP(add_a_r3),  OP(add_a_r4),  OP(add_a_r5),   OP(add_a_r6),  OP(add_a_r7),
952 	OP(adc_a_xr0),  OP(adc_a_xr1),  OP(jb_3),      OP(illegal),   OP(call_3),    OP(ent0_clk),   OP(jf1),       OP(rr_a),          /* 70 */
953 	OP(adc_a_r0),   OP(adc_a_r1),   OP(adc_a_r2),  OP(adc_a_r3),  OP(adc_a_r4),  OP(adc_a_r5),   OP(adc_a_r6),  OP(adc_a_r7),
954 	OP(movx_a_xr0), OP(movx_a_xr1), OP(illegal),   OP(ret),       OP(jmp_4),     OP(clr_f0),     OP(jni),       OP(illegal),       /* 80 */
955 	OP(orl_bus_n),  OP(orl_p1_n),   OP(orl_p2_n),  OP(illegal),   OP(orld_p4_a), OP(orld_p5_a),  OP(orld_p6_a), OP(orld_p7_a),
956 	OP(movx_xr0_a), OP(movx_xr1_a), OP(jb_4),      OP(retr),      OP(call_4),    OP(cpl_f0),     OP(jnz),       OP(clr_c),         /* 90 */
957 	OP(anl_bus_n),  OP(anl_p1_n),   OP(anl_p2_n),  OP(illegal),   OP(anld_p4_a), OP(anld_p5_a),  OP(anld_p6_a), OP(anld_p7_a),
958 	OP(mov_xr0_a),  OP(mov_xr1_a),  OP(illegal),   OP(movp_a_xa), OP(jmp_5),     OP(clr_f1),     OP(illegal),   OP(cpl_c),         /* A0 */
959 	OP(mov_r0_a),   OP(mov_r1_a),   OP(mov_r2_a),  OP(mov_r3_a),  OP(mov_r4_a),  OP(mov_r5_a),   OP(mov_r6_a),  OP(mov_r7_a),
960 	OP(mov_xr0_n),  OP(mov_xr1_n),  OP(jb_5),      OP(jmpp_xa),   OP(call_5),    OP(cpl_f1),     OP(jf0),       OP(illegal),       /* B0 */
961 	OP(mov_r0_n),   OP(mov_r1_n),   OP(mov_r2_n),  OP(mov_r3_n),  OP(mov_r4_n),  OP(mov_r5_n),   OP(mov_r6_n),  OP(mov_r7_n),
962 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(jmp_6),     OP(sel_rb0),    OP(jz),        OP(mov_a_psw),     /* C0 */
963 	OP(dec_r0),     OP(dec_r1),     OP(dec_r2),    OP(dec_r3),    OP(dec_r4),    OP(dec_r5),     OP(dec_r6),    OP(dec_r7),
964 	OP(xrl_a_xr0),  OP(xrl_a_xr1),  OP(jb_6),      OP(xrl_a_n),   OP(call_6),    OP(sel_rb1),    OP(illegal),   OP(mov_psw_a),     /* D0 */
965 	OP(xrl_a_r0),   OP(xrl_a_r1),   OP(xrl_a_r2),  OP(xrl_a_r3),  OP(xrl_a_r4),  OP(xrl_a_r5),   OP(xrl_a_r6),  OP(xrl_a_r7),
966 	OP(illegal),    OP(illegal),    OP(illegal),   OP(movp3_a_xa),OP(jmp_7),     OP(sel_mb0),    OP(jnc),       OP(rl_a),          /* E0 */
967 	OP(djnz_r0),    OP(djnz_r1),    OP(djnz_r2),   OP(djnz_r3),   OP(djnz_r4),   OP(djnz_r5),    OP(djnz_r6),   OP(djnz_r7),
968 	OP(mov_a_xr0),  OP(mov_a_xr1),  OP(jb_7),      OP(illegal),   OP(call_7),    OP(sel_mb1),    OP(jc),        OP(rlc_a),         /* F0 */
969 	OP(mov_a_r0),   OP(mov_a_r1),   OP(mov_a_r2),  OP(mov_a_r3),  OP(mov_a_r4),  OP(mov_a_r5),   OP(mov_a_r6),  OP(mov_a_r7)
970 };
971 
972 const mcs48_cpu_device::mcs48_ophandler mcs48_cpu_device::s_upi41_opcodes[256] =
973 {
974 	OP(nop),        OP(illegal),    OP(out_dbb_a), OP(add_a_n),   OP(jmp_0),     OP(en_i),       OP(illegal),   OP(dec_a),         /* 00 */
975 	OP(illegal),    OP(in_a_p1),    OP(in_a_p2),   OP(illegal),   OP(movd_a_p4), OP(movd_a_p5),  OP(movd_a_p6), OP(movd_a_p7),
976 	OP(inc_xr0),    OP(inc_xr1),    OP(jb_0),      OP(adc_a_n),   OP(call_0),    OP(dis_i),      OP(jtf),       OP(inc_a),         /* 10 */
977 	OP(inc_r0),     OP(inc_r1),     OP(inc_r2),    OP(inc_r3),    OP(inc_r4),    OP(inc_r5),     OP(inc_r6),    OP(inc_r7),
978 	OP(xch_a_xr0),  OP(xch_a_xr1),  OP(in_a_dbb),  OP(mov_a_n),   OP(jmp_1),     OP(en_tcnti),   OP(jnt_0),     OP(clr_a),         /* 20 */
979 	OP(xch_a_r0),   OP(xch_a_r1),   OP(xch_a_r2),  OP(xch_a_r3),  OP(xch_a_r4),  OP(xch_a_r5),   OP(xch_a_r6),  OP(xch_a_r7),
980 	OP(xchd_a_xr0), OP(xchd_a_xr1), OP(jb_1),      OP(illegal),   OP(call_1),    OP(dis_tcnti),  OP(jt_0),      OP(cpl_a),         /* 30 */
981 	OP(illegal),    OP(outl_p1_a),  OP(outl_p2_a), OP(illegal),   OP(movd_p4_a), OP(movd_p5_a),  OP(movd_p6_a), OP(movd_p7_a),
982 	OP(orl_a_xr0),  OP(orl_a_xr1),  OP(mov_a_t),   OP(orl_a_n),   OP(jmp_2),     OP(strt_cnt),   OP(jnt_1),     OP(swap_a),        /* 40 */
983 	OP(orl_a_r0),   OP(orl_a_r1),   OP(orl_a_r2),  OP(orl_a_r3),  OP(orl_a_r4),  OP(orl_a_r5),   OP(orl_a_r6),  OP(orl_a_r7),
984 	OP(anl_a_xr0),  OP(anl_a_xr1),  OP(jb_2),      OP(anl_a_n),   OP(call_2),    OP(strt_t),     OP(jt_1),      OP(da_a),          /* 50 */
985 	OP(anl_a_r0),   OP(anl_a_r1),   OP(anl_a_r2),  OP(anl_a_r3),  OP(anl_a_r4),  OP(anl_a_r5),   OP(anl_a_r6),  OP(anl_a_r7),
986 	OP(add_a_xr0),  OP(add_a_xr1),  OP(mov_t_a),   OP(illegal),   OP(jmp_3),     OP(stop_tcnt),  OP(illegal),   OP(rrc_a),         /* 60 */
987 	OP(add_a_r0),   OP(add_a_r1),   OP(add_a_r2),  OP(add_a_r3),  OP(add_a_r4),  OP(add_a_r5),   OP(add_a_r6),  OP(add_a_r7),
988 	OP(adc_a_xr0),  OP(adc_a_xr1),  OP(jb_3),      OP(illegal),   OP(call_3),    OP(illegal),    OP(jf1),       OP(rr_a),          /* 70 */
989 	OP(adc_a_r0),   OP(adc_a_r1),   OP(adc_a_r2),  OP(adc_a_r3),  OP(adc_a_r4),  OP(adc_a_r5),   OP(adc_a_r6),  OP(adc_a_r7),
990 	OP(illegal),    OP(illegal),    OP(illegal),   OP(ret),       OP(jmp_4),     OP(clr_f0),     OP(jobf),      OP(illegal),       /* 80 */
991 	OP(illegal),    OP(orl_p1_n),   OP(orl_p2_n),  OP(illegal),   OP(orld_p4_a), OP(orld_p5_a),  OP(orld_p6_a), OP(orld_p7_a),
992 	OP(mov_sts_a),  OP(illegal),    OP(jb_4),      OP(retr),      OP(call_4),    OP(cpl_f0),     OP(jnz),       OP(clr_c),         /* 90 */
993 	OP(illegal),    OP(anl_p1_n),   OP(anl_p2_n),  OP(illegal),   OP(anld_p4_a), OP(anld_p5_a),  OP(anld_p6_a), OP(anld_p7_a),
994 	OP(mov_xr0_a),  OP(mov_xr1_a),  OP(illegal),   OP(movp_a_xa), OP(jmp_5),     OP(clr_f1),     OP(illegal),   OP(cpl_c),         /* A0 */
995 	OP(mov_r0_a),   OP(mov_r1_a),   OP(mov_r2_a),  OP(mov_r3_a),  OP(mov_r4_a),  OP(mov_r5_a),   OP(mov_r6_a),  OP(mov_r7_a),
996 	OP(mov_xr0_n),  OP(mov_xr1_n),  OP(jb_5),      OP(jmpp_xa),   OP(call_5),    OP(cpl_f1),     OP(jf0),       OP(illegal),       /* B0 */
997 	OP(mov_r0_n),   OP(mov_r1_n),   OP(mov_r2_n),  OP(mov_r3_n),  OP(mov_r4_n),  OP(mov_r5_n),   OP(mov_r6_n),  OP(mov_r7_n),
998 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(jmp_6),     OP(sel_rb0),    OP(jz),        OP(mov_a_psw),     /* C0 */
999 	OP(dec_r0),     OP(dec_r1),     OP(dec_r2),    OP(dec_r3),    OP(dec_r4),    OP(dec_r5),     OP(dec_r6),    OP(dec_r7),
1000 	OP(xrl_a_xr0),  OP(xrl_a_xr1),  OP(jb_6),      OP(xrl_a_n),   OP(call_6),    OP(sel_rb1),    OP(jnibf),     OP(mov_psw_a),     /* D0 */
1001 	OP(xrl_a_r0),   OP(xrl_a_r1),   OP(xrl_a_r2),  OP(xrl_a_r3),  OP(xrl_a_r4),  OP(xrl_a_r5),   OP(xrl_a_r6),  OP(xrl_a_r7),
1002 	OP(illegal),    OP(illegal),    OP(illegal),   OP(movp3_a_xa),OP(jmp_7),     OP(en_dma),     OP(jnc),       OP(rl_a),          /* E0 */
1003 	OP(djnz_r0),    OP(djnz_r1),    OP(djnz_r2),   OP(djnz_r3),   OP(djnz_r4),   OP(djnz_r5),    OP(djnz_r6),   OP(djnz_r7),
1004 	OP(mov_a_xr0),  OP(mov_a_xr1),  OP(jb_7),      OP(illegal),   OP(call_7),    OP(en_flags),   OP(jc),        OP(rlc_a),         /* F0 */
1005 	OP(mov_a_r0),   OP(mov_a_r1),   OP(mov_a_r2),  OP(mov_a_r3),  OP(mov_a_r4),  OP(mov_a_r5),   OP(mov_a_r6),  OP(mov_a_r7)
1006 };
1007 
1008 const mcs48_cpu_device::mcs48_ophandler mcs48_cpu_device::s_i8021_opcodes[256] =
1009 {
1010 	OP(nop),        OP(illegal),    OP(illegal),   OP(add_a_n),   OP(jmp_0),     OP(illegal),    OP(illegal),   OP(dec_a),         /* 00 */
1011 	OP(in_a_p0),    OP(in_a_p1),    OP(in_a_p2),   OP(illegal),   OP(movd_a_p4), OP(movd_a_p5),  OP(movd_a_p6), OP(movd_a_p7),
1012 	OP(inc_xr0),    OP(inc_xr1),    OP(illegal),   OP(adc_a_n),   OP(call_0),    OP(illegal),    OP(jtf),       OP(inc_a),         /* 10 */
1013 	OP(inc_r0),     OP(inc_r1),     OP(inc_r2),    OP(inc_r3),    OP(inc_r4),    OP(inc_r5),     OP(inc_r6),    OP(inc_r7),
1014 	OP(xch_a_xr0),  OP(xch_a_xr1),  OP(illegal),   OP(mov_a_n),   OP(jmp_1),     OP(illegal),    OP(illegal),   OP(clr_a),         /* 20 */
1015 	OP(xch_a_r0),   OP(xch_a_r1),   OP(xch_a_r2),  OP(xch_a_r3),  OP(xch_a_r4),  OP(xch_a_r5),   OP(xch_a_r6),  OP(xch_a_r7),
1016 	OP(xchd_a_xr0), OP(xchd_a_xr1), OP(illegal),   OP(illegal),   OP(call_1),    OP(illegal),    OP(illegal),   OP(cpl_a),         /* 30 */
1017 	OP(illegal),    OP(outl_p1_a),  OP(outl_p2_a), OP(illegal),   OP(movd_p4_a), OP(movd_p5_a),  OP(movd_p6_a), OP(movd_p7_a),
1018 	OP(orl_a_xr0),  OP(orl_a_xr1),  OP(mov_a_t),   OP(orl_a_n),   OP(jmp_2),     OP(strt_cnt),   OP(jnt_1),     OP(swap_a),        /* 40 */
1019 	OP(orl_a_r0),   OP(orl_a_r1),   OP(orl_a_r2),  OP(orl_a_r3),  OP(orl_a_r4),  OP(orl_a_r5),   OP(orl_a_r6),  OP(orl_a_r7),
1020 	OP(anl_a_xr0),  OP(anl_a_xr1),  OP(illegal),   OP(anl_a_n),   OP(call_2),    OP(strt_t),     OP(jt_1),      OP(da_a),          /* 50 */
1021 	OP(anl_a_r0),   OP(anl_a_r1),   OP(anl_a_r2),  OP(anl_a_r3),  OP(anl_a_r4),  OP(anl_a_r5),   OP(anl_a_r6),  OP(anl_a_r7),
1022 	OP(add_a_xr0),  OP(add_a_xr1),  OP(mov_t_a),   OP(illegal),   OP(jmp_3),     OP(stop_tcnt),  OP(illegal),   OP(rrc_a),         /* 60 */
1023 	OP(add_a_r0),   OP(add_a_r1),   OP(add_a_r2),  OP(add_a_r3),  OP(add_a_r4),  OP(add_a_r5),   OP(add_a_r6),  OP(add_a_r7),
1024 	OP(adc_a_xr0),  OP(adc_a_xr1),  OP(illegal),   OP(illegal),   OP(call_3),    OP(illegal),    OP(illegal),   OP(rr_a),          /* 70 */
1025 	OP(adc_a_r0),   OP(adc_a_r1),   OP(adc_a_r2),  OP(adc_a_r3),  OP(adc_a_r4),  OP(adc_a_r5),   OP(adc_a_r6),  OP(adc_a_r7),
1026 	OP(illegal),    OP(illegal),    OP(illegal),   OP(ret),       OP(jmp_4),     OP(illegal),    OP(illegal),   OP(illegal),       /* 80 */
1027 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(orld_p4_a), OP(orld_p5_a),  OP(orld_p6_a), OP(orld_p7_a),
1028 	OP(outl_p0_a),  OP(illegal),    OP(illegal),   OP(illegal),   OP(call_4),    OP(illegal),    OP(jnz),       OP(clr_c),         /* 90 */
1029 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(anld_p4_a), OP(anld_p5_a),  OP(anld_p6_a), OP(anld_p7_a),
1030 	OP(mov_xr0_a),  OP(mov_xr1_a),  OP(illegal),   OP(movp_a_xa), OP(jmp_5),     OP(illegal),    OP(illegal),   OP(cpl_c),         /* A0 */
1031 	OP(mov_r0_a),   OP(mov_r1_a),   OP(mov_r2_a),  OP(mov_r3_a),  OP(mov_r4_a),  OP(mov_r5_a),   OP(mov_r6_a),  OP(mov_r7_a),
1032 	OP(mov_xr0_n),  OP(mov_xr1_n),  OP(illegal),   OP(jmpp_xa),   OP(call_5),    OP(illegal),    OP(illegal),   OP(illegal),       /* B0 */
1033 	OP(mov_r0_n),   OP(mov_r1_n),   OP(mov_r2_n),  OP(mov_r3_n),  OP(mov_r4_n),  OP(mov_r5_n),   OP(mov_r6_n),  OP(mov_r7_n),
1034 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(jmp_6),     OP(illegal),    OP(jz),        OP(illegal),       /* C0 */
1035 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(illegal),   OP(illegal),    OP(illegal),   OP(illegal),
1036 	OP(xrl_a_xr0),  OP(xrl_a_xr1),  OP(illegal),   OP(xrl_a_n),   OP(call_6),    OP(illegal),    OP(illegal),   OP(illegal),       /* D0 */
1037 	OP(xrl_a_r0),   OP(xrl_a_r1),   OP(xrl_a_r2),  OP(xrl_a_r3),  OP(xrl_a_r4),  OP(xrl_a_r5),   OP(xrl_a_r6),  OP(xrl_a_r7),
1038 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(jmp_7),     OP(illegal),    OP(jnc),       OP(rl_a),          /* E0 */
1039 	OP(djnz_r0),    OP(djnz_r1),    OP(djnz_r2),   OP(djnz_r3),   OP(djnz_r4),   OP(djnz_r5),    OP(djnz_r6),   OP(djnz_r7),
1040 	OP(mov_a_xr0),  OP(mov_a_xr1),  OP(illegal),   OP(illegal),   OP(call_7),    OP(illegal),    OP(jc),        OP(rlc_a),         /* F0 */
1041 	OP(mov_a_r0),   OP(mov_a_r1),   OP(mov_a_r2),  OP(mov_a_r3),  OP(mov_a_r4),  OP(mov_a_r5),   OP(mov_a_r6),  OP(mov_a_r7)
1042 };
1043 
1044 const mcs48_cpu_device::mcs48_ophandler mcs48_cpu_device::s_i8022_opcodes[256] =
1045 {
1046 	OP(nop),        OP(illegal),    OP(illegal),   OP(add_a_n),   OP(jmp_0),     OP(en_i),       OP(illegal),   OP(dec_a),         /* 00 */
1047 	OP(in_a_p0),    OP(in_a_p1),    OP(in_a_p2),   OP(illegal),   OP(movd_a_p4), OP(movd_a_p5),  OP(movd_a_p6), OP(movd_a_p7),
1048 	OP(inc_xr0),    OP(inc_xr1),    OP(illegal),   OP(adc_a_n),   OP(call_0),    OP(dis_i),      OP(jtf),       OP(inc_a),         /* 10 */
1049 	OP(inc_r0),     OP(inc_r1),     OP(inc_r2),    OP(inc_r3),    OP(inc_r4),    OP(inc_r5),     OP(inc_r6),    OP(inc_r7),
1050 	OP(xch_a_xr0),  OP(xch_a_xr1),  OP(illegal),   OP(mov_a_n),   OP(jmp_1),     OP(en_tcnti),   OP(jnt_0),     OP(clr_a),         /* 20 */
1051 	OP(xch_a_r0),   OP(xch_a_r1),   OP(xch_a_r2),  OP(xch_a_r3),  OP(xch_a_r4),  OP(xch_a_r5),   OP(xch_a_r6),  OP(xch_a_r7),
1052 	OP(xchd_a_xr0), OP(xchd_a_xr1), OP(illegal),   OP(illegal),   OP(call_1),    OP(dis_tcnti),  OP(jt_0),      OP(cpl_a),         /* 30 */
1053 	OP(illegal),    OP(outl_p1_a),  OP(outl_p2_a), OP(illegal),   OP(movd_p4_a), OP(movd_p5_a),  OP(movd_p6_a), OP(movd_p7_a),
1054 	OP(orl_a_xr0),  OP(orl_a_xr1),  OP(mov_a_t),   OP(orl_a_n),   OP(jmp_2),     OP(strt_cnt),   OP(jnt_1),     OP(swap_a),        /* 40 */
1055 	OP(orl_a_r0),   OP(orl_a_r1),   OP(orl_a_r2),  OP(orl_a_r3),  OP(orl_a_r4),  OP(orl_a_r5),   OP(orl_a_r6),  OP(orl_a_r7),
1056 	OP(anl_a_xr0),  OP(anl_a_xr1),  OP(illegal),   OP(anl_a_n),   OP(call_2),    OP(strt_t),     OP(jt_1),      OP(da_a),          /* 50 */
1057 	OP(anl_a_r0),   OP(anl_a_r1),   OP(anl_a_r2),  OP(anl_a_r3),  OP(anl_a_r4),  OP(anl_a_r5),   OP(anl_a_r6),  OP(anl_a_r7),
1058 	OP(add_a_xr0),  OP(add_a_xr1),  OP(mov_t_a),   OP(illegal),   OP(jmp_3),     OP(stop_tcnt),  OP(illegal),   OP(rrc_a),         /* 60 */
1059 	OP(add_a_r0),   OP(add_a_r1),   OP(add_a_r2),  OP(add_a_r3),  OP(add_a_r4),  OP(add_a_r5),   OP(add_a_r6),  OP(add_a_r7),
1060 	OP(adc_a_xr0),  OP(adc_a_xr1),  OP(illegal),   OP(illegal),   OP(call_3),    OP(illegal),    OP(illegal),   OP(rr_a),          /* 70 */
1061 	OP(adc_a_r0),   OP(adc_a_r1),   OP(adc_a_r2),  OP(adc_a_r3),  OP(adc_a_r4),  OP(adc_a_r5),   OP(adc_a_r6),  OP(adc_a_r7),
1062 	OP(illegal),    OP(illegal),    OP(illegal),   OP(ret),       OP(jmp_4),     OP(illegal),    OP(illegal),   OP(illegal),       /* 80 */
1063 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(orld_p4_a), OP(orld_p5_a),  OP(orld_p6_a), OP(orld_p7_a),
1064 	OP(outl_p0_a),  OP(illegal),    OP(illegal),   OP(retr),      OP(call_4),    OP(illegal),    OP(jnz),       OP(clr_c),         /* 90 */
1065 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(anld_p4_a), OP(anld_p5_a),  OP(anld_p6_a), OP(anld_p7_a),
1066 	OP(mov_xr0_a),  OP(mov_xr1_a),  OP(illegal),   OP(movp_a_xa), OP(jmp_5),     OP(illegal),    OP(illegal),   OP(cpl_c),         /* A0 */
1067 	OP(mov_r0_a),   OP(mov_r1_a),   OP(mov_r2_a),  OP(mov_r3_a),  OP(mov_r4_a),  OP(mov_r5_a),   OP(mov_r6_a),  OP(mov_r7_a),
1068 	OP(mov_xr0_n),  OP(mov_xr1_n),  OP(illegal),   OP(jmpp_xa),   OP(call_5),    OP(illegal),    OP(illegal),   OP(illegal),       /* B0 */
1069 	OP(mov_r0_n),   OP(mov_r1_n),   OP(mov_r2_n),  OP(mov_r3_n),  OP(mov_r4_n),  OP(mov_r5_n),   OP(mov_r6_n),  OP(mov_r7_n),
1070 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(jmp_6),     OP(illegal),    OP(jz),        OP(illegal),       /* C0 */
1071 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(illegal),   OP(illegal),    OP(illegal),   OP(illegal),
1072 	OP(xrl_a_xr0),  OP(xrl_a_xr1),  OP(illegal),   OP(xrl_a_n),   OP(call_6),    OP(illegal),    OP(illegal),   OP(illegal),       /* D0 */
1073 	OP(xrl_a_r0),   OP(xrl_a_r1),   OP(xrl_a_r2),  OP(xrl_a_r3),  OP(xrl_a_r4),  OP(xrl_a_r5),   OP(xrl_a_r6),  OP(xrl_a_r7),
1074 	OP(illegal),    OP(illegal),    OP(illegal),   OP(illegal),   OP(jmp_7),     OP(illegal),    OP(jnc),       OP(rl_a),          /* E0 */
1075 	OP(djnz_r0),    OP(djnz_r1),    OP(djnz_r2),   OP(djnz_r3),   OP(djnz_r4),   OP(djnz_r5),    OP(djnz_r6),   OP(djnz_r7),
1076 	OP(mov_a_xr0),  OP(mov_a_xr1),  OP(illegal),   OP(illegal),   OP(call_7),    OP(illegal),    OP(jc),        OP(rlc_a),         /* F0 */
1077 	OP(mov_a_r0),   OP(mov_a_r1),   OP(mov_a_r2),  OP(mov_a_r3),  OP(mov_a_r4),  OP(mov_a_r5),   OP(mov_a_r6),  OP(mov_a_r7)
1078 };
1079 
1080 
1081 
1082 /***************************************************************************
1083     INITIALIZATION/RESET
1084 ***************************************************************************/
1085 
device_config_complete()1086 void mcs48_cpu_device::device_config_complete()
1087 {
1088 	m_t0_clk_func.resolve();
1089 	if (!m_t0_clk_func.isnull())
1090 		m_t0_clk_func(clock() / 3);
1091 }
1092 
1093 /*-------------------------------------------------
1094     mcs48_init - generic MCS-48 initialization
1095 -------------------------------------------------*/
1096 
device_start()1097 void mcs48_cpu_device::device_start()
1098 {
1099 	/* External access line
1100 	 * EA=1 : read from external rom
1101 	 * EA=0 : read from internal rom
1102 	 */
1103 
1104 	m_a = 0;
1105 	m_timer = 0;
1106 	m_prescaler = 0;
1107 	m_t1_history = 0;
1108 	m_dbbi = 0;
1109 	m_dbbo = 0;
1110 	m_irq_state = 0;
1111 
1112 	/* FIXME: Current implementation suboptimal */
1113 	m_ea = (m_int_rom_size ? 0 : 1);
1114 
1115 	space(AS_PROGRAM).cache(m_program);
1116 	space(AS_DATA).specific(m_data);
1117 	if(m_feature_mask & EXT_BUS_FEATURE)
1118 		space(AS_IO).specific(m_io);
1119 
1120 	// resolve callbacks
1121 	m_port_in_cb.resolve_all_safe(0xff);
1122 	m_port_out_cb.resolve_all_safe();
1123 	m_bus_in_cb.resolve_safe(0xff);
1124 	m_bus_out_cb.resolve_safe();
1125 	m_test_in_cb.resolve_all_safe(0);
1126 	m_prog_out_cb.resolve_safe();
1127 
1128 	/* set up the state table */
1129 	{
1130 		state_add(MCS48_PC,        "PC",        m_pc).mask(0xfff);
1131 		state_add(STATE_GENPC,     "GENPC",     m_pc).mask(0xfff).noshow();
1132 		state_add(STATE_GENPCBASE, "CURPC",     m_prevpc).mask(0xfff).noshow();
1133 		state_add(STATE_GENSP,     "GENSP",     m_psw).mask(0x7).noshow();
1134 		state_add(STATE_GENFLAGS,  "GENFLAGS",  m_psw).noshow().formatstr("%11s");
1135 		state_add(MCS48_A,         "A",         m_a);
1136 		state_add(MCS48_TC,        "TC",        m_timer);
1137 		state_add(MCS48_TPRE,      "TPRE",      m_prescaler).mask(0x1f);
1138 
1139 		if (m_feature_mask & I802X_FEATURE)
1140 			state_add(MCS48_P0,    "P0",        m_dbbo);
1141 		state_add(MCS48_P1,        "P1",        m_p1);
1142 		state_add(MCS48_P2,        "P2",        m_p2);
1143 
1144 		for (int regnum = 0; regnum < 8; regnum++) {
1145 			state_add(MCS48_R0 + regnum, string_format("R%d", regnum).c_str(), m_rtemp).callimport().callexport();
1146 		}
1147 
1148 		if (m_feature_mask & EXT_BUS_FEATURE)
1149 			state_add(MCS48_EA,    "EA",        m_ea).mask(0x1);
1150 
1151 		if (m_feature_mask & UPI41_FEATURE)
1152 		{
1153 			state_add(MCS48_STS,   "STS",       m_sts);
1154 			state_add(MCS48_DBBI,  "DBBI",      m_dbbi);
1155 			state_add(MCS48_DBBO,  "DBBO",      m_dbbo);
1156 		}
1157 
1158 	}
1159 
1160 	/* ensure that regptr is valid before get_info gets called */
1161 	update_regptr();
1162 
1163 	save_item(NAME(m_prevpc));
1164 	save_item(NAME(m_pc));
1165 
1166 	save_item(NAME(m_a));
1167 	save_item(NAME(m_psw));
1168 	save_item(NAME(m_p1));
1169 	save_item(NAME(m_p2));
1170 	save_item(NAME(m_ea));
1171 	save_item(NAME(m_timer));
1172 	save_item(NAME(m_prescaler));
1173 	save_item(NAME(m_t1_history));
1174 	save_item(NAME(m_sts));
1175 	save_item(NAME(m_dbbi));
1176 	save_item(NAME(m_dbbo));
1177 
1178 	save_item(NAME(m_irq_state));
1179 	save_item(NAME(m_irq_polled));
1180 	save_item(NAME(m_irq_in_progress));
1181 	save_item(NAME(m_timer_overflow));
1182 	save_item(NAME(m_timer_flag));
1183 	save_item(NAME(m_tirq_enabled));
1184 	save_item(NAME(m_xirq_enabled));
1185 	save_item(NAME(m_timecount_enabled));
1186 	save_item(NAME(m_flags_enabled));
1187 	save_item(NAME(m_dma_enabled));
1188 
1189 	save_item(NAME(m_a11));
1190 
1191 	set_icountptr(m_icount);
1192 }
1193 
1194 
device_reset()1195 void mcs48_cpu_device::device_reset()
1196 {
1197 	/* confirmed from reset description */
1198 	m_pc = 0;
1199 	m_psw = m_psw & (C_FLAG | A_FLAG);
1200 	update_regptr();
1201 	m_a11 = 0x000;
1202 	m_dbbo = 0xff;
1203 	bus_w(0xff);
1204 	m_p1 = 0xff;
1205 	m_p2 = 0xff;
1206 	port_w(1, m_p1);
1207 	port_w(2, m_p2);
1208 	m_tirq_enabled = false;
1209 	m_xirq_enabled = false;
1210 	m_timecount_enabled = 0;
1211 	m_timer_flag = false;
1212 	m_sts = 0;
1213 	m_flags_enabled = false;
1214 	m_dma_enabled = false;
1215 	if (!m_t0_clk_func.isnull())
1216 		m_t0_clk_func(0);
1217 
1218 	/* confirmed from interrupt logic description */
1219 	m_irq_in_progress = false;
1220 	m_timer_overflow = false;
1221 
1222 	m_irq_polled = false;
1223 }
1224 
1225 
1226 /***************************************************************************
1227     EXECUTION
1228 ***************************************************************************/
1229 
1230 /*-------------------------------------------------
1231     check_irqs - check for and process IRQs
1232 -------------------------------------------------*/
1233 
check_irqs()1234 void mcs48_cpu_device::check_irqs()
1235 {
1236 	/* if something is in progress, we do nothing */
1237 	if (m_irq_in_progress)
1238 		return;
1239 
1240 	/* external interrupts take priority */
1241 	else if ((m_irq_state || (m_sts & STS_IBF) != 0) && m_xirq_enabled)
1242 	{
1243 		burn_cycles(2);
1244 		m_irq_in_progress = true;
1245 
1246 		// force JNI to be taken (hack)
1247 		if (m_irq_polled)
1248 		{
1249 			m_pc = ((m_prevpc + 1) & 0x7ff) | (m_prevpc & 0x800);
1250 			execute_jcc(true);
1251 		}
1252 
1253 		/* transfer to location 0x03 */
1254 		push_pc_psw();
1255 		m_pc = 0x03;
1256 
1257 		/* indicate we took the external IRQ */
1258 		standard_irq_callback(0);
1259 	}
1260 
1261 	/* timer overflow interrupts follow */
1262 	else if (m_timer_overflow && m_tirq_enabled)
1263 	{
1264 		burn_cycles(2);
1265 		m_irq_in_progress = true;
1266 
1267 		/* transfer to location 0x07 */
1268 		push_pc_psw();
1269 		m_pc = 0x07;
1270 
1271 		/* timer overflow flip-flop is reset once taken */
1272 		m_timer_overflow = false;
1273 	}
1274 }
1275 
1276 
1277 /*-------------------------------------------------
1278     burn_cycles - burn cycles, processing timers
1279     and counters
1280 -------------------------------------------------*/
1281 
burn_cycles(int count)1282 void mcs48_cpu_device::burn_cycles(int count)
1283 {
1284 	if (count == 0)
1285 		return;
1286 
1287 	bool timerover = false;
1288 
1289 	/* if the timer is enabled, accumulate prescaler cycles */
1290 	if (m_timecount_enabled & TIMER_ENABLED)
1291 	{
1292 		uint8_t oldtimer = m_timer;
1293 		m_prescaler += count;
1294 		m_timer += m_prescaler >> 5;
1295 		m_prescaler &= 0x1f;
1296 		timerover = (oldtimer != 0 && m_timer == 0);
1297 	}
1298 
1299 	/* if the counter is enabled, poll the T1 test input once for each cycle */
1300 	else if (m_timecount_enabled & COUNTER_ENABLED)
1301 		for ( ; count > 0; count--, m_icount--)
1302 		{
1303 			m_t1_history = (m_t1_history << 1) | (test_r(1) & 1);
1304 			if ((m_t1_history & 3) == 2)
1305 			{
1306 				if (++m_timer == 0)
1307 					timerover = true;
1308 			}
1309 		}
1310 
1311 	/* if timer counter was disabled, adjust icount here (otherwise count is 0) */
1312 	m_icount -= count;
1313 
1314 	/* if either source caused a timer overflow, set the flags and check IRQs */
1315 	if (timerover)
1316 	{
1317 		m_timer_flag = true;
1318 
1319 		/* according to the docs, if an overflow occurs with interrupts disabled, the overflow is not stored */
1320 		if (m_tirq_enabled)
1321 			m_timer_overflow = true;
1322 	}
1323 }
1324 
1325 
1326 /*-------------------------------------------------
1327     mcs48_execute - execute until we run out
1328     of cycles
1329 -------------------------------------------------*/
1330 
execute_run()1331 void mcs48_cpu_device::execute_run()
1332 {
1333 	update_regptr();
1334 
1335 	// iterate over remaining cycles, guaranteeing at least one instruction
1336 	do
1337 	{
1338 		// check interrupts
1339 		check_irqs();
1340 		m_irq_polled = false;
1341 
1342 		m_prevpc = m_pc;
1343 		debugger_instruction_hook(m_pc);
1344 
1345 		// fetch and process opcode
1346 		unsigned opcode = opcode_fetch();
1347 		(this->*m_opcode_table[opcode])();
1348 
1349 	} while (m_icount > 0);
1350 }
1351 
1352 
1353 
1354 /***************************************************************************
1355     DATA ACCESS HELPERS
1356 ***************************************************************************/
1357 
1358 /*-------------------------------------------------
1359     upi41_master_r - master CPU data/status
1360     read
1361 -------------------------------------------------*/
1362 
upi41_master_r(offs_t offset)1363 uint8_t upi41_cpu_device::upi41_master_r(offs_t offset)
1364 {
1365 	/* if just reading the status, return it */
1366 	if ((offset & 1) != 0)
1367 		return m_sts;
1368 
1369 	/* if the output buffer was full, it gets cleared now */
1370 	if (m_sts & STS_OBF)
1371 	{
1372 		m_sts &= ~STS_OBF;
1373 		if (m_flags_enabled)
1374 			port_w(2, m_p2 &= ~P2_OBF);
1375 	}
1376 	return m_dbbo;
1377 }
1378 
1379 
1380 /*-------------------------------------------------
1381     upi41_master_w - master CPU command/data
1382     write
1383 -------------------------------------------------*/
1384 
TIMER_CALLBACK_MEMBER(upi41_cpu_device::master_callback)1385 TIMER_CALLBACK_MEMBER( upi41_cpu_device::master_callback )
1386 {
1387 	uint8_t a0 = (param >> 8) & 1;
1388 	uint8_t data = param;
1389 
1390 	/* data always goes to the input buffer */
1391 	m_dbbi = data;
1392 
1393 	/* set the appropriate flags */
1394 	if ((m_sts & STS_IBF) == 0)
1395 	{
1396 		m_sts |= STS_IBF;
1397 		if (m_flags_enabled)
1398 			port_w(2, m_p2 &= ~P2_NIBF);
1399 	}
1400 
1401 	/* set F1 accordingly */
1402 	if (a0 == 0)
1403 		m_sts &= ~STS_F1;
1404 	else
1405 		m_sts |= STS_F1;
1406 }
1407 
upi41_master_w(offs_t offset,uint8_t data)1408 void upi41_cpu_device::upi41_master_w(offs_t offset, uint8_t data)
1409 {
1410 	machine().scheduler().synchronize(timer_expired_delegate(FUNC(upi41_cpu_device::master_callback), this), (offset << 8) | data);
1411 }
1412 
1413 
1414 /***************************************************************************
1415     GENERAL CONTEXT ACCESS
1416 ***************************************************************************/
1417 
1418 /*-------------------------------------------------
1419     mcs48_import_state - import state from the
1420     debugger into our internal format
1421 -------------------------------------------------*/
1422 
state_import(const device_state_entry & entry)1423 void mcs48_cpu_device::state_import(const device_state_entry &entry)
1424 {
1425 	switch (entry.index())
1426 	{
1427 		case MCS48_R0:
1428 		case MCS48_R1:
1429 		case MCS48_R2:
1430 		case MCS48_R3:
1431 		case MCS48_R4:
1432 		case MCS48_R5:
1433 		case MCS48_R6:
1434 		case MCS48_R7:
1435 			m_regptr[entry.index() - MCS48_R0] = m_rtemp;
1436 			break;
1437 
1438 		default:
1439 			fatalerror("CPU_IMPORT_STATE(mcs48) called for unexpected value\n");
1440 	}
1441 }
1442 
1443 
1444 /*-------------------------------------------------
1445     mcs48_export_state - prepare state for
1446     exporting to the debugger
1447 -------------------------------------------------*/
1448 
state_export(const device_state_entry & entry)1449 void mcs48_cpu_device::state_export(const device_state_entry &entry)
1450 {
1451 	switch (entry.index())
1452 	{
1453 		case MCS48_R0:
1454 		case MCS48_R1:
1455 		case MCS48_R2:
1456 		case MCS48_R3:
1457 		case MCS48_R4:
1458 		case MCS48_R5:
1459 		case MCS48_R6:
1460 		case MCS48_R7:
1461 			m_rtemp = m_regptr[entry.index() - MCS48_R0];
1462 			break;
1463 
1464 		default:
1465 			fatalerror("CPU_EXPORT_STATE(mcs48) called for unexpected value\n");
1466 	}
1467 }
1468 
state_string_export(const device_state_entry & entry,std::string & str) const1469 void mcs48_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
1470 {
1471 	switch (entry.index())
1472 	{
1473 		case STATE_GENFLAGS:
1474 			str = string_format("%c%c %c%c%c%c%c%c%c%c",
1475 				m_irq_state ? 'I':'.',
1476 				m_a11       ? 'M':'.',
1477 				m_psw & 0x80 ? 'C':'.',
1478 				m_psw & 0x40 ? 'A':'.',
1479 				m_psw & 0x20 ? 'F':'.',
1480 				m_psw & 0x10 ? 'B':'.',
1481 				m_psw & 0x08 ? '?':'.',
1482 				m_psw & 0x04 ? '4':'.',
1483 				m_psw & 0x02 ? '2':'.',
1484 				m_psw & 0x01 ? '1':'.');
1485 			break;
1486 	}
1487 }
1488 
1489 
execute_set_input(int inputnum,int state)1490 void mcs48_cpu_device::execute_set_input(int inputnum, int state)
1491 {
1492 	switch( inputnum )
1493 	{
1494 		case MCS48_INPUT_IRQ:
1495 			m_irq_state = (state != CLEAR_LINE);
1496 			break;
1497 
1498 		case MCS48_INPUT_EA:
1499 			m_ea = (state != CLEAR_LINE);
1500 			break;
1501 	}
1502 }
1503