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