summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/ucom4/ucom4.h
blob: 47305a4638a56dccce7f74de3c8d09583b8d49ce (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
// license:BSD-3-Clause
// copyright-holders:hap
/*

  NEC uCOM-4 MCU family cores

*/

#ifndef _UCOM4_H_
#define _UCOM4_H_

#include "emu.h"


// I/O ports setup
#define MCFG_UCOM4_READ_A_CB(_devcb) \
	ucom4_cpu_device::set_read_a_callback(*device, DEVCB_##_devcb);

#define MCFG_UCOM4_READ_B_CB(_devcb) \
	ucom4_cpu_device::set_read_b_callback(*device, DEVCB_##_devcb);

#define MCFG_UCOM4_READ_C_CB(_devcb) \
	ucom4_cpu_device::set_read_c_callback(*device, DEVCB_##_devcb);
#define MCFG_UCOM4_WRITE_C_CB(_devcb) \
	ucom4_cpu_device::set_write_c_callback(*device, DEVCB_##_devcb);

#define MCFG_UCOM4_READ_D_CB(_devcb) \
	ucom4_cpu_device::set_read_d_callback(*device, DEVCB_##_devcb);
#define MCFG_UCOM4_WRITE_D_CB(_devcb) \
	ucom4_cpu_device::set_write_d_callback(*device, DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_E_CB(_devcb) \
	ucom4_cpu_device::set_write_e_callback(*device, DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_F_CB(_devcb) \
	ucom4_cpu_device::set_write_f_callback(*device, DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_G_CB(_devcb) \
	ucom4_cpu_device::set_write_g_callback(*device, DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_H_CB(_devcb) \
	ucom4_cpu_device::set_write_h_callback(*device, DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_I_CB(_devcb) \
	ucom4_cpu_device::set_write_i_callback(*device, DEVCB_##_devcb);

enum
{
	NEC_UCOM4_PORTA = 0,
	NEC_UCOM4_PORTB,
	NEC_UCOM4_PORTC,
	NEC_UCOM4_PORTD,
	NEC_UCOM4_PORTE,
	NEC_UCOM4_PORTF,
	NEC_UCOM4_PORTG,
	NEC_UCOM4_PORTH,
	NEC_UCOM4_PORTI
};

enum
{
	NEC_UCOM43 = 0,
	NEC_UCOM44,
	NEC_UCOM45
};


// pinout reference

/*
            _______   _______
    CL1  1 |*      \_/       | 42 CL0
    PC0  2 |                 | 41 Vgg
    PC1  3 |                 | 40 PB3
    PC2  4 |                 | 39 PB2
    PC3  5 |                 | 38 PB1
   /INT  6 |                 | 37 PB0
  RESET  7 |                 | 36 PA3
    PD0  8 |                 | 35 PA2
    PD1  9 |     uPD552      | 34 PA1
    PD2 10 |     uPD553      | 33 PA0
    PD3 11 |     uPD650*     | 32 PI2
    PE0 12 |                 | 31 PI1
    PE1 13 |                 | 30 PI0
    PE2 14 |                 | 29 PH3
    PE3 15 |                 | 28 PH2
    PF0 16 |                 | 27 PH1
    PF1 17 |                 | 26 PH0
    PF2 18 |                 | 25 PG3
    PF3 19 |                 | 24 PG2
   TEST 20 |                 | 23 PG1
    Vss 21 |_________________| 22 PG0

  *: pin 21 is Vcc, pin 41 is Vss

*/


class ucom4_cpu_device : public cpu_device
{
public:
	// construction/destruction
	ucom4_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, int family, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source)
		: cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
		, m_program_config("program", ENDIANNESS_BIG, 8, prgwidth, 0, program)
		, m_data_config("data", ENDIANNESS_BIG, 8, datawidth, 0, data)
		, m_prgwidth(prgwidth)
		, m_datawidth(datawidth)
		, m_family(family)
		, m_stack_levels(stack_levels)
		, m_read_a(*this)
		, m_read_b(*this)
		, m_read_c(*this)
		, m_read_d(*this)
		, m_write_c(*this)
		, m_write_d(*this)
		, m_write_e(*this)
		, m_write_f(*this)
		, m_write_g(*this)
		, m_write_h(*this)
		, m_write_i(*this)
	{ }

	// static configuration helpers
	template<class _Object> static devcb_base &set_read_a_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_read_a.set_callback(object); }
	template<class _Object> static devcb_base &set_read_b_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_read_b.set_callback(object); }
	template<class _Object> static devcb_base &set_read_c_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_read_c.set_callback(object); }
	template<class _Object> static devcb_base &set_read_d_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_read_d.set_callback(object); }

	template<class _Object> static devcb_base &set_write_c_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_write_c.set_callback(object); }
	template<class _Object> static devcb_base &set_write_d_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_write_d.set_callback(object); }
	template<class _Object> static devcb_base &set_write_e_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_write_e.set_callback(object); }
	template<class _Object> static devcb_base &set_write_f_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_write_f.set_callback(object); }
	template<class _Object> static devcb_base &set_write_g_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_write_g.set_callback(object); }
	template<class _Object> static devcb_base &set_write_h_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_write_h.set_callback(object); }
	template<class _Object> static devcb_base &set_write_i_callback(device_t &device, _Object object) { return downcast<ucom4_cpu_device &>(device).m_write_i.set_callback(object); }

protected:
	// device-level overrides
	virtual void device_start();
	virtual void device_reset();

	// device_execute_interface overrides
	virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 4 - 1) / 4; } // 4 cycles per machine cycle
	virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 4); } // "
	virtual UINT32 execute_min_cycles() const { return 1; }
	virtual UINT32 execute_max_cycles() const { return 2; }
	virtual UINT32 execute_input_lines() const { return 1; }
	virtual void execute_set_input(int line, int state);
	virtual void execute_run();

	// device_memory_interface overrides
	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return(spacenum == AS_PROGRAM) ? &m_program_config : ((spacenum == AS_DATA) ? &m_data_config : NULL); }

	// device_disasm_interface overrides
	virtual UINT32 disasm_min_opcode_bytes() const { return 1; }
	virtual UINT32 disasm_max_opcode_bytes() const { return 2; }
	virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);

	void state_string_export(const device_state_entry &entry, std::string &str);

	address_space_config m_program_config;
	address_space_config m_data_config;
	address_space *m_program;
	address_space *m_data;

	int m_prgwidth;
	int m_datawidth;
	int m_prgmask;
	int m_datamask;
	int m_family;           // MCU family (43/44/45)
	int m_stack_levels;     // number of callstack levels
	UINT16 m_stack[3];      // max 3
	UINT8 m_port_out[0x10]; // last value written to output port
	UINT8 m_op;
	UINT8 m_prev_op;        // previous opcode
	UINT8 m_arg;            // opcode argument for 2-byte opcodes
	UINT8 m_bitmask;        // opcode bit argument
	bool m_skip;            // skip next opcode
	int m_icount;
	emu_timer *m_timer;

	UINT16 m_pc;            // program counter
	UINT16 m_prev_pc;
	UINT8 m_acc;            // 4-bit accumulator
	UINT8 m_dpl;            // 4-bit data pointer low (RAM x)
	UINT8 m_dph;            // 4-bit(?) data pointer high (RAM y)
	UINT8 m_dph_mask;
	UINT8 m_carry_f;        // carry flag
	UINT8 m_carry_s_f;      // carry save flag
	UINT8 m_timer_f;        // timer out flag
	UINT8 m_int_f;          // interrupt flag
	UINT8 m_inte_f;         // interrupt enable flag
	int m_int_line;         // interrupt pin state

	// i/o handlers
	devcb_read8 m_read_a;
	devcb_read8 m_read_b;
	devcb_read8 m_read_c;
	devcb_read8 m_read_d;

	devcb_write8 m_write_c;
	devcb_write8 m_write_d;
	devcb_write8 m_write_e;
	devcb_write8 m_write_f;
	devcb_write8 m_write_g;
	devcb_write8 m_write_h;
	devcb_write8 m_write_i;

	// misc internal helpers
	void increment_pc();
	void fetch_arg();
	void do_interrupt();

	UINT8 ram_r();
	void ram_w(UINT8 data);
	void pop_stack();
	void push_stack();
	virtual UINT8 input_r(int index);
	virtual void output_w(int index, UINT8 data);

	bool check_op_43();
	TIMER_CALLBACK_MEMBER( simple_timer_cb );
	UINT8 ucom43_reg_r(int index);
	void ucom43_reg_w(int index, UINT8 data);

	// opcode handlers
	void op_illegal();

	void op_li();
	void op_lm();
	void op_ldi();
	void op_ldz();
	void op_s();
	void op_tal();
	void op_tla();

	void op_xm();
	void op_xmi();
	void op_xmd();
	void op_ad();
	void op_adc();
	void op_ads();
	void op_daa();
	void op_das();

	void op_exl();
	void op_cma();
	void op_cia();
	void op_clc();
	void op_stc();
	void op_tc();
	void op_inc();
	void op_dec();
	void op_ind();
	void op_ded();

	void op_rmb();
	void op_smb();
	void op_reb();
	void op_seb();
	void op_rpb();
	void op_spb();
	void op_jmpcal();
	void op_jcp();
	void op_jpa();
	void op_czp();
	void op_rt();
	void op_rts();

	void op_ci();
	void op_cm();
	void op_cmb();
	void op_tab();
	void op_cli();
	void op_tmb();
	void op_tpa();
	void op_tpb();

	void op_tit();
	void op_ia();
	void op_ip();
	void op_oe();
	void op_op();
	void op_ocd();
	void op_nop();

	void op_taw();
	void op_taz();
	void op_thx();
	void op_tly();
	void op_xaw();
	void op_xaz();
	void op_xhr();
	void op_xhx();
	void op_xls();
	void op_xly();
	void op_xc();

	void op_sfb();
	void op_rfb();
	void op_fbt();
	void op_fbf();
	void op_rar();
	void op_inm();
	void op_dem();
	void op_stm();
	void op_ttm();
	void op_ei();
	void op_di();
};


class upd553_cpu_device : public ucom4_cpu_device
{
public:
	upd553_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};


class upd650_cpu_device : public ucom4_cpu_device
{
public:
	upd650_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

protected:
	virtual UINT8 input_r(int index);
};


class upd552_cpu_device : public ucom4_cpu_device
{
public:
	upd552_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};



extern const device_type NEC_D553;
extern const device_type NEC_D650;
extern const device_type NEC_D552;


#endif /* _UCOM4_H_ */