Skip to content

Commit 639578d

Browse files
authored
i86.cpp: Effective Address calculatation time varies greatly from one (#14632)
CPU variant to the next. On the 286, it's effectively free, unless two additions are required, in which case it takes 1 cycle. On the 8088/8086 on the other hand, it can take up to 12 cycles. There needs to be a different set of timings for each CPU variant. I tested on a 286 system (att6300p) with https://thandor.net/benchmark/36, and the score went from 29 to 46 - almost a 60% speedup! Also added a few minor cycle count fixes.
1 parent 0e6366a commit 639578d

File tree

7 files changed

+54
-31
lines changed

7 files changed

+54
-31
lines changed

src/devices/cpu/i86/i186.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,9 @@ i80186_cpu_device::i80186_cpu_device(const machine_config &mconfig, device_type
167167
, m_irmx_irq_ack(*this)
168168
{
169169
memcpy(m_timing, m_i80186_timing, sizeof(m_i80186_timing));
170+
// The Effective Address calculation times are already included in the
171+
// instruction timings for the 80186, so fill the table with zeros.
172+
memset(m_ea_timing, 0, sizeof(m_i80186_ea_timing));
170173
set_irq_acknowledge_callback(*this, FUNC(i80186_cpu_device::inta_callback));
171174
}
172175

src/devices/cpu/i86/i186.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class i80186_cpu_device : public i8086_common_cpu_device
8585
virtual void write_word(uint32_t addr, uint16_t data) override;
8686

8787
static const uint8_t m_i80186_timing[200];
88+
static const uint8_t m_i80186_ea_timing[200];
8889

8990
private:
9091
void update_interrupt_state();

src/devices/cpu/i86/i286.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ const uint8_t i80286_cpu_device::m_i80286_timing[] =
114114
5, 5, 5, 5, /* port reads */
115115
3, 3, 3, 3, /* port writes */
116116

117-
2, 3, 3, /* move, 8-bit */
117+
2, 5, 3, /* move, 8-bit */
118118
2, 3, /* move, 8-bit immediate */
119-
2, 3, 3, /* move, 16-bit */
119+
2, 5, 3, /* move, 16-bit */
120120
2, 3, /* move, 16-bit immediate */
121121
5, 5, 3, 3, /* move, AL/AX memory */
122122
2, 5, 2, 3, /* move, segment registers */
@@ -164,6 +164,25 @@ const uint8_t i80286_cpu_device::m_i80286_timing[] =
164164
13, /* (80186) BOUND */
165165
};
166166

167+
// Effective Address calculation takes one extra clock if offset calculation
168+
// requires summing 3 elements.
169+
const uint8_t i80286_cpu_device::m_i80286_ea_timing[] =
170+
{
171+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
173+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
174+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
175+
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
176+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
177+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
178+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
179+
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
180+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
181+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
182+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
183+
0, 0, 0, 0, 0, 0, 0, 0,
184+
};
185+
167186
DEFINE_DEVICE_TYPE(I80286, i80286_cpu_device, "i80286", "Intel 80286")
168187

169188
i80286_cpu_device::i80286_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@@ -175,6 +194,7 @@ i80286_cpu_device::i80286_cpu_device(const machine_config &mconfig, const char *
175194
, m_out_shutdown_func(*this)
176195
{
177196
memcpy(m_timing, m_i80286_timing, sizeof(m_i80286_timing));
197+
memcpy(m_ea_timing, m_i80286_ea_timing, sizeof(m_i80286_ea_timing));
178198
m_amask = 0xffffff;
179199
memset(m_sregs, 0x00, sizeof(m_sregs));
180200
m_sregs[CS] = 0xf000;

src/devices/cpu/i86/i286.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class i80286_cpu_device : public i8086_common_cpu_device
150150
address_space_config m_opcodes_config;
151151
address_space_config m_io_config;
152152
static const uint8_t m_i80286_timing[200];
153+
static const uint8_t m_i80286_ea_timing[200];
153154

154155
enum {
155156
FAULT_DE = 0,

src/devices/cpu/i86/i86.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,23 @@ const uint8_t i8086_cpu_device::m_i8086_timing[] =
8080
18, 9,17, /* MOVS 16-bit */
8181
};
8282

83+
const uint8_t i8086_cpu_device::m_i8086_ea_timing[] =
84+
{
85+
7, 8, 8, 7, 5, 5, 6, 5, 0, 0, 0, 0, 0, 0, 0, 0,
86+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
87+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
88+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
89+
11, 12, 12, 11, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,
90+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
91+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
92+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
93+
11, 12, 11, 11, 9, 9, 9, 9, 0, 0, 0, 0, 0, 0, 0, 0,
94+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97+
0, 0, 0, 0, 0, 0, 0, 0,
98+
};
99+
83100
/***************************************************************************/
84101
/* cpu state */
85102
/***************************************************************************/
@@ -94,6 +111,7 @@ i8088_cpu_device::i8088_cpu_device(const machine_config &mconfig, const char *ta
94111
: i8086_cpu_device(mconfig, I8088, tag, owner, clock, 8)
95112
{
96113
memcpy(m_timing, m_i8086_timing, sizeof(m_i8086_timing));
114+
memcpy(m_ea_timing, m_i8086_ea_timing, sizeof(m_i8086_ea_timing));
97115
}
98116

99117
i8086_cpu_device::i8086_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@@ -1504,28 +1522,28 @@ bool i8086_common_cpu_device::common_op(uint8_t op)
15041522
m_modrm = fetch();
15051523
m_src = RegByte();
15061524
PutRMByte(m_src);
1507-
CLKM(ALU_RR8,ALU_MR8);
1525+
CLKM(MOV_RR8,MOV_MR8);
15081526
break;
15091527

15101528
case 0x89: // i_mov_wr16
15111529
m_modrm = fetch();
15121530
m_src = RegWord();
15131531
PutRMWord(m_src);
1514-
CLKM(ALU_RR16,ALU_MR16);
1532+
CLKM(MOV_RR16,MOV_MR16);
15151533
break;
15161534

15171535
case 0x8a: // i_mov_r8b
15181536
m_modrm = fetch();
15191537
m_src = GetRMByte();
15201538
RegByte(m_src);
1521-
CLKM(ALU_RR8,ALU_RM8);
1539+
CLKM(MOV_RR8,MOV_RM8);
15221540
break;
15231541

15241542
case 0x8b: // i_mov_r16w
15251543
m_modrm = fetch();
15261544
m_src = GetRMWord();
15271545
RegWord(m_src);
1528-
CLKM(ALU_RR16,ALU_RM16);
1546+
CLKM(MOV_RR16,MOV_RM16);
15291547
break;
15301548

15311549
case 0x8c: // i_mov_wsreg

src/devices/cpu/i86/i86.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ class i8086_common_cpu_device : public cpu_device, public i386_disassembler::con
330330
} m_Mod_RM;
331331

332332
uint8_t m_timing[200];
333+
uint8_t m_ea_timing[200];
333334
bool m_halt;
334335

335336
bool m_lock;
@@ -372,6 +373,7 @@ class i8086_cpu_device : public i8086_common_cpu_device
372373
address_space_config m_extra_config;
373374
address_space_config m_io_config;
374375
static const uint8_t m_i8086_timing[200];
376+
static const uint8_t m_i8086_ea_timing[200];
375377
devcb_write_line m_out_if_func;
376378
devcb_write32 m_esc_opcode_handler;
377379
devcb_write32 m_esc_data_handler;

src/devices/cpu/i86/i86inline.h

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -76,140 +76,118 @@ inline void i8086_common_cpu_device::CLKM(uint8_t op_reg, uint8_t op_mem)
7676
inline uint32_t i8086_common_cpu_device::get_ea(int size, int op)
7777
{
7878
uint16_t e16;
79+
uint8_t modrm = m_modrm & 0xc7;
7980

80-
switch( m_modrm & 0xc7 )
81+
switch( modrm )
8182
{
8283
case 0x00:
83-
m_icount -= 7;
8484
m_eo = m_regs.w[BX] + m_regs.w[SI];
8585
m_ea = calc_addr(DS, m_eo, size, op);
8686
break;
8787
case 0x01:
88-
m_icount -= 8;
8988
m_eo = m_regs.w[BX] + m_regs.w[DI];
9089
m_ea = calc_addr(DS, m_eo, size, op);
9190
break;
9291
case 0x02:
93-
m_icount -= 8;
9492
m_eo = m_regs.w[BP] + m_regs.w[SI];
9593
m_ea = calc_addr(SS, m_eo, size, op);
9694
break;
9795
case 0x03:
98-
m_icount -= 7;
9996
m_eo = m_regs.w[BP] + m_regs.w[DI];
10097
m_ea = calc_addr(SS, m_eo, size, op);
10198
break;
10299
case 0x04:
103-
m_icount -= 5;
104100
m_eo = m_regs.w[SI];
105101
m_ea = calc_addr(DS, m_eo, size, op);
106102
break;
107103
case 0x05:
108-
m_icount -= 5;
109104
m_eo = m_regs.w[DI];
110105
m_ea = calc_addr(DS, m_eo, size, op);
111106
break;
112107
case 0x06:
113-
m_icount -= 6;
114108
m_eo = fetch_word();
115109
m_ea = calc_addr(DS, m_eo, size, op);
116110
break;
117111
case 0x07:
118-
m_icount -= 5;
119112
m_eo = m_regs.w[BX];
120113
m_ea = calc_addr(DS, m_eo, size, op);
121114
break;
122115

123116
case 0x40:
124-
m_icount -= 11;
125117
m_eo = m_regs.w[BX] + m_regs.w[SI] + (int8_t)fetch();
126118
m_ea = calc_addr(DS, m_eo, size, op);
127119
break;
128120
case 0x41:
129-
m_icount -= 12;
130121
m_eo = m_regs.w[BX] + m_regs.w[DI] + (int8_t)fetch();
131122
m_ea = calc_addr(DS, m_eo, size, op);
132123
break;
133124
case 0x42:
134-
m_icount -= 12;
135125
m_eo = m_regs.w[BP] + m_regs.w[SI] + (int8_t)fetch();
136126
m_ea = calc_addr(SS, m_eo, size, op);
137127
break;
138128
case 0x43:
139-
m_icount -= 11;
140129
m_eo = m_regs.w[BP] + m_regs.w[DI] + (int8_t)fetch();
141130
m_ea = calc_addr(SS, m_eo, size, op);
142131
break;
143132
case 0x44:
144-
m_icount -= 9;
145133
m_eo = m_regs.w[SI] + (int8_t)fetch();
146134
m_ea = calc_addr(DS, m_eo, size, op);
147135
break;
148136
case 0x45:
149-
m_icount -= 9;
150137
m_eo = m_regs.w[DI] + (int8_t)fetch();
151138
m_ea = calc_addr(DS, m_eo, size, op);
152139
break;
153140
case 0x46:
154-
m_icount -= 9;
155141
m_eo = m_regs.w[BP] + (int8_t)fetch();
156142
m_ea = calc_addr(SS, m_eo, size, op);
157143
break;
158144
case 0x47:
159-
m_icount -= 9;
160145
m_eo = m_regs.w[BX] + (int8_t)fetch();
161146
m_ea = calc_addr(DS, m_eo, size, op);
162147
break;
163148

164149
case 0x80:
165-
m_icount -= 11;
166150
e16 = fetch_word();
167151
m_eo = m_regs.w[BX] + m_regs.w[SI] + (int16_t)e16;
168152
m_ea = calc_addr(DS, m_eo, size, op);
169153
break;
170154
case 0x81:
171-
m_icount -= 12;
172155
e16 = fetch_word();
173156
m_eo = m_regs.w[BX] + m_regs.w[DI] + (int16_t)e16;
174157
m_ea = calc_addr(DS, m_eo, size, op);
175158
break;
176159
case 0x82:
177-
m_icount -= 11;
178160
e16 = fetch_word();
179161
m_eo = m_regs.w[BP] + m_regs.w[SI] + (int16_t)e16;
180162
m_ea = calc_addr(SS, m_eo, size, op);
181163
break;
182164
case 0x83:
183-
m_icount -= 11;
184165
e16 = fetch_word();
185166
m_eo = m_regs.w[BP] + m_regs.w[DI] + (int16_t)e16;
186167
m_ea = calc_addr(SS, m_eo, size, op);
187168
break;
188169
case 0x84:
189-
m_icount -= 9;
190170
e16 = fetch_word();
191171
m_eo = m_regs.w[SI] + (int16_t)e16;
192172
m_ea = calc_addr(DS, m_eo, size, op);
193173
break;
194174
case 0x85:
195-
m_icount -= 9;
196175
e16 = fetch_word();
197176
m_eo = m_regs.w[DI] + (int16_t)e16;
198177
m_ea = calc_addr(DS, m_eo, size, op);
199178
break;
200179
case 0x86:
201-
m_icount -= 9;
202180
e16 = fetch_word();
203181
m_eo = m_regs.w[BP] + (int16_t)e16;
204182
m_ea = calc_addr(SS, m_eo, size, op);
205183
break;
206184
case 0x87:
207-
m_icount -= 9;
208185
e16 = fetch_word();
209186
m_eo = m_regs.w[BX] + (int16_t)e16;
210187
m_ea = calc_addr(DS, m_eo, size, op);
211188
break;
212189
}
190+
m_icount -= m_ea_timing[modrm];
213191
return m_ea;
214192
}
215193

0 commit comments

Comments
 (0)