summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/hmcs400/hmcs400.h
blob: 4f97c082539ea9a2ee15504beee00dcb444b99ab (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
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
// license:BSD-3-Clause
// copyright-holders:hap
/*

  Hitachi HMCS400 MCU family cores

*/

#ifndef MAME_CPU_HMCS400_HMCS400_H
#define MAME_CPU_HMCS400_HMCS400_H

#pragma once


// input lines

enum
{
	HMCS400_INPUT_LINE_INT0 = 0,
	HMCS400_INPUT_LINE_INT1
};


// pinout reference (see datasheets for other pinouts)

/*
                _________________                            _________________
        D11  1 |*                | 64 D10            D12  1 |*                | 64 D11
        D12  2 |                 | 63 D9             D13  2 |                 | 63 D10
        D13  3 |                 | 62 D8             D14  3 |                 | 62 D9
        D14  4 |                 | 61 D7       RA1/Vdisp  4 |                 | 61 D8
        D15  5 |                 | 60 D6             R00  5 |                 | 60 D7
        R00  6 |                 | 59 D5             R01  6 |                 | 59 D6
        R01  7 |                 | 58 D4             R02  7 |                 | 58 D5
        R02  8 |                 | 57 D3             R03  8 |    HD61412x     | 57 D4
        R03  9 |                 | 56 D2             R10  9 |    HD61414x     | 56 D3
        R10 10 |                 | 55 D1             R11 10 |    HD40x4240    | 55 D2
        R11 11 |                 | 54 D0             R12 11 |                 | 54 D1
        R12 12 |                 | 53 GND            R13 12 |     DP-42       | 53 D0
        R13 13 |                 | 52 OSC2           R20 13 |     DP-42S      | 52 GND
        R20 14 |    HD61402x     | 51 OSC1           R21 14 |                 | 51 OSC2
        R21 15 |    HD61404x     | 50 _TEST          R22 15 |                 | 50 OSC1
        R22 16 |    HD61408x     | 49 RESET          R23 16 |                 | 49 _TEST
        R23 17 |                 | 48 R93            R30 17 |                 | 48 RESET
        RA0 18 |     DP-64S      | 47 R92            R31 18 |                 | 47 R43
  RA1/Vdisp 19 |     DC-64S      | 46 R91      R32/_INT0 19 |                 | 46 R42/SO
        R30 20 |                 | 45 R90      R33/_INT1 20 |                 | 45 R41/SI
        R31 21 |                 | 44 R83            Vcc 21 |_________________| 44 R40/_SCK
  R32/_INT0 22 |                 | 43 R82
  R33/_INT1 23 |                 | 42 R81
        R50 24 |                 | 41 R80
        R51 25 |                 | 40 R73
        R52 26 |                 | 39 R72
        R53 27 |                 | 38 R71
        R60 28 |                 | 37 R70
        R61 29 |                 | 36 R43
        R62 30 |                 | 35 R42/SO
        R63 31 |                 | 34 R41/SI
        Vcc 32 |_________________| 33 R40/_SCK

*/


class hmcs400_cpu_device : public cpu_device, public device_nvram_interface
{
public:
	virtual ~hmcs400_cpu_device();

	// configuration helpers

	// 10 4-bit R ports (port A is 2-bit)
	template <std::size_t N> auto read_r() { return m_read_r[N].bind(); }
	template <std::size_t N> auto write_r() { return m_write_r[N].bind(); }

	// 16-bit discrete
	auto read_d() { return m_read_d.bind(); }
	auto write_d() { return m_write_d.bind(); }

	// system clock divider mask option (only for HMCS408, HMCS41x, HMCS42x)
	// valid options: 4, 8, 16, default to 8
	auto &set_divider(u8 div) { assert(m_has_div); m_divider = div; return *this; }

	// nvram
	void nvram_set_battery(int state) { m_nvram_battery = bool(state); } // default is 1 (nvram_enable_backup needs to be true)
	void nvram_set_default_value(u8 val) { m_nvram_defval = val & 0xf; } // default is 0
	auto stop_cb() { return m_stop_cb.bind(); } // notifier (not an output pin)
	int stop_mode() { return m_stop ? 1 : 0; }

protected:
	// construction
	hmcs400_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 rom_size, u32 ram_size);

	// device_t implementation
	virtual void device_start() override ATTR_COLD;
	virtual void device_reset() override ATTR_COLD;

	// device_nvram_interface implementation
	virtual void nvram_default() override;
	virtual bool nvram_read(util::read_stream &file) override;
	virtual bool nvram_write(util::write_stream &file) override;

	// device_execute_interface implementation
	virtual u64 execute_clocks_to_cycles(u64 clocks) const noexcept override { return (clocks + m_divider - 1) / m_divider; }
	virtual u64 execute_cycles_to_clocks(u64 cycles) const noexcept override { return (cycles * m_divider); }
	virtual u32 execute_min_cycles() const noexcept override { return 1; }
	virtual u32 execute_max_cycles() const noexcept override { return 3+2; } // max 3 + interrupt
	virtual void execute_set_input(int line, int state) override;
	virtual void execute_run() override;

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

	// device_disasm_interface implementation
	virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
	virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;

	// memory maps
	void program_map(address_map &map) ATTR_COLD;
	void data_map(address_map &map) ATTR_COLD;

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

	required_shared_ptr_array<u8, 2> m_ram;
	u8 m_nvram_defval;
	bool m_nvram_battery; // keeps internal RAM intact after soft power-off

	int m_icount;
	int m_state_count;

	const u32 m_rom_size; // ROM size in 16-bit words
	const u32 m_ram_size; // RAM size minus the 64-byte stack
	bool m_has_div;       // MCU supports divider mask option
	u8 m_divider;         // system clock divider

	u16 m_pc;             // program counter
	u16 m_prev_pc;
	u16 m_sp;             // stack pointer
	u16 m_op;             // current opcode
	u16 m_param;          // 2-byte opcode param or RAM address
	u8 m_i;               // 4-bit immediate opcode param

	u8 m_a;               // 4-bit accumulator
	u8 m_b;               // 4-bit B register
	u8 m_w;               // 2-bit W register
	u8 m_x;               // 4-bit X register
	u8 m_spx;             // 4-bit SPX register
	u8 m_y;               // 4-bit Y register
	u8 m_spy;             // 4-bit SPY register
	u8 m_st;              // status flag
	u8 m_ca;              // carry flag
	bool m_standby;       // standby mode (SBY opcode)
	bool m_stop;          // stop mode (STOP opcode)

	u8 m_r[11];           // R pins output state
	u8 m_r_mask[11];      // R pins voltage mask
	u32 m_r_dir;          // R pins I/O direction (bit 0=R, bit 1=W)
	u16 m_d;              // D pins state
	u16 m_d_mask;         // D pins voltage mask

	u8 m_int_line[2];     // INT0/INT1 pin state
	u16 m_irq_flags;      // interrupt control bits
	u16 m_irq_mask;       // valid irq flags bits
	u8 m_pmr;             // port mode register
	u16 m_prescaler;      // 11-bit clock prescaler
	u8 m_timer_mode[2];   // TMA/TMB: timer mode registers
	u16 m_timer_div[2];   // timer prescaler divide ratio masks from TMA/TMB
	u8 m_timer_count[2];  // TCA/TCA: timer counters
	u8 m_timer_load;      // timer B reload register
	u8 m_timer_b_low;     // timer B counter low latch

	// I/O handlers
	devcb_read8::array<11> m_read_r;
	devcb_write8::array<11> m_write_r;
	devcb_read16 m_read_d;
	devcb_write16 m_write_d;
	devcb_write_line m_stop_cb;

	// misc internal helpers
	u8 ram_r(u8 mem_mask = 0xf);
	void ram_w(u8 data, u8 mem_mask = 0xf);
	void pop_stack();
	void push_stack();

	virtual void reset_io();
	u8 read_r(u8 index);
	void write_r(u8 index, u8 data);
	int read_d(u8 index);
	void write_d(u8 index, int state);

	bool access_mode(u8 mem_mask, bool bit_mode = false);
	u8 irq_control_r(offs_t offset, u8 mem_mask);
	void irq_control_w(offs_t offset, u8 data, u8 mem_mask);
	void pmr_w(offs_t offset, u8 data, u8 mem_mask);
	void tm_w(offs_t offset, u8 data, u8 mem_mask);
	void tlrl_w(offs_t offset, u8 data, u8 mem_mask);
	void tlru_w(offs_t offset, u8 data, u8 mem_mask);
	u8 tcbl_r(offs_t offset, u8 mem_mask);
	u8 tcbu_r(offs_t offset, u8 mem_mask);

	void ext_int_edge(int line);
	void take_interrupt(int irq);
	void check_interrupts();
	void clock_timer(int timer);
	void clock_prescaler();
	void cycle();
	u16 fetch();

	// opcode handlers
	void op_illegal();
	void op_todo();

	void op_lai();
	void op_lbi();
	void op_lmi();
	void op_lmiiy();

	void op_lab();
	void op_lba();
	void op_law();
	void op_lay();
	void op_laspx();
	void op_laspy();
	void op_lamr();
	void op_xmra();

	void op_lwi();
	void op_lxi();
	void op_lyi();
	void op_lwa();
	void op_lxa();
	void op_lya();
	void op_iy();
	void op_dy();
	void op_ayy();
	void op_syy();
	void op_xsp();

	void op_lam();
	void op_lbm();
	void op_lma();
	void op_lmaiy();
	void op_lmady();
	void op_xma();
	void op_xmb();

	void op_ai();
	void op_ib();
	void op_db();
	void op_daa();
	void op_das();
	void op_nega();
	void op_comb();
	void op_rotr();
	void op_rotl();
	void op_sec();
	void op_rec();
	void op_tc();
	void op_am();
	void op_amc();
	void op_smc();
	void op_or();
	void op_anm();
	void op_orm();
	void op_eorm();

	void op_inem();
	void op_anem();
	void op_bnem();
	void op_ynei();
	void op_ilem();
	void op_alem();
	void op_blem();
	void op_alei();

	void op_sem();
	void op_rem();
	void op_tm();

	void op_br();
	void op_brl();
	void op_jmpl();
	void op_cal();
	void op_call();
	void op_tbr();
	void op_rtn();
	void op_rtni();

	void op_sed();
	void op_sedd();
	void op_red();
	void op_redd();
	void op_td();
	void op_tdd();
	void op_lar();
	void op_lbr();
	void op_lra();
	void op_lrb();
	void op_p();

	void op_sts();
	void op_sby();
	void op_stop();
};


