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