summaryrefslogtreecommitdiffstats
path: root/src/devices/cpu/patinhofeio/patinhofeio_cpu.h
blob: ecff53f7249c83ec3f06a629d8dec5b849eda32e (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
// license:GPL-2.0+
// copyright-holders:Felipe Sanches
#ifndef MAME_DEVICES_CPU_PATINHOFEIO_CPU_H
#define MAME_DEVICES_CPU_PATINHOFEIO_CPU_H

#pragma once

#define MCFG_PATINHO_RC_READ_CB(_devcb) \
	devcb = &downcast<patinho_feio_cpu_device &>(*device).set_rc_read_callback(DEVCB_##_devcb);
#define MCFG_PATINHO_BUTTONS_READ_CB(_devcb) \
	devcb = &downcast<patinho_feio_cpu_device &>(*device).set_buttons_read_callback(DEVCB_##_devcb);
#define MCFG_PATINHO_IODEV_READ_CB(devnumber, _devcb) \
	devcb = &downcast<patinho_feio_cpu_device &>(*device).set_iodev_read_callback(devnumber, DEVCB_##_devcb);
#define MCFG_PATINHO_IODEV_WRITE_CB(devnumber, _devcb) \
	devcb = &downcast<patinho_feio_cpu_device &>(*device).set_iodev_write_callback(devnumber, DEVCB_##_devcb);

/* register IDs */
enum
{
	PATINHO_FEIO_CI=1, PATINHO_FEIO_ACC, PATINHO_FEIO_EXT, PATINHO_FEIO_IDX, PATINHO_FEIO_RC
};

enum
{
	NORMAL_MODE,
	CYCLE_STEP_MODE,
	INSTRUCTION_STEP_MODE,
	ADDRESSING_MODE,
	DATA_STORE_MODE,
	DATA_VIEW_MODE
};

#define IODEV_READY true
#define IODEV_BUSY false
#define REQUEST true
#define NO_REQUEST false

#define BUTTON_NORMAL                (1 << 0)  /* normal CPU execution */
#define BUTTON_CICLO_UNICO           (1 << 1)  /* single-cycle step */
#define BUTTON_INSTRUCAO_UNICA       (1 << 2)  /* single-instruction step */
#define BUTTON_ENDERECAMENTO         (1 << 3)  /* addressing action */
#define BUTTON_ARMAZENAMENTO         (1 << 4)  /* storage action */
#define BUTTON_EXPOSICAO             (1 << 5)  /* memory viewing action */
#define BUTTON_ESPERA                (1 << 6)  /* wait */
#define BUTTON_INTERRUPCAO           (1 << 7)  /* interrupt */
#define BUTTON_PARTIDA               (1 << 8)  /* startup */
#define BUTTON_PREPARACAO            (1 << 9)  /* reset */
#define BUTTON_TIPO_DE_ENDERECAMENTO (1 << 10) /* Addressing mode (0: Fixed / 1: Sequential) */
#define BUTTON_PROTECAO_DE_MEMORIA   (1 << 11) /* Memory protection (in the address range 0xF80-0xFFF (1: write-only / 0: read-write) */

class patinho_feio_cpu_device : public cpu_device {
public:
	// construction/destruction
	patinho_feio_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);

	template <class Object> devcb_base &set_rc_read_callback(Object &&cb) { return m_rc_read_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_buttons_read_callback(Object &&cb) { return m_buttons_read_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_iodev_read_callback(int devnumber, Object &&cb) { return m_iodev_read_cb[devnumber].set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_iodev_write_callback(int devnumber, Object &&cb) { return m_iodev_write_cb[devnumber].set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_iodev_status_callback(int devnumber, Object &&cb) { return m_iodev_status_cb[devnumber].set_callback(std::forward<Object>(cb)); }

	void transfer_byte_from_external_device(uint8_t channel, uint8_t data);
	void set_iodev_status(uint8_t channel, bool status) { m_iodev_status[channel] = status; }

	void prog_8bit(address_map &map);
protected:

	virtual void execute_run() override;
	virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;

	address_space_config m_program_config;

	offs_t m_addr;
	unsigned char m_opcode;

	/* processor registers */
	unsigned char m_acc; /* accumulator (8 bits) */
	unsigned int m_pc;   /* program counter (12 bits)
	                      * Actual register name is CI, which
	                      * stands for "Contador de Instrucao"
	                      * or "instructions counter".
	                      */
	unsigned int m_rc; /* RC = "Registrador de Chaves" (Keys Register)
	                    * It represents the 12 bits of input data
	                    * from toggle switches in the computer panel
	                    */
	unsigned char m_idx; /* IDX = Index Register */
	unsigned char m_ext; /* EXT = Accumulator Extension Register */

	/* processor state flip-flops */
	bool m_run; /* processor is running */
	bool m_wait_for_interrupt;
	bool m_interrupts_enabled;
	bool m_scheduled_IND_bit_reset;
	bool m_indirect_addressing;
	bool m_iodev_control[16];
	bool m_iodev_status[16];

	/* 8-bit registers for receiving data from peripherals */
	uint8_t m_iodev_incoming_byte[16];

	/* 8-bit registers for sending data to peripherals */
	uint8_t m_iodev_outgoing_byte[16];

	int m_flags;
	// V = "Vai um" (Carry flag)
	// T = "Transbordo" (Overflow flag)

	int m_address_mask;        /* address mask */
	int m_icount;

	address_space *m_program;

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

	// device_execute_interface overrides
	virtual uint32_t execute_min_cycles() const override { return 1; }
	virtual uint32_t execute_max_cycles() const override { return 2; }

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

private:
	void execute_instruction();
	void compute_effective_address(unsigned int addr);
	void set_flag(uint8_t flag, bool state);
	uint16_t read_panel_keys_register();
	devcb_read16 m_rc_read_cb;
	devcb_read16 m_buttons_read_cb;
	devcb_read8 m_iodev_read_cb[16];
	devcb_write8 m_iodev_write_cb[16];
	devcb_read8 m_iodev_status_cb[16];
	uint8_t m_mode;
};

DECLARE_DEVICE_TYPE(PATO_FEIO_CPU, patinho_feio_cpu_device)

#endif // MAME_DEVICES_CPU_PATINHOFEIO_CPU_H