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
|
// license:BSD-3-Clause
// copyright-holders:Carl
#ifndef MAME_CPU_I86_I186_H
#define MAME_CPU_I86_I186_H
#pragma once
#include "i86.h"
DECLARE_DEVICE_TYPE(I80186, i80186_cpu_device)
DECLARE_DEVICE_TYPE(I80188, i80188_cpu_device)
class i80186_cpu_device : public i8086_common_cpu_device
{
public:
// construction/destruction
i80186_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
auto read_slave_ack_callback() { return m_read_slave_ack_func.bind(); }
auto chip_select_callback() { return m_out_chip_select_func.bind(); }
auto tmrout0_handler() { return m_out_tmrout0_func.bind(); }
auto tmrout1_handler() { return m_out_tmrout1_func.bind(); }
IRQ_CALLBACK_MEMBER(int_callback);
DECLARE_WRITE_LINE_MEMBER(drq0_w) { m_dma[0].drq_state = state; }
DECLARE_WRITE_LINE_MEMBER(drq1_w) { m_dma[1].drq_state = state; }
DECLARE_WRITE_LINE_MEMBER(tmrin0_w) { if(state && (m_timer[0].control & 0x8004) == 0x8004) { inc_timer(0); } }
DECLARE_WRITE_LINE_MEMBER(tmrin1_w) { if(state && (m_timer[1].control & 0x8004) == 0x8004) { inc_timer(1); } }
DECLARE_WRITE_LINE_MEMBER(int0_w) { external_int(0, state); }
DECLARE_WRITE_LINE_MEMBER(int1_w) { external_int(1, state); }
DECLARE_WRITE_LINE_MEMBER(int2_w) { external_int(2, state); }
DECLARE_WRITE_LINE_MEMBER(int3_w) { external_int(3, state); }
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
protected:
enum
{
I80186_RELREG = I8086_HALT + 1,
I80186_UMCS, I80186_LMCS, I80186_PACS, I80186_MMCS, I80186_MPCS,
I80186_DxSRC,
I80186_DxDST = I80186_DxSRC + 2,
I80186_DxTC = I80186_DxDST + 2,
I80186_DxCON = I80186_DxTC + 2,
I80186_TxCNT = I80186_DxCON + 2,
I80186_TxCMPA = I80186_TxCNT + 3,
I80186_TxCMPB = I80186_TxCMPA + 3,
I80186_TxCON = I80186_TxCMPB + 2,
I80186_INSERV = I80186_TxCON + 3,
I80186_REQST, I80186_PRIMSK, I80186_INTSTS,
I80186_TCUCON, I80186_DMA0CON, I80186_DMA1CON,
I80186_I0CON, I80186_I1CON, I80186_I2CON, I80186_I3CON,
I80186_POLLSTS
};
i80186_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int data_bus_size);
// device_execute_interface overrides
virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const noexcept override { return (clocks / 2); }
virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const noexcept override { return (cycles * 2); }
virtual void execute_run() override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
virtual uint32_t execute_input_lines() const noexcept override { return 1; }
virtual uint8_t fetch() override;
uint32_t update_pc() { return m_pc = (m_sregs[CS] << 4) + m_ip; }
virtual uint8_t read_port_byte(uint16_t port) override;
virtual uint16_t read_port_word(uint16_t port) override;
virtual void write_port_byte(uint16_t port, uint8_t data) override;
void write_port_byte_al(uint16_t port);
virtual void write_port_word(uint16_t port, uint16_t data) override;
virtual uint8_t read_byte(uint32_t addr) override;
virtual uint16_t read_word(uint32_t addr) override;
virtual void write_byte(uint32_t addr, uint8_t data) override;
virtual void write_word(uint32_t addr, uint16_t data) override;
static const uint8_t m_i80186_timing[200];
private:
void update_interrupt_state();
void handle_eoi(int data);
void external_int(uint16_t intno, int state);
void internal_timer_sync(int which);
void internal_timer_update(int which, int new_count, int new_maxA, int new_maxB, int new_control);
void update_dma_control(int which, int new_control);
void drq_callback(int which);
void inc_timer(int which);
DECLARE_READ16_MEMBER(internal_port_r);
DECLARE_WRITE16_MEMBER(internal_port_w);
struct mem_state
{
uint16_t lower;
uint16_t upper;
uint16_t middle;
uint16_t middle_size;
uint16_t peripheral;
};
struct timer_state
{
uint16_t control;
uint16_t maxA;
uint16_t maxB;
bool active_count;
uint16_t count;
emu_timer *int_timer;
};
struct dma_state
{
bool drq_state;
uint32_t source;
uint32_t dest;
uint16_t count;
uint16_t control;
};
struct intr_state
{
uint8_t pending;
uint16_t ack_mask;
uint16_t priority_mask;
uint16_t in_service;
uint16_t request;
uint16_t status;
uint16_t poll_status;
uint16_t timer;
uint16_t dma[2];
uint16_t ext[4];
uint8_t ext_state;
};
timer_state m_timer[3];
dma_state m_dma[2];
intr_state m_intr;
mem_state m_mem;
bool m_last_dma;
static const device_timer_id TIMER_INT0 = 0;
static const device_timer_id TIMER_INT1 = 1;
static const device_timer_id TIMER_INT2 = 2;
uint16_t m_reloc;
address_space_config m_program_config;
address_space_config m_opcodes_config;
address_space_config m_io_config;
devcb_read8 m_read_slave_ack_func;
devcb_write16 m_out_chip_select_func;
devcb_write_line m_out_tmrout0_func;
devcb_write_line m_out_tmrout1_func;
};
class i80188_cpu_device : public i80186_cpu_device
{
public:
// construction/destruction
i80188_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
};
#endif // MAME_CPU_I86_I186_H
|