1 // license:BSD-3-Clause
2 // copyright-holders:Carl
3 #ifndef MAME_CPU_I86_I186_H
4 #define MAME_CPU_I86_I186_H
5 
6 #pragma once
7 
8 #include "i86.h"
9 
DECLARE_DEVICE_TYPE(I80186,i80186_cpu_device)10 DECLARE_DEVICE_TYPE(I80186, i80186_cpu_device)
11 DECLARE_DEVICE_TYPE(I80188, i80188_cpu_device)
12 
13 class i80186_cpu_device : public i8086_common_cpu_device
14 {
15 public:
16 	// construction/destruction
17 	i80186_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
18 
19 	auto read_slave_ack_callback() { return m_read_slave_ack_func.bind(); }
20 	auto chip_select_callback() { return m_out_chip_select_func.bind(); }
21 	auto tmrout0_handler() { return m_out_tmrout0_func.bind(); }
22 	auto tmrout1_handler() { return m_out_tmrout1_func.bind(); }
23 	auto irmx_irq_cb() { return m_irmx_irq_cb.bind(); }
24 	template <typename... T> void set_irmx_irq_ack(T &&... args) { m_irmx_irq_ack.set(std::forward<T>(args)...); }
25 
26 	IRQ_CALLBACK_MEMBER(int_callback);
27 	IRQ_CALLBACK_MEMBER(inta_callback);
28 	DECLARE_WRITE_LINE_MEMBER(drq0_w) { m_dma[0].drq_state = state; }
29 	DECLARE_WRITE_LINE_MEMBER(drq1_w) { m_dma[1].drq_state = state; }
30 	DECLARE_WRITE_LINE_MEMBER(tmrin0_w) { if(state && (m_timer[0].control & 0x8004) == 0x8004) { inc_timer(0); } }
31 	DECLARE_WRITE_LINE_MEMBER(tmrin1_w) { if(state && (m_timer[1].control & 0x8004) == 0x8004) { inc_timer(1); } }
32 	DECLARE_WRITE_LINE_MEMBER(int0_w) { external_int(0, state); }
33 	DECLARE_WRITE_LINE_MEMBER(int1_w) { external_int(1, state); }
34 	DECLARE_WRITE_LINE_MEMBER(int2_w) { external_int(2, state); }
35 	DECLARE_WRITE_LINE_MEMBER(int3_w) { external_int(3, state); }
36 
37 	// device_memory_interface overrides
38 	virtual space_config_vector memory_space_config() const override;
39 
40 protected:
41 	enum
42 	{
43 		I80186_RELREG = I8086_HALT + 1,
44 		I80186_UMCS, I80186_LMCS, I80186_PACS, I80186_MMCS, I80186_MPCS,
45 		I80186_DxSRC,
46 		I80186_DxDST = I80186_DxSRC + 2,
47 		I80186_DxTC = I80186_DxDST + 2,
48 		I80186_DxCON = I80186_DxTC + 2,
49 		I80186_TxCNT = I80186_DxCON + 2,
50 		I80186_TxCMPA = I80186_TxCNT + 3,
51 		I80186_TxCMPB = I80186_TxCMPA + 3,
52 		I80186_TxCON = I80186_TxCMPB + 2,
53 		I80186_INSERV = I80186_TxCON + 3,
54 		I80186_REQST, I80186_PRIMSK, I80186_INTSTS,
55 		I80186_TCUCON, I80186_DMA0CON, I80186_DMA1CON,
56 		I80186_I0CON, I80186_I1CON, I80186_I2CON, I80186_I3CON,
57 		I80186_POLLSTS
58 	};
59 
60 	i80186_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int data_bus_size);
61 
62 	// device_execute_interface overrides
63 	virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks / 2); }
64 	virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 2); }
65 	virtual void execute_run() override;
66 	virtual void device_start() override;
67 	virtual void device_reset() override;
68 	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
69 	virtual uint32_t execute_input_lines() const noexcept override { return 1; }
70 	virtual uint8_t fetch() override;
71 	uint32_t update_pc() { return m_pc = (m_sregs[CS] << 4) + m_ip; }
72 
73 	virtual uint8_t read_port_byte(uint16_t port) override;
74 	virtual uint16_t read_port_word(uint16_t port) override;
75 	virtual void write_port_byte(uint16_t port, uint8_t data) override;
76 	void write_port_byte_al(uint16_t port);
77 	virtual void write_port_word(uint16_t port, uint16_t data) override;
78 	virtual uint8_t read_byte(uint32_t addr) override;
79 	virtual uint16_t read_word(uint32_t addr) override;
80 	virtual void write_byte(uint32_t addr, uint8_t data) override;
81 	virtual void write_word(uint32_t addr, uint16_t data) override;
82 
83 	static const uint8_t m_i80186_timing[200];
84 
85 private:
86 	void update_interrupt_state();
87 	void handle_eoi(int data);
88 	void external_int(uint16_t intno, int state);
89 	void internal_timer_sync(int which);
90 	void internal_timer_update(int which, int new_count, int new_maxA, int new_maxB, int new_control);
91 	void update_dma_control(int which, int new_control);
92 	void drq_callback(int which);
93 	void inc_timer(int which);
94 	uint16_t internal_port_r(offs_t offset, uint16_t mem_mask = ~0);
95 	void internal_port_w(offs_t offset, uint16_t data);
96 
97 	struct mem_state
98 	{
99 		uint16_t      lower;
100 		uint16_t      upper;
101 		uint16_t      middle;
102 		uint16_t      middle_size;
103 		uint16_t      peripheral;
104 	};
105 
106 	struct timer_state
107 	{
108 		uint16_t      control;
109 		uint16_t      maxA;
110 		uint16_t      maxB;
111 		bool        active_count;
112 		uint16_t      count;
113 		emu_timer   *int_timer;
114 	};
115 
116 	struct dma_state
117 	{
118 		bool        drq_state;
119 		uint32_t      source;
120 		uint32_t      dest;
121 		uint16_t      count;
122 		uint16_t      control;
123 	};
124 
125 	struct intr_state
126 	{
127 		uint8_t       vector;
128 		uint8_t       pending;
129 		uint16_t      ack_mask;
130 		uint16_t      priority_mask;
131 		uint16_t      in_service;
132 		uint16_t      request;
133 		uint16_t      status;
134 		uint16_t      poll_status;
135 		uint16_t      timer[3];
136 		uint16_t      dma[2];
137 		uint16_t      ext[4];
138 		uint8_t       ext_state;
139 	};
140 
141 	timer_state     m_timer[3];
142 	dma_state       m_dma[2];
143 	intr_state      m_intr;
144 	mem_state       m_mem;
145 	bool            m_last_dma;
146 
147 	static const device_timer_id TIMER_INT0 = 0;
148 	static const device_timer_id TIMER_INT1 = 1;
149 	static const device_timer_id TIMER_INT2 = 2;
150 
151 	uint16_t m_reloc;
152 
153 	address_space_config m_program_config;
154 	address_space_config m_opcodes_config;
155 	address_space_config m_io_config;
156 
157 	devcb_read8 m_read_slave_ack_func;
158 	devcb_write16 m_out_chip_select_func;
159 	devcb_write_line m_out_tmrout0_func;
160 	devcb_write_line m_out_tmrout1_func;
161 	devcb_write_line m_irmx_irq_cb;
162 	device_irq_acknowledge_delegate m_irmx_irq_ack;
163 };
164 
165 class i80188_cpu_device : public i80186_cpu_device
166 {
167 public:
168 	// construction/destruction
169 	i80188_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
170 };
171 
172 #endif // MAME_CPU_I86_I186_H
173