summaryrefslogtreecommitdiffstats
path: root/src/devices/cpu/ucom4/ucom4.h
blob: 77f963a61e951c5f87cd7f3afdc1e7f1f4f20494 (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
345
346
347
// license:BSD-3-Clause
// copyright-holders:hap
/*

  NEC uCOM-4 MCU family cores

*/

#ifndef MAME_CPU_UCOM4_UCOM4_H
#define MAME_CPU_UCOM4_UCOM4_H

#pragma once


// I/O ports setup
#define MCFG_UCOM4_READ_A_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_read_a_callback(DEVCB_##_devcb);

#define MCFG_UCOM4_READ_B_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_read_b_callback(DEVCB_##_devcb);

#define MCFG_UCOM4_READ_C_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_read_c_callback(DEVCB_##_devcb);
#define MCFG_UCOM4_WRITE_C_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_write_c_callback(DEVCB_##_devcb);

#define MCFG_UCOM4_READ_D_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_read_d_callback(DEVCB_##_devcb);
#define MCFG_UCOM4_WRITE_D_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_write_d_callback(DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_E_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_write_e_callback(DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_F_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_write_f_callback(DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_G_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_write_g_callback(DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_H_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_write_h_callback(DEVCB_##_devcb);

#define MCFG_UCOM4_WRITE_I_CB(_devcb) \
	devcb = &downcast<ucom4_cpu_device &>(*device).set_write_i_callback(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 |     uPD546      | 34 PA1
    PD2 10 |     uPD552      | 33 PA0
    PD3 11 |     uPD553      | 32 PI2
    PE0 12 |     uPD650*     | 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:
	// configuration helpers
	template <class Object> devcb_base &set_read_a_callback(Object &&cb) { return m_read_a.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_read_b_callback(Object &&cb) { return m_read_b.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_read_c_callback(Object &&cb) { return m_read_c.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_read_d_callback(Object &&cb) { return m_read_d.set_callback(std::forward<Object>(cb)); }

	template <class Object> devcb_base &set_write_c_callback(Object &&cb) { return m_write_c.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_write_d_callback(Object &&cb) { return m_write_d.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_write_e_callback(Object &&cb) { return m_write_e.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_write_f_callback(Object &&cb) { return m_write_f.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_write_g_callback(Object &&cb) { return m_write_g.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_write_h_callback(Object &&cb) { return m_write_h.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_write_i_callback(Object &&cb) { return m_write_i.set_callback(std::forward<Object>(cb)); }

protected:
	// construction/destruction
	ucom4_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int family, int stack_levels, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data);

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

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

	// device_memory_interface overrides
	virtual space_config_vector memory_space_config() const override;

	// device_disasm_interface overrides
	virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;

	// device_state_interface overrides
	virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;

	// memorymaps
	void program_1k(address_map &map);
	void program_2k(address_map &map);
	void data_64x4(address_map &map);
	void data_96x4(address_map &map);

	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
	u16 m_stack[3];      // max 3
	u8 m_port_out[0x10]; // last value written to output port
	u8 m_op;
	u8 m_prev_op;        // previous opcode
	u8 m_arg;            // opcode argument for 2-byte opcodes
	u8 m_bitmask;        // opcode bit argument
	bool m_skip;         // skip next opcode
	int m_icount;
	emu_timer *m_timer;

	u16 m_pc;            // program counter
	u16 m_prev_pc;
	u8 m_acc;            // 4-bit accumulator
	u8 m_dpl;            // 4-bit data pointer low (RAM x)
	u8 m_dph;            // 4-bit(?) data pointer high (RAM y)
	u8 m_dph_mask;
	u8 m_carry_f;        // carry flag
	u8 m_carry_s_f;      // carry save flag
	u8 m_timer_f;        // timer out flag
	u8 m_int_f;          // interrupt flag
	u8 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;

	virtual u8 input_r(int index);
	virtual void output_w(int index, u8 data);

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

	u8 ram_r();
	void ram_w(u8 data);
	void pop_stack();
	void push_stack();

	bool check_op_43();
	TIMER_CALLBACK_MEMBER( simple_timer_cb );
	u8 ucom43_reg_r(int index);
	void ucom43_reg_w(int index, u8 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 upd546_cpu_device : public ucom4_cpu_device
{
public:
	upd546_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};


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


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

protected:
	virtual u8 input_r(int index) override;
	virtual void output_w(int index, u8 data) override;
};


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


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



DECLARE_DEVICE_TYPE(NEC_D546,  upd546_cpu_device)
DECLARE_DEVICE_TYPE(NEC_D553,  upd553_cpu_device)
DECLARE_DEVICE_TYPE(NEC_D557L, upd557l_cpu_device)
DECLARE_DEVICE_TYPE(NEC_D650,  upd650_cpu_device)
DECLARE_DEVICE_TYPE(NEC_D552,  upd552_cpu_device)

#endif // MAME_CPU_UCOM4_UCOM4_H