class hmcs402_cpu_device : public hmcs400_cpu_device
{
protected:
	hmcs402_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};

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

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

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

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

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

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


class hmcs404_cpu_device : public hmcs400_cpu_device
{
protected:
	hmcs404_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};

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

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

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

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

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

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


class hmcs408_cpu_device : public hmcs400_cpu_device
{
protected:
	hmcs408_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};

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

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

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

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

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

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


class hmcs41x_cpu_device : public hmcs400_cpu_device
{
protected:
	hmcs41x_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 rom_size, u32 ram_size);

	virtual void device_start() override ATTR_COLD;
	virtual void reset_io() override;
};

class hmcs412_cpu_device : public hmcs41x_cpu_device
{
protected:
	hmcs412_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};

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

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

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


class hmcs414_cpu_device : public hmcs41x_cpu_device
{
protected:
	hmcs414_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
};

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

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

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


class hmcs424_cpu_device : public hmcs41x_cpu_device
{
protected:
	hmcs424_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);

	virtual void device_start() override ATTR_COLD { hmcs400_cpu_device::device_start(); }
};

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

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

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


DECLARE_DEVICE_TYPE(HD614022, hd614022_device)
DECLARE_DEVICE_TYPE(HD614023, hd614023_device)
DECLARE_DEVICE_TYPE(HD614025, hd614025_device)
DECLARE_DEVICE_TYPE(HD614026, hd614026_device)
DECLARE_DEVICE_TYPE(HD614028, hd614028_device)
DECLARE_DEVICE_TYPE(HD614029, hd614029_device)

DECLARE_DEVICE_TYPE(HD614042, hd614042_device)
DECLARE_DEVICE_TYPE(HD614043, hd614043_device)
DECLARE_DEVICE_TYPE(HD614045, hd614045_device)
DECLARE_DEVICE_TYPE(HD614046, hd614046_device)
DECLARE_DEVICE_TYPE(HD614048, hd614048_device)
DECLARE_DEVICE_TYPE(HD614049, hd614049_device)

DECLARE_DEVICE_TYPE(HD614080, hd614080_device)
DECLARE_DEVICE_TYPE(HD614081, hd614081_device)
DECLARE_DEVICE_TYPE(HD614085, hd614085_device)
DECLARE_DEVICE_TYPE(HD614086, hd614086_device)
DECLARE_DEVICE_TYPE(HD614088, hd614088_device)
DECLARE_DEVICE_TYPE(HD614089, hd614089_device)

DECLARE_DEVICE_TYPE(HD614120, hd614120_device)
DECLARE_DEVICE_TYPE(HD614125, hd614125_device)
DECLARE_DEVICE_TYPE(HD614128, hd614128_device)

DECLARE_DEVICE_TYPE(HD614140, hd614140_device)
DECLARE_DEVICE_TYPE(HD614145, hd614145_device)
DECLARE_DEVICE_TYPE(HD614148, hd614148_device)

DECLARE_DEVICE_TYPE(HD404240, hd404240_device)
DECLARE_DEVICE_TYPE(HD40A4240, hd40a4240_device)
DECLARE_DEVICE_TYPE(HD40L4240, hd40l4240_device)

#endif // MAME_CPU_HMCS400_HMCS400_H