1 // license:BSD-3-Clause
2 // copyright-holders:Carl
3 /****************************************************************************
4
5 NEC V20/V30/V33 emulator modified back to a 8086/80186 emulator
6
7 (Re)Written June-September 2000 by Bryan McPhail (mish@tendril.co.uk) based
8 on code by Oliver Bergmann (Raul_Bloodworth@hotmail.com) who based code
9 on the i286 emulator by Fabrice Frances which had initial work based on
10 David Hedley's pcemu(!).
11
12 ****************************************************************************/
13
14 #include "emu.h"
15 #include "i86.h"
16 #include "debugger.h"
17 #include "i86inline.h"
18 #include "cpu/i386/i386dasm.h"
19
20 #define I8086_NMI_INT_VECTOR 2
21
22 const uint8_t i8086_cpu_device::m_i8086_timing[] =
23 {
24 51,32, /* exception, IRET */
25 2, 0, 4, 2, /* INTs */
26 2, /* segment overrides */
27 2, 4, 4, /* flag operations */
28 4, 4,83,60, /* arithmetic adjusts */
29 4, 4, /* decimal adjusts */
30 2, 5, /* sign extension */
31 2,24, 2, 2, 3,11, /* misc */
32
33 15,15,15, /* direct JMPs */
34 11,18,24, /* indirect JMPs */
35 19,28, /* direct CALLs */
36 16,21,37, /* indirect CALLs */
37 20,32,24,31, /* returns */
38 4,16, 6,18, /* conditional JMPs */
39 5,17, 6,18, /* loops */
40
41 10,14, 8,12, /* port reads */
42 10,14, 8,12, /* port writes */
43
44 2, 8, 9, /* move, 8-bit */
45 4,10, /* move, 8-bit immediate */
46 2, 8, 9, /* move, 16-bit */
47 4,10, /* move, 16-bit immediate */
48 10,10,10,10, /* move, AL/AX memory */
49 2, 8, 2, 9, /* move, segment registers */
50 4,17, /* exchange, 8-bit */
51 4,17, 3, /* exchange, 16-bit */
52
53 15,24,14,14, /* pushes */
54 12,25,12,12, /* pops */
55
56 3, 9,16, /* ALU ops, 8-bit */
57 4,17,10, /* ALU ops, 8-bit immediate */
58 3, 9,16, /* ALU ops, 16-bit */
59 4,17,10, /* ALU ops, 16-bit immediate */
60 4,17,10, /* ALU ops, 16-bit w/8-bit immediate */
61 70,118,76,128, /* MUL */
62 80,128,86,138, /* IMUL */
63 80,144,86,154, /* DIV */
64 101,165,107,175,/* IDIV */
65 3, 2,15,15, /* INC/DEC */
66 3, 3,16,16, /* NEG/NOT */
67
68 2, 8, 4, /* reg shift/rotate */
69 15,20, 4, /* m8 shift/rotate */
70 15,20, 4, /* m16 shift/rotate */
71
72 22, 9,21, /* CMPS 8-bit */
73 22, 9,21, /* CMPS 16-bit */
74 15, 9,14, /* SCAS 8-bit */
75 15, 9,14, /* SCAS 16-bit */
76 12, 9,11, /* LODS 8-bit */
77 12, 9,11, /* LODS 16-bit */
78 11, 9,10, /* STOS 8-bit */
79 11, 9,10, /* STOS 16-bit */
80 18, 9,17, /* MOVS 8-bit */
81 18, 9,17, /* MOVS 16-bit */
82 };
83
84 /***************************************************************************/
85 /* cpu state */
86 /***************************************************************************/
87
88
89 /***************************************************************************/
90
91 DEFINE_DEVICE_TYPE(I8086, i8086_cpu_device, "i8086", "Intel 8086")
92 DEFINE_DEVICE_TYPE(I8088, i8088_cpu_device, "i8088", "Intel 8088")
93
i8088_cpu_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)94 i8088_cpu_device::i8088_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
95 : i8086_cpu_device(mconfig, I8088, tag, owner, clock, 8)
96 {
97 memcpy(m_timing, m_i8086_timing, sizeof(m_i8086_timing));
98 }
99
i8086_cpu_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)100 i8086_cpu_device::i8086_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
101 : i8086_cpu_device(mconfig, I8086, tag, owner, clock, 16)
102 {
103 memcpy(m_timing, m_i8086_timing, sizeof(m_i8086_timing));
104 }
105
i8086_cpu_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,int data_bus_size)106 i8086_cpu_device::i8086_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int data_bus_size)
107 : i8086_common_cpu_device(mconfig, type, tag, owner, clock)
108 , m_program_config("program", ENDIANNESS_LITTLE, data_bus_size, 20, 0)
109 , m_opcodes_config("opcodes", ENDIANNESS_LITTLE, data_bus_size, 20, 0)
110 , m_stack_config("stack", ENDIANNESS_LITTLE, data_bus_size, 20, 0)
111 , m_code_config("code", ENDIANNESS_LITTLE, data_bus_size, 20, 0)
112 , m_extra_config("extra", ENDIANNESS_LITTLE, data_bus_size, 20, 0)
113 , m_io_config("io", ENDIANNESS_LITTLE, data_bus_size, 16, 0)
114 , m_out_if_func(*this)
115 , m_esc_opcode_handler(*this)
116 , m_esc_data_handler(*this)
117 {
118 }
119
memory_space_config() const120 device_memory_interface::space_config_vector i8086_cpu_device::memory_space_config() const
121 {
122 space_config_vector spaces = {
123 std::make_pair(AS_PROGRAM, &m_program_config),
124 std::make_pair(AS_IO, &m_io_config)
125 };
126 if(has_configured_map(AS_OPCODES))
127 spaces.push_back(std::make_pair(AS_OPCODES, &m_opcodes_config));
128 if(has_configured_map(AS_STACK))
129 spaces.push_back(std::make_pair(AS_STACK, &m_stack_config));
130 if(has_configured_map(AS_CODE))
131 spaces.push_back(std::make_pair(AS_CODE, &m_code_config));
132 if(has_configured_map(AS_EXTRA))
133 spaces.push_back(std::make_pair(AS_EXTRA, &m_extra_config));
134 return spaces;
135 }
136
fetch()137 uint8_t i8086_cpu_device::fetch()
138 {
139 uint8_t data;
140 data = m_or8(update_pc());
141 m_ip++;
142 return data;
143 }
144
sreg_to_space(int sreg) const145 address_space *i8086_cpu_device::sreg_to_space(int sreg) const
146 {
147 switch(sreg)
148 {
149 default:
150 return m_program;
151 case CS:
152 return m_code;
153 case SS:
154 return m_stack;
155 case ES:
156 return m_extra;
157 }
158 }
159
read_byte(uint32_t addr)160 uint8_t i8086_cpu_device::read_byte(uint32_t addr)
161 {
162 return sreg_to_space(m_easeg)->read_byte(addr);
163 }
164
read_word(uint32_t addr)165 uint16_t i8086_cpu_device::read_word(uint32_t addr)
166 {
167 return sreg_to_space(m_easeg)->read_word_unaligned(addr);
168 }
169
write_byte(uint32_t addr,uint8_t data)170 void i8086_cpu_device::write_byte(uint32_t addr, uint8_t data)
171 {
172 sreg_to_space(m_easeg)->write_byte(addr, data);
173 }
174
write_word(uint32_t addr,uint16_t data)175 void i8086_cpu_device::write_word(uint32_t addr, uint16_t data)
176 {
177 sreg_to_space(m_easeg)->write_word_unaligned(addr, data);
178 }
179
execute_run()180 void i8086_cpu_device::execute_run()
181 {
182 u8 iflag = m_IF;
183 while(m_icount > 0 )
184 {
185 if ( m_seg_prefix_next )
186 {
187 m_seg_prefix = true;
188 m_seg_prefix_next = false;
189 }
190 else
191 {
192 m_prev_ip = m_ip;
193 m_seg_prefix = false;
194
195 /* Dispatch IRQ */
196 if ( m_pending_irq && (m_no_interrupt == 0) )
197 {
198 if ( m_pending_irq & NMI_IRQ )
199 {
200 interrupt(I8086_NMI_INT_VECTOR);
201 m_pending_irq &= ~NMI_IRQ;
202 m_halt = false;
203 }
204 else if ( m_IF )
205 {
206 /* the actual vector is retrieved after pushing flags */
207 /* and clearing the IF */
208 interrupt(-1);
209 m_halt = false;
210 }
211 }
212
213 if(m_halt)
214 {
215 m_icount = 0;
216 return;
217 }
218
219 /* Trap should allow one instruction to be executed.
220 CPUID.ASM (by Bob Smith, 1985) suggests that in situations where m_no_interrupt is 1,
221 (directly after POP SS / MOV_SREG), single step IRQs don't fire.
222 */
223 if (m_fire_trap )
224 {
225 if ( (m_fire_trap >= 2) && (m_no_interrupt == 0) )
226 {
227 m_fire_trap = 0; // reset trap flag upon entry
228 interrupt(1);
229 }
230 else
231 {
232 m_fire_trap++;
233 }
234 }
235
236 /* No interrupt allowed between last instruction and this one */
237 if ( m_no_interrupt )
238 {
239 m_no_interrupt--;
240 }
241
242 }
243
244 if (!m_seg_prefix)
245 {
246 debugger_instruction_hook( update_pc() );
247 }
248
249 uint8_t op = fetch_op();
250
251 switch(op)
252 {
253 case 0x0f:
254 m_sregs[CS] = POP();
255 CLK(POP_SEG);
256 break;
257
258 case 0xd2: // i_rotshft_bcl
259 {
260 uint8_t c;
261
262 m_modrm = fetch();
263 m_src = GetRMByte();
264 m_dst = m_src;
265 c = m_regs.b[CL];
266 CLKM(ROT_REG_BASE,ROT_M8_BASE);
267 m_icount -= m_timing[ROT_REG_BIT] * c;
268 if (c)
269 {
270 switch ( m_modrm & 0x38 )
271 {
272 case 0x00: do { ROL_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
273 case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
274 case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
275 case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
276 case 0x30:
277 case 0x20: SHL_BYTE(c); break;
278 case 0x28: SHR_BYTE(c); break;
279 case 0x38: SHRA_BYTE(c); break;
280 }
281 }
282 }
283 break;
284
285 case 0xd3: // i_rotshft_wcl
286 {
287 uint8_t c;
288
289 m_modrm = fetch();
290 m_src = GetRMWord();
291 m_dst = m_src;
292 c = m_regs.b[CL];
293 CLKM(ROT_REG_BASE,ROT_M16_BASE);
294 m_icount -= m_timing[ROT_REG_BIT] * c;
295 if (c)
296 {
297 switch ( m_modrm & 0x38 )
298 {
299 case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
300 case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
301 case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
302 case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
303 case 0x30:
304 case 0x20: SHL_WORD(c); break;
305 case 0x28: SHR_WORD(c); break;
306 case 0x38: SHRA_WORD(c); break;
307 }
308 }
309 }
310 break;
311
312 case 0xd8: // i_esc
313 case 0xd9:
314 case 0xda:
315 case 0xdb:
316 case 0xdc:
317 case 0xdd:
318 case 0xde:
319 case 0xdf:
320 m_esc_opcode_handler(m_pc);
321 m_modrm = fetch();
322 if(m_modrm < 0xc0)
323 m_esc_data_handler(get_ea(1, I8086_READ));
324 else
325 m_esc_data_handler(0);
326 CLK(NOP);
327 break;
328
329 default:
330 if(!common_op(op))
331 {
332 m_icount -= 10;
333 logerror("%06x: Invalid Opcode %02x\n", m_pc, op);
334 break;
335 }
336 break;
337 }
338 if(iflag != m_IF)
339 {
340 m_out_if_func(m_IF ? ASSERT_LINE : CLEAR_LINE);
341 iflag = m_IF;
342 }
343 }
344 }
345
device_start()346 void i8086_cpu_device::device_start()
347 {
348 i8086_common_cpu_device::device_start();
349 m_out_if_func.resolve_safe();
350 m_esc_opcode_handler.resolve_safe();
351 m_esc_data_handler.resolve_safe();
352 m_stack = has_space(AS_STACK) ? &space(AS_STACK) : m_program;
353 m_code = has_space(AS_CODE) ? &space(AS_CODE) : m_program;
354 m_extra = has_space(AS_EXTRA) ? &space(AS_EXTRA) : m_program;
355 state_add( I8086_ES, "ES", m_sregs[ES] ).formatstr("%04X");
356 state_add( I8086_CS, "CS", m_sregs[CS] ).callimport().formatstr("%04X");
357 state_add( I8086_SS, "SS", m_sregs[SS] ).formatstr("%04X");
358 state_add( I8086_DS, "DS", m_sregs[DS] ).formatstr("%04X");
359 state_add( I8086_VECTOR, "V", m_int_vector).formatstr("%02X");
360
361 state_add( I8086_PC, "PC", m_pc ).callimport().formatstr("%05X");
362 state_add<uint32_t>( STATE_GENPCBASE, "CURPC", [this] { return (m_sregs[CS] << 4) + m_prev_ip; }).mask(0xfffff).noshow();
363 state_add( I8086_HALT, "HALT", m_halt ).mask(1);
364 }
365
i8086_common_cpu_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)366 i8086_common_cpu_device::i8086_common_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
367 : cpu_device(mconfig, type, tag, owner, clock)
368 , m_ip(0)
369 , m_TF(0)
370 , m_int_vector(0)
371 , m_pending_irq(0)
372 , m_nmi_state(0)
373 , m_irq_state(0)
374 , m_test_state(1)
375 , m_pc(0)
376 , m_lock(false)
377 , m_lock_handler(*this)
378 {
379 static const BREGS reg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH };
380
381 /* Set up parity lookup table. */
382 for (uint16_t i = 0;i < 256; i++)
383 {
384 uint16_t c = 0;
385 for (uint16_t j = i; j > 0; j >>= 1)
386 {
387 if (j & 1) c++;
388 }
389 m_parity_table[i] = !(c & 1);
390 }
391
392 for (uint16_t i = 0; i < 256; i++)
393 {
394 m_Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
395 m_Mod_RM.reg.w[i] = (WREGS) ( (i & 0x38) >> 3) ;
396 }
397
398 for (uint16_t i = 0xc0; i < 0x100; i++)
399 {
400 m_Mod_RM.RM.w[i] = (WREGS)( i & 7 );
401 m_Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
402 }
403
404 memset(&m_regs, 0x00, sizeof(m_regs));
405 memset(m_sregs, 0x00, sizeof(m_sregs));
406 }
407
408
409 //-------------------------------------------------
410 // state_import - import state into the device,
411 // after it has been set
412 //-------------------------------------------------
413
state_import(const device_state_entry & entry)414 void i8086_common_cpu_device::state_import(const device_state_entry &entry)
415 {
416 switch (entry.index())
417 {
418 case I8086_IP:
419 case I8086_CS:
420 m_pc = (m_sregs[CS] << 4) + m_ip;
421 break;
422
423 case STATE_GENPC:
424 if (m_pc - (m_sregs[CS] << 4) > 0xffff)
425 m_sregs[CS] = m_pc >> 4;
426 m_ip = m_pc - (m_sregs[CS] << 4);
427 m_prev_ip = m_ip;
428 break;
429 }
430 }
431
432
433 //-------------------------------------------------
434 // state_string_export - export state as a string
435 // for the debugger
436 //-------------------------------------------------
437
state_string_export(const device_state_entry & entry,std::string & str) const438 void i8086_common_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
439 {
440 switch (entry.index())
441 {
442 case STATE_GENFLAGS:
443 {
444 uint16_t flags = CompressFlags();
445 str = string_format("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
446 flags & 0x8000 ? '1':'.',
447 flags & 0x4000 ? '1':'.',
448 flags & 0x2000 ? '1':'.',
449 flags & 0x1000 ? '1':'.',
450 flags & 0x0800 ? 'O':'.',
451 flags & 0x0400 ? 'D':'.',
452 flags & 0x0200 ? 'I':'.',
453 flags & 0x0100 ? 'T':'.',
454 flags & 0x0080 ? 'S':'.',
455 flags & 0x0040 ? 'Z':'.',
456 flags & 0x0020 ? '0':'.',
457 flags & 0x0010 ? 'A':'.',
458 flags & 0x0008 ? '0':'.',
459 flags & 0x0004 ? 'P':'.',
460 flags & 0x0002 ? '1':'.',
461 flags & 0x0001 ? 'C':'.');
462 }
463 break;
464 }
465 }
466
device_start()467 void i8086_common_cpu_device::device_start()
468 {
469 m_program = &space(AS_PROGRAM);
470 m_opcodes = has_space(AS_OPCODES) ? &space(AS_OPCODES) : m_program;
471
472 if(m_opcodes->data_width() == 8) {
473 m_opcodes->cache(m_cache8);
474 m_or8 = [this](offs_t address) -> u8 { return m_cache8.read_byte(address); };
475 } else {
476 m_opcodes->cache(m_cache16);
477 m_or8 = [this](offs_t address) -> u8 { return m_cache16.read_byte(address); };
478 }
479 m_io = &space(AS_IO);
480
481 save_item(NAME(m_regs.w));
482 save_item(NAME(m_sregs));
483 save_item(NAME(m_ip));
484 save_item(NAME(m_prev_ip));
485 save_item(NAME(m_TF));
486 save_item(NAME(m_IF));
487 save_item(NAME(m_DF));
488 save_item(NAME(m_MF));
489 save_item(NAME(m_NT));
490 save_item(NAME(m_IOPL));
491 save_item(NAME(m_SignVal));
492 save_item(NAME(m_int_vector));
493 save_item(NAME(m_pending_irq));
494 save_item(NAME(m_nmi_state));
495 save_item(NAME(m_irq_state));
496 save_item(NAME(m_AuxVal));
497 save_item(NAME(m_OverVal));
498 save_item(NAME(m_ZeroVal));
499 save_item(NAME(m_CarryVal));
500 save_item(NAME(m_ParityVal));
501 save_item(NAME(m_seg_prefix));
502 save_item(NAME(m_seg_prefix_next));
503 save_item(NAME(m_prefix_seg));
504 save_item(NAME(m_halt));
505
506 // Register state for debugger
507 state_add( I8086_IP, "IP", m_ip ).callimport().formatstr("%04X");
508 state_add( I8086_AX, "AX", m_regs.w[AX] ).formatstr("%04X");
509 state_add( I8086_CX, "CX", m_regs.w[CX] ).formatstr("%04X");
510 state_add( I8086_DX, "DX", m_regs.w[DX] ).formatstr("%04X");
511 state_add( I8086_BX, "BX", m_regs.w[BX] ).formatstr("%04X");
512 state_add( I8086_SP, "SP", m_regs.w[SP] ).formatstr("%04X");
513 state_add( I8086_BP, "BP", m_regs.w[BP] ).formatstr("%04X");
514 state_add( I8086_SI, "SI", m_regs.w[SI] ).formatstr("%04X");
515 state_add( I8086_DI, "DI", m_regs.w[DI] ).formatstr("%04X");
516
517 state_add( I8086_AL, "AL", m_regs.b[AL] ).noshow();
518 state_add( I8086_AH, "AH", m_regs.b[AH] ).noshow();
519 state_add( I8086_CL, "CL", m_regs.b[CL] ).noshow();
520 state_add( I8086_CH, "CH", m_regs.b[CH] ).noshow();
521 state_add( I8086_DL, "DL", m_regs.b[DL] ).noshow();
522 state_add( I8086_DH, "DH", m_regs.b[DH] ).noshow();
523 state_add( I8086_BL, "BL", m_regs.b[BL] ).noshow();
524 state_add( I8086_BH, "BH", m_regs.b[BH] ).noshow();
525
526 state_add(STATE_GENFLAGS, "GENFLAGS", m_TF).formatstr("%16s").noshow();
527
528 set_icountptr(m_icount);
529
530 m_lock_handler.resolve_safe();
531 }
532
533
device_reset()534 void i8086_common_cpu_device::device_reset()
535 {
536 m_ZeroVal = 1;
537 m_ParityVal = 1;
538 m_regs.w[AX] = 0;
539 m_regs.w[CX] = 0;
540 m_regs.w[DX] = 0;
541 m_regs.w[BX] = 0;
542 m_regs.w[SP] = 0;
543 m_regs.w[BP] = 0;
544 m_regs.w[SI] = 0;
545 m_regs.w[DI] = 0;
546 m_sregs[ES] = 0;
547 m_sregs[CS] = 0xffff;
548 m_sregs[SS] = 0;
549 m_sregs[DS] = 0;
550 m_ip = 0;
551 m_prev_ip = 0;
552 m_SignVal = 0;
553 m_AuxVal = 0;
554 m_OverVal = 0;
555 m_CarryVal = 0;
556 m_TF = 0;
557 m_IF = 0;
558 m_DF = 0;
559 m_IOPL = 3; // 8086 IOPL always 3
560 m_NT = 1; // 8086 NT always 1
561 m_MF = 1; // 8086 MF always 1, 80286 always 0
562 m_int_vector = 0;
563 m_pending_irq = 0;
564 m_nmi_state = 0;
565 m_irq_state = 0;
566 m_no_interrupt = 0;
567 m_fire_trap = 0;
568 m_prefix_seg = 0;
569 m_seg_prefix = false;
570 m_seg_prefix_next = false;
571 m_ea = 0;
572 m_eo = 0;
573 m_modrm = 0;
574 m_dst = 0;
575 m_src = 0;
576 m_halt = false;
577 m_lock = false;
578 m_easeg = DS;
579 }
580
581
582
interrupt(int int_num,int trap)583 void i8086_common_cpu_device::interrupt(int int_num, int trap)
584 {
585 PUSH( CompressFlags() );
586 m_TF = m_IF = 0;
587
588 if (int_num == -1)
589 int_num = standard_irq_callback(0);
590 debugger_exception_hook(int_num);
591
592 m_easeg = CS;
593 uint16_t dest_off = read_word(int_num * 4 + 0);
594 uint16_t dest_seg = read_word(int_num * 4 + 2);
595
596 PUSH(m_sregs[CS]);
597 PUSH(m_ip);
598 m_prev_ip = m_ip = dest_off;
599 m_sregs[CS] = dest_seg;
600 }
601
602
execute_set_input(int inptnum,int state)603 void i8086_common_cpu_device::execute_set_input( int inptnum, int state )
604 {
605 if (inptnum == INPUT_LINE_NMI)
606 {
607 if ( m_nmi_state == state )
608 {
609 return;
610 }
611 m_nmi_state = state;
612 if (state != CLEAR_LINE)
613 {
614 m_pending_irq |= NMI_IRQ;
615 }
616 }
617 else if (inptnum == INPUT_LINE_TEST)
618 {
619 m_test_state = state;
620 }
621 else
622 {
623 m_irq_state = state;
624 if (state == CLEAR_LINE)
625 {
626 m_pending_irq &= ~INT_IRQ;
627 }
628 else
629 {
630 m_pending_irq |= INT_IRQ;
631 }
632 }
633 }
634
create_disassembler()635 std::unique_ptr<util::disasm_interface> i8086_common_cpu_device::create_disassembler()
636 {
637 return std::make_unique<i386_disassembler>(this);
638 }
639
get_mode() const640 int i8086_common_cpu_device::get_mode() const
641 {
642 return 1;
643 }
644
read_byte(uint32_t addr)645 uint8_t i8086_common_cpu_device::read_byte(uint32_t addr)
646 {
647 return m_program->read_byte(addr);
648 }
649
read_word(uint32_t addr)650 uint16_t i8086_common_cpu_device::read_word(uint32_t addr)
651 {
652 return m_program->read_word_unaligned(addr);
653 }
654
write_byte(uint32_t addr,uint8_t data)655 void i8086_common_cpu_device::write_byte(uint32_t addr, uint8_t data)
656 {
657 m_program->write_byte(addr, data);
658 }
659
write_word(uint32_t addr,uint16_t data)660 void i8086_common_cpu_device::write_word(uint32_t addr, uint16_t data)
661 {
662 m_program->write_word_unaligned(addr, data);
663 }
664
read_port_byte(uint16_t port)665 uint8_t i8086_common_cpu_device::read_port_byte(uint16_t port)
666 {
667 return m_io->read_byte(port);
668 }
669
read_port_word(uint16_t port)670 uint16_t i8086_common_cpu_device::read_port_word(uint16_t port)
671 {
672 return m_io->read_word_unaligned(port);
673 }
674
write_port_byte(uint16_t port,uint8_t data)675 void i8086_common_cpu_device::write_port_byte(uint16_t port, uint8_t data)
676 {
677 m_io->write_byte(port, data);
678 }
679
write_port_word(uint16_t port,uint16_t data)680 void i8086_common_cpu_device::write_port_word(uint16_t port, uint16_t data)
681 {
682 m_io->write_word_unaligned(port, data);
683 }
684
calc_addr(int seg,uint16_t offset,int size,int op,bool override)685 uint32_t i8086_common_cpu_device::calc_addr(int seg, uint16_t offset, int size, int op, bool override)
686 {
687 if ( m_seg_prefix && (seg==DS || seg==SS) && override )
688 {
689 m_easeg = m_seg_prefix;
690 return (m_sregs[m_prefix_seg] << 4) + offset;
691 }
692 else
693 {
694 m_easeg = seg;
695 return (m_sregs[seg] << 4) + offset;
696 }
697 }
698
common_op(uint8_t op)699 bool i8086_common_cpu_device::common_op(uint8_t op)
700 {
701 switch(op)
702 {
703 case 0x00: // i_add_br8
704 DEF_br8();
705 set_CFB(ADDB());
706 PutbackRMByte(m_dst);
707 CLKM(ALU_RR8,ALU_MR8);
708 break;
709
710 case 0x01: // i_add_wr16
711 DEF_wr16();
712 set_CFW(ADDX());
713 PutbackRMWord(m_dst);
714 CLKM(ALU_RR16,ALU_MR16);
715 break;
716
717 case 0x02: // i_add_r8b
718 DEF_r8b();
719 set_CFB(ADDB());
720 RegByte(m_dst);
721 CLKM(ALU_RR8,ALU_RM8);
722 break;
723
724 case 0x03: // i_add_r16w
725 DEF_r16w();
726 set_CFW(ADDX());
727 RegWord(m_dst);
728 CLKM(ALU_RR16,ALU_RM16);
729 break;
730
731 case 0x04: // i_add_ald8
732 DEF_ald8();
733 set_CFB(ADDB());
734 m_regs.b[AL] = m_dst;
735 CLK(ALU_RI8);
736 break;
737
738 case 0x05: // i_add_axd16
739 DEF_axd16();
740 set_CFW(ADDX());
741 m_regs.w[AX] = m_dst;
742 CLK(ALU_RI16);
743 break;
744
745 case 0x06: // i_push_es
746 PUSH(m_sregs[ES]);
747 CLK(PUSH_SEG);
748 break;
749
750 case 0x07: // i_pop_es
751 m_sregs[ES] = POP();
752 CLK(POP_SEG);
753 break;
754
755 case 0x08: // i_or_br8
756 DEF_br8();
757 ORB();
758 PutbackRMByte(m_dst);
759 CLKM(ALU_RR8,ALU_MR8);
760 break;
761
762 case 0x09: // i_or_wr16
763 DEF_wr16();
764 ORW();
765 PutbackRMWord(m_dst);
766 CLKM(ALU_RR16,ALU_MR16);
767 break;
768
769 case 0x0a: // i_or_r8b
770 DEF_r8b();
771 ORB();
772 RegByte(m_dst);
773 CLKM(ALU_RR8,ALU_RM8);
774 break;
775
776 case 0x0b: // i_or_r16w
777 DEF_r16w();
778 ORW();
779 RegWord(m_dst);
780 CLKM(ALU_RR16,ALU_RM16);
781 break;
782
783 case 0x0c: // i_or_ald8
784 DEF_ald8();
785 ORB();
786 m_regs.b[AL] = m_dst;
787 CLK(ALU_RI8);
788 break;
789
790 case 0x0d: // i_or_axd16
791 DEF_axd16();
792 ORW();
793 m_regs.w[AX] = m_dst;
794 CLK(ALU_RI16);
795 break;
796
797 case 0x0e: // i_push_cs
798 PUSH(m_sregs[CS]);
799 CLK(PUSH_SEG);
800 break;
801
802 case 0x10: // i_adc_br8
803 {
804 DEF_br8();
805 m_src += CF ? 1 : 0;
806 uint32_t tmpcf = ADDB();
807 PutbackRMByte(m_dst);
808 set_CFB(tmpcf);
809 CLKM(ALU_RR8,ALU_MR8);
810 break;
811 }
812 case 0x11: // i_adc_wr16
813 {
814 DEF_wr16();
815 m_src += CF ? 1 : 0;
816 uint32_t tmpcf = ADDX();
817 PutbackRMWord(m_dst);
818 set_CFW(tmpcf);
819 CLKM(ALU_RR16,ALU_MR16);
820 break;
821 }
822
823 case 0x12: // i_adc_r8b
824 DEF_r8b();
825 m_src += CF ? 1 : 0;
826 set_CFB(ADDB());
827 RegByte(m_dst);
828 CLKM(ALU_RR8,ALU_RM8);
829 break;
830
831 case 0x13: // i_adc_r16w
832 DEF_r16w();
833 m_src += CF ? 1 : 0;
834 set_CFW(ADDX());
835 RegWord(m_dst);
836 CLKM(ALU_RR16,ALU_RM16);
837 break;
838
839 case 0x14: // i_adc_ald8
840 DEF_ald8();
841 m_src += CF ? 1 : 0;
842 set_CFB(ADDB());
843 m_regs.b[AL] = m_dst;
844 CLK(ALU_RI8);
845 break;
846
847 case 0x15: // i_adc_axd16
848 DEF_axd16();
849 m_src += CF ? 1 : 0;
850 set_CFW(ADDX());
851 m_regs.w[AX] = m_dst;
852 CLK(ALU_RI16);
853 break;
854
855 case 0x16: // i_push_ss
856 PUSH(m_sregs[SS]);
857 CLK(PUSH_SEG);
858 break;
859
860 case 0x17: // i_pop_ss
861 m_sregs[SS] = POP();
862 CLK(POP_SEG);
863 m_no_interrupt = 1;
864 break;
865
866 case 0x18: // i_sbb_br8
867 {
868 uint32_t tmpcf;
869 DEF_br8();
870 m_src += CF ? 1 : 0;
871 tmpcf = SUBB();
872 PutbackRMByte(m_dst);
873 set_CFB(tmpcf);
874 CLKM(ALU_RR8,ALU_MR8);
875 break;
876 }
877
878 case 0x19: // i_sbb_wr16
879 {
880 uint32_t tmpcf;
881 DEF_wr16();
882 m_src += CF ? 1 : 0;
883 tmpcf = SUBX();
884 PutbackRMWord(m_dst);
885 set_CFW(tmpcf);
886 CLKM(ALU_RR16,ALU_MR16);
887 break;
888 }
889
890 case 0x1a: // i_sbb_r8b
891 DEF_r8b();
892 m_src += CF ? 1 : 0;
893 set_CFB(SUBB());
894 RegByte(m_dst);
895 CLKM(ALU_RR8,ALU_RM8);
896 break;
897
898 case 0x1b: // i_sbb_r16w
899 DEF_r16w();
900 m_src += CF ? 1 : 0;
901 set_CFW(SUBX());
902 RegWord(m_dst);
903 CLKM(ALU_RR16,ALU_RM16);
904 break;
905
906 case 0x1c: // i_sbb_ald8
907 DEF_ald8();
908 m_src += CF ? 1 : 0;
909 set_CFB(SUBB());
910 m_regs.b[AL] = m_dst;
911 CLK(ALU_RI8);
912 break;
913
914 case 0x1d: // i_sbb_axd16
915 DEF_axd16();
916 m_src += CF ? 1 : 0;
917 set_CFW(SUBX());
918 m_regs.w[AX] = m_dst;
919 CLK(ALU_RI16);
920 break;
921
922 case 0x1e: // i_push_ds
923 PUSH(m_sregs[DS]);
924 CLK(PUSH_SEG);
925 break;
926
927 case 0x1f: // i_pop_ds
928 m_sregs[DS] = POP();
929 CLK(POP_SEG);
930 break;
931
932
933 case 0x20: // i_and_br8
934 DEF_br8();
935 ANDB();
936 PutbackRMByte(m_dst);
937 CLKM(ALU_RR8,ALU_MR8);
938 break;
939
940 case 0x21: // i_and_wr16
941 DEF_wr16();
942 ANDX();
943 PutbackRMWord(m_dst);
944 CLKM(ALU_RR16,ALU_MR16);
945 break;
946
947 case 0x22: // i_and_r8b
948 DEF_r8b();
949 ANDB();
950 RegByte(m_dst);
951 CLKM(ALU_RR8,ALU_RM8);
952 break;
953
954 case 0x23: // i_and_r16w
955 DEF_r16w();
956 ANDX();
957 RegWord(m_dst);
958 CLKM(ALU_RR16,ALU_RM16);
959 break;
960
961 case 0x24: // i_and_ald8
962 DEF_ald8();
963 ANDB();
964 m_regs.b[AL] = m_dst;
965 CLK(ALU_RI8);
966 break;
967
968 case 0x25: // i_and_axd16
969 DEF_axd16();
970 ANDX();
971 m_regs.w[AX] = m_dst;
972 CLK(ALU_RI16);
973 break;
974
975 case 0x26: // i_es
976 m_seg_prefix_next = true;
977 m_prefix_seg = ES;
978 CLK(OVERRIDE);
979 break;
980
981 case 0x27: // i_daa
982 ADJ4(6,0x60);
983 CLK(DAA);
984 break;
985
986
987 case 0x28: // i_sub_br8
988 DEF_br8();
989 set_CFB(SUBB());
990 PutbackRMByte(m_dst);
991 CLKM(ALU_RR8,ALU_MR8);
992 break;
993
994 case 0x29: // i_sub_wr16
995 DEF_wr16();
996 set_CFW(SUBX());
997 PutbackRMWord(m_dst);
998 CLKM(ALU_RR16,ALU_MR16);
999 break;
1000
1001 case 0x2a: // i_sub_r8b
1002 DEF_r8b();
1003 set_CFB(SUBB());
1004 RegByte(m_dst);
1005 CLKM(ALU_RR8,ALU_RM8);
1006 break;
1007
1008 case 0x2b: // i_sub_r16w
1009 DEF_r16w();
1010 set_CFW(SUBX());
1011 RegWord(m_dst);
1012 CLKM(ALU_RR16,ALU_RM16);
1013 break;
1014
1015 case 0x2c: // i_sub_ald8
1016 DEF_ald8();
1017 set_CFB(SUBB());
1018 m_regs.b[AL] = m_dst;
1019 CLK(ALU_RI8);
1020 break;
1021
1022 case 0x2d: // i_sub_axd16
1023 DEF_axd16();
1024 set_CFW(SUBX());
1025 m_regs.w[AX] = m_dst;
1026 CLK(ALU_RI16);
1027 break;
1028
1029 case 0x2e: // i_cs
1030 m_seg_prefix_next = true;
1031 m_prefix_seg = CS;
1032 CLK(OVERRIDE);
1033 break;
1034
1035 case 0x2f: // i_das
1036 ADJ4(-6,-0x60);
1037 CLK(DAS);
1038 break;
1039
1040
1041 case 0x30: // i_xor_br8
1042 DEF_br8();
1043 XORB();
1044 PutbackRMByte(m_dst);
1045 CLKM(ALU_RR8,ALU_MR8);
1046 break;
1047
1048 case 0x31: // i_xor_wr16
1049 DEF_wr16();
1050 XORW();
1051 PutbackRMWord(m_dst);
1052 CLKM(ALU_RR16,ALU_RM16);
1053 break;
1054
1055 case 0x32: // i_xor_r8b
1056 DEF_r8b();
1057 XORB();
1058 RegByte(m_dst);
1059 CLKM(ALU_RR8,ALU_RM8);
1060 break;
1061
1062 case 0x33: // i_xor_r16w
1063 DEF_r16w();
1064 XORW();
1065 RegWord(m_dst);
1066 CLKM(ALU_RR16,ALU_RM16);
1067 break;
1068
1069 case 0x34: // i_xor_ald8
1070 DEF_ald8();
1071 XORB();
1072 m_regs.b[AL] = m_dst;
1073 CLK(ALU_RI8);
1074 break;
1075
1076 case 0x35: // i_xor_axd16
1077 DEF_axd16();
1078 XORW();
1079 m_regs.w[AX] = m_dst;
1080 CLK(ALU_RI16);
1081 break;
1082
1083 case 0x36: // i_ss
1084 m_seg_prefix_next = true;
1085 m_prefix_seg = SS;
1086 CLK(OVERRIDE);
1087 break;
1088
1089 case 0x37: // i_aaa
1090 ADJB(6, (m_regs.b[AL] > 0xf9) ? 2 : 1);
1091 CLK(AAA);
1092 break;
1093
1094
1095 case 0x38: // i_cmp_br8
1096 DEF_br8();
1097 set_CFB(SUBB());
1098 CLKM(ALU_RR8,ALU_RM8);
1099 break;
1100
1101 case 0x39: // i_cmp_wr16
1102 DEF_wr16();
1103 set_CFW(SUBX());
1104 CLKM(ALU_RR16,ALU_RM16);
1105 break;
1106
1107 case 0x3a: // i_cmp_r8b
1108 DEF_r8b();
1109 set_CFB(SUBB());
1110 CLKM(ALU_RR8,ALU_RM8);
1111 break;
1112
1113 case 0x3b: // i_cmp_r16w
1114 DEF_r16w();
1115 set_CFW(SUBX());
1116 CLKM(ALU_RR16,ALU_RM16);
1117 break;
1118
1119 case 0x3c: // i_cmp_ald8
1120 DEF_ald8();
1121 set_CFB(SUBB());
1122 CLK(ALU_RI8);
1123 break;
1124
1125 case 0x3d: // i_cmp_axd16
1126 DEF_axd16();
1127 set_CFW(SUBX());
1128 CLK(ALU_RI16);
1129 break;
1130
1131 case 0x3e: // i_ds
1132 m_seg_prefix_next = true;
1133 m_prefix_seg = DS;
1134 CLK(OVERRIDE);
1135 break;
1136
1137 case 0x3f: // i_aas
1138 ADJB(-6, (m_regs.b[AL] < 6) ? -2 : -1);
1139 CLK(AAS);
1140 break;
1141
1142
1143 case 0x40: // i_inc_ax
1144 IncWordReg(AX);
1145 CLK(INCDEC_R16);
1146 break;
1147
1148 case 0x41: // i_inc_cx
1149 IncWordReg(CX);
1150 CLK(INCDEC_R16);
1151 break;
1152
1153 case 0x42: // i_inc_dx
1154 IncWordReg(DX);
1155 CLK(INCDEC_R16);
1156 break;
1157
1158 case 0x43: // i_inc_bx
1159 IncWordReg(BX);
1160 CLK(INCDEC_R16);
1161 break;
1162
1163 case 0x44: // i_inc_sp
1164 IncWordReg(SP);
1165 CLK(INCDEC_R16);
1166 break;
1167
1168 case 0x45: // i_inc_bp
1169 IncWordReg(BP);
1170 CLK(INCDEC_R16);
1171 break;
1172
1173 case 0x46: // i_inc_si
1174 IncWordReg(SI);
1175 CLK(INCDEC_R16);
1176 break;
1177
1178 case 0x47: // i_inc_di
1179 IncWordReg(DI);
1180 CLK(INCDEC_R16);
1181 break;
1182
1183
1184 case 0x48: // i_dec_ax
1185 DecWordReg(AX);
1186 CLK(INCDEC_R16);
1187 break;
1188
1189 case 0x49: // i_dec_cx
1190 DecWordReg(CX);
1191 CLK(INCDEC_R16);
1192 break;
1193
1194 case 0x4a: // i_dec_dx
1195 DecWordReg(DX);
1196 CLK(INCDEC_R16);
1197 break;
1198
1199 case 0x4b: // i_dec_bx
1200 DecWordReg(BX);
1201 CLK(INCDEC_R16);
1202 break;
1203
1204 case 0x4c: // i_dec_sp
1205 DecWordReg(SP);
1206 CLK(INCDEC_R16);
1207 break;
1208
1209 case 0x4d: // i_dec_bp
1210 DecWordReg(BP);
1211 CLK(INCDEC_R16);
1212 break;
1213
1214 case 0x4e: // i_dec_si
1215 DecWordReg(SI);
1216 CLK(INCDEC_R16);
1217 break;
1218
1219 case 0x4f: // i_dec_di
1220 DecWordReg(DI);
1221 CLK(INCDEC_R16);
1222 break;
1223
1224
1225 case 0x50: // i_push_ax
1226 PUSH(m_regs.w[AX]);
1227 CLK(PUSH_R16);
1228 break;
1229
1230 case 0x51: // i_push_cx
1231 PUSH(m_regs.w[CX]);
1232 CLK(PUSH_R16);
1233 break;
1234
1235 case 0x52: // i_push_dx
1236 PUSH(m_regs.w[DX]);
1237 CLK(PUSH_R16);
1238 break;
1239
1240 case 0x53: // i_push_bx
1241 PUSH(m_regs.w[BX]);
1242 CLK(PUSH_R16);
1243 break;
1244
1245 case 0x54: // i_push_sp
1246 PUSH(m_regs.w[SP]-2);
1247 CLK(PUSH_R16);
1248 break;
1249
1250 case 0x55: // i_push_bp
1251 PUSH(m_regs.w[BP]);
1252 CLK(PUSH_R16);
1253 break;
1254
1255 case 0x56: // i_push_si
1256 PUSH(m_regs.w[SI]);
1257 CLK(PUSH_R16);
1258 break;
1259
1260 case 0x57: // i_push_di
1261 PUSH(m_regs.w[DI]);
1262 CLK(PUSH_R16);
1263 break;
1264
1265
1266 case 0x58: // i_pop_ax
1267 m_regs.w[AX] = POP();
1268 CLK(POP_R16);
1269 break;
1270
1271 case 0x59: // i_pop_cx
1272 m_regs.w[CX] = POP();
1273 CLK(POP_R16);
1274 break;
1275
1276 case 0x5a: // i_pop_dx
1277 m_regs.w[DX] = POP();
1278 CLK(POP_R16);
1279 break;
1280
1281 case 0x5b: // i_pop_bx
1282 m_regs.w[BX] = POP();
1283 CLK(POP_R16);
1284 break;
1285
1286 case 0x5c: // i_pop_sp
1287 m_regs.w[SP] = POP();
1288 CLK(POP_R16);
1289 break;
1290
1291 case 0x5d: // i_pop_bp
1292 m_regs.w[BP] = POP();
1293 CLK(POP_R16);
1294 break;
1295
1296 case 0x5e: // i_pop_si
1297 m_regs.w[SI] = POP();
1298 CLK(POP_R16);
1299 break;
1300
1301 case 0x5f: // i_pop_di
1302 m_regs.w[DI] = POP();
1303 CLK(POP_R16);
1304 break;
1305
1306 // 8086 'invalid opcodes', as documented at http://www.os2museum.com/wp/?p=2147 and tested on real hardware
1307 // - 0x60 - 0x6f are aliases to 0x70 - 0x7f.
1308 // - 0xc0, 0xc1, 0xc8, 0xc9 are also aliases where the CPU ignores BIT 1 (*).
1309 // - 0xf1 is an alias to 0xf0.
1310 //
1311 // Instructions are used in the boot sector for some versions of
1312 // MS-DOS (e.g. the DEC Rainbow-100 version of DOS 2.x)
1313 case 0x60:
1314 case 0x70: // i_jo
1315 JMP( OF);
1316 break;
1317
1318 case 0x61:
1319 case 0x71: // i_jno
1320 JMP(!OF);
1321 break;
1322
1323 case 0x62:
1324 case 0x72: // i_jc
1325 JMP( CF);
1326 break;
1327
1328 case 0x63:
1329 case 0x73: // i_jnc
1330 JMP(!CF);
1331 break;
1332
1333 case 0x64:
1334 case 0x74: // i_jz
1335 JMP( ZF);
1336 break;
1337
1338 case 0x65:
1339 case 0x75: // i_jnz
1340 JMP(!ZF);
1341 break;
1342
1343 case 0x66:
1344 case 0x76: // i_jce
1345 JMP(CF || ZF);
1346 break;
1347
1348 case 0x67:
1349 case 0x77: // i_jnce
1350 JMP(!(CF || ZF));
1351 break;
1352
1353 case 0x68:
1354 case 0x78: // i_js
1355 JMP( SF);
1356 break;
1357
1358 case 0x69:
1359 case 0x79: // i_jns
1360 JMP(!SF);
1361 break;
1362
1363 case 0x6a:
1364 case 0x7a: // i_jp
1365 JMP( PF);
1366 break;
1367
1368 case 0x6b:
1369 case 0x7b: // i_jnp
1370 JMP(!PF);
1371 break;
1372
1373 case 0x6c:
1374 case 0x7c: // i_jl
1375 JMP((SF!=OF)&&(!ZF));
1376 break;
1377
1378 case 0x6d:
1379 case 0x7d: // i_jnl
1380 JMP(SF==OF);
1381 break;
1382
1383 case 0x6e:
1384 case 0x7e: // i_jle
1385 JMP((ZF)||(SF!=OF));
1386 break;
1387
1388 case 0x6f:
1389 case 0x7f: // i_jnle
1390 JMP((SF==OF)&&(!ZF));
1391 break;
1392
1393
1394 case 0x80: // i_80pre
1395 {
1396 uint32_t tmpcf;
1397 m_modrm = fetch();
1398 m_dst = GetRMByte();
1399 m_src = fetch();
1400 if (m_modrm >=0xc0 ) { CLK(ALU_RI8); }
1401 else if ((m_modrm & 0x38)==0x38) { CLK(ALU_MI8_RO); }
1402 else { CLK(ALU_MI8); }
1403 switch (m_modrm & 0x38)
1404 {
1405 case 0x00: set_CFB(ADDB()); PutbackRMByte(m_dst); break;
1406 case 0x08: ORB(); PutbackRMByte(m_dst); break;
1407 case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break;
1408 case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break;
1409 case 0x20: ANDB(); PutbackRMByte(m_dst); break;
1410 case 0x28: set_CFB(SUBB()); PutbackRMByte(m_dst); break;
1411 case 0x30: XORB(); PutbackRMByte(m_dst); break;
1412 case 0x38: set_CFB(SUBB()); break; /* CMP */
1413 }
1414 break;
1415 }
1416
1417
1418 case 0x81: // i_81pre
1419 {
1420 uint32_t tmpcf;
1421 m_modrm = fetch();
1422 m_dst = GetRMWord();
1423 m_src = fetch_word();
1424 if (m_modrm >=0xc0 ) { CLK(ALU_RI16); }
1425 else if ((m_modrm & 0x38)==0x38) { CLK(ALU_MI16_RO); }
1426 else { CLK(ALU_MI16); }
1427 switch (m_modrm & 0x38)
1428 {
1429 case 0x00: set_CFW(ADDX()); PutbackRMWord(m_dst); break;
1430 case 0x08: ORW(); PutbackRMWord(m_dst); break;
1431 case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break;
1432 case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break;
1433 case 0x20: ANDX(); PutbackRMWord(m_dst); break;
1434 case 0x28: set_CFW(SUBX()); PutbackRMWord(m_dst); break;
1435 case 0x30: XORW(); PutbackRMWord(m_dst); break;
1436 case 0x38: set_CFW(SUBX()); break; /* CMP */
1437 }
1438 break;
1439 }
1440
1441
1442 case 0x82: // i_82pre
1443 {
1444 uint32_t tmpcf;
1445 m_modrm = fetch();
1446 m_dst = GetRMByte();
1447 m_src = (int8_t)fetch();
1448 if (m_modrm >=0xc0 ) { CLK(ALU_RI8); }
1449 else if ((m_modrm & 0x38)==0x38) { CLK(ALU_MI8_RO); }
1450 else { CLK(ALU_MI8); }
1451 switch (m_modrm & 0x38)
1452 {
1453 case 0x00: set_CFB(ADDB()); PutbackRMByte(m_dst); break;
1454 case 0x08: ORB(); PutbackRMByte(m_dst); break;
1455 case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break;
1456 case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break;
1457 case 0x20: ANDB(); PutbackRMByte(m_dst); break;
1458 case 0x28: set_CFB(SUBB()); PutbackRMByte(m_dst); break;
1459 case 0x30: XORB(); PutbackRMByte(m_dst); break;
1460 case 0x38: set_CFB(SUBB()); break; /* CMP */
1461 }
1462 break;
1463 }
1464
1465
1466 case 0x83: // i_83pre
1467 {
1468 uint32_t tmpcf;
1469 m_modrm = fetch();
1470 m_dst = GetRMWord();
1471 m_src = (uint16_t)((int16_t)((int8_t)fetch()));
1472 if (m_modrm >=0xc0 ) { CLK(ALU_R16I8); }
1473 else if ((m_modrm & 0x38)==0x38) { CLK(ALU_M16I8_RO); }
1474 else { CLK(ALU_M16I8); }
1475 switch (m_modrm & 0x38)
1476 {
1477 case 0x00: set_CFW(ADDX()); PutbackRMWord(m_dst); break;
1478 case 0x08: ORW(); PutbackRMWord(m_dst); break;
1479 case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break;
1480 case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break;
1481 case 0x20: ANDX(); PutbackRMWord(m_dst); break;
1482 case 0x28: set_CFW(SUBX()); PutbackRMWord(m_dst); break;
1483 case 0x30: XORW(); PutbackRMWord(m_dst); break;
1484 case 0x38: set_CFW(SUBX()); break; /* CMP */
1485 }
1486 break;
1487 }
1488
1489
1490 case 0x84: // i_test_br8
1491 DEF_br8();
1492 ANDB();
1493 CLKM(ALU_RR8,ALU_RM8);
1494 break;
1495
1496 case 0x85: // i_test_wr16
1497 DEF_wr16();
1498 ANDX();
1499 CLKM(ALU_RR16,ALU_RM16);
1500 break;
1501
1502 case 0x86: // i_xchg_br8
1503 DEF_br8();
1504 RegByte(m_dst);
1505 PutbackRMByte(m_src);
1506 CLKM(XCHG_RR8,XCHG_RM8);
1507 break;
1508
1509 case 0x87: // i_xchg_wr16
1510 DEF_wr16();
1511 RegWord(m_dst);
1512 PutbackRMWord(m_src);
1513 CLKM(XCHG_RR16,XCHG_RM16);
1514 break;
1515
1516
1517 case 0x88: // i_mov_br8
1518 m_modrm = fetch();
1519 m_src = RegByte();
1520 PutRMByte(m_src);
1521 CLKM(ALU_RR8,ALU_MR8);
1522 break;
1523
1524 case 0x89: // i_mov_wr16
1525 m_modrm = fetch();
1526 m_src = RegWord();
1527 PutRMWord(m_src);
1528 CLKM(ALU_RR16,ALU_MR16);
1529 break;
1530
1531 case 0x8a: // i_mov_r8b
1532 m_modrm = fetch();
1533 m_src = GetRMByte();
1534 RegByte(m_src);
1535 CLKM(ALU_RR8,ALU_RM8);
1536 break;
1537
1538 case 0x8b: // i_mov_r16w
1539 m_modrm = fetch();
1540 m_src = GetRMWord();
1541 RegWord(m_src);
1542 CLKM(ALU_RR16,ALU_RM16);
1543 break;
1544
1545 case 0x8c: // i_mov_wsreg
1546 m_modrm = fetch();
1547 PutRMWord(m_sregs[(m_modrm & 0x18) >> 3]); // confirmed on hw: modrm bit 5 ignored
1548 CLKM(MOV_RS,MOV_MS);
1549 break;
1550
1551 case 0x8d: // i_lea
1552 m_modrm = fetch();
1553 get_ea(0, I8086_NONE);
1554 RegWord(m_eo);
1555 CLK(LEA);
1556 break;
1557
1558 case 0x8e: // i_mov_sregw
1559 m_modrm = fetch();
1560 m_src = GetRMWord();
1561 m_sregs[(m_modrm & 0x18) >> 3] = m_src; // confirmed on hw: modrm bit 5 ignored
1562 CLKM(MOV_SR,MOV_SM);
1563 m_no_interrupt = 1; // Disable IRQ after load segment register.
1564 break;
1565
1566 case 0x8f: // i_popw
1567 m_modrm = fetch();
1568 PutRMWord( POP() );
1569 CLKM(POP_R16,POP_M16);
1570 break;
1571
1572 case 0x90: // i_nop
1573 CLK(NOP);
1574 break;
1575
1576 case 0x91: // i_xchg_axcx
1577 XchgAXReg(CX);
1578 CLK(XCHG_AR16);
1579 break;
1580
1581 case 0x92: // i_xchg_axdx
1582 XchgAXReg(DX);
1583 CLK(XCHG_AR16);
1584 break;
1585
1586 case 0x93: // i_xchg_axbx
1587 XchgAXReg(BX);
1588 CLK(XCHG_AR16);
1589 break;
1590
1591 case 0x94: // i_xchg_axsp
1592 XchgAXReg(SP);
1593 CLK(XCHG_AR16);
1594 break;
1595
1596 case 0x95: // i_xchg_axbp
1597 XchgAXReg(BP);
1598 CLK(XCHG_AR16);
1599 break;
1600
1601 case 0x96: // i_xchg_axsi
1602 XchgAXReg(SI);
1603 CLK(XCHG_AR16);
1604 break;
1605
1606 case 0x97: // i_xchg_axdi
1607 XchgAXReg(DI);
1608 CLK(XCHG_AR16);
1609 break;
1610
1611
1612 case 0x98: // i_cbw
1613 m_regs.b[AH] = (m_regs.b[AL] & 0x80) ? 0xff : 0;
1614 CLK(CBW);
1615 break;
1616
1617 case 0x99: // i_cwd
1618 m_regs.w[DX] = (m_regs.b[AH] & 0x80) ? 0xffff : 0;
1619 CLK(CWD);
1620 break;
1621
1622 case 0x9a: // i_call_far
1623 {
1624 uint16_t tmp = fetch_word();
1625 uint16_t tmp2 = fetch_word();
1626 PUSH(m_sregs[CS]);
1627 PUSH(m_ip);
1628 m_ip = tmp;
1629 m_sregs[CS] = tmp2;
1630 CLK(CALL_FAR);
1631 }
1632 break;
1633
1634 case 0x9b: // i_wait
1635 // Wait for assertion of /TEST
1636 if (m_test_state == 0)
1637 {
1638 m_icount = 0;
1639 m_ip--;
1640 }
1641 else
1642 CLK(WAIT);
1643 break;
1644
1645 case 0x9c: // i_pushf
1646 PUSH( CompressFlags() );
1647 CLK(PUSHF);
1648 break;
1649
1650 case 0x9d: // i_popf
1651 i_popf();
1652 break;
1653
1654 case 0x9e: // i_sahf
1655 {
1656 uint32_t tmp = (CompressFlags() & 0xff00) | (m_regs.b[AH] & 0xd5);
1657 ExpandFlags(tmp);
1658 CLK(SAHF);
1659 }
1660 break;
1661
1662 case 0x9f: // i_lahf
1663 m_regs.b[AH] = CompressFlags();
1664 CLK(LAHF);
1665 break;
1666
1667
1668 case 0xa0: // i_mov_aldisp
1669 {
1670 uint32_t addr = fetch_word();
1671 m_regs.b[AL] = GetMemB(DS, addr);
1672 CLK(MOV_AM8);
1673 }
1674 break;
1675
1676 case 0xa1: // i_mov_axdisp
1677 {
1678 uint32_t addr = fetch_word();
1679 m_regs.w[AX] = GetMemW(DS, addr);
1680 CLK(MOV_AM16);
1681 }
1682 break;
1683
1684 case 0xa2: // i_mov_dispal
1685 {
1686 uint32_t addr = fetch_word();
1687 PutMemB(DS, addr, m_regs.b[AL]);
1688 CLK(MOV_MA8);
1689 }
1690 break;
1691
1692 case 0xa3: // i_mov_dispax
1693 {
1694 uint32_t addr = fetch_word();
1695 PutMemW(DS, addr, m_regs.w[AX]);
1696 CLK(MOV_MA16);
1697 }
1698 break;
1699
1700 case 0xa4: // i_movsb
1701 i_movsb();
1702 break;
1703
1704 case 0xa5: // i_movsw
1705 i_movsw();
1706 break;
1707
1708 case 0xa6: // i_cmpsb
1709 i_cmpsb();
1710 break;
1711
1712 case 0xa7: // i_cmpsw
1713 i_cmpsw();
1714 break;
1715
1716
1717 case 0xa8: // i_test_ald8
1718 DEF_ald8();
1719 ANDB();
1720 CLK(ALU_RI8);
1721 break;
1722
1723 case 0xa9: // i_test_axd16
1724 DEF_axd16();
1725 ANDX();
1726 CLK(ALU_RI16);
1727 break;
1728
1729 case 0xaa: // i_stosb
1730 i_stosb();
1731 break;
1732
1733 case 0xab: // i_stosw
1734 i_stosw();
1735 break;
1736
1737 case 0xac: // i_lodsb
1738 i_lodsb();
1739 break;
1740
1741 case 0xad: // i_lodsw
1742 i_lodsw();
1743 break;
1744
1745 case 0xae: // i_scasb
1746 i_scasb();
1747 break;
1748
1749 case 0xaf: // i_scasw
1750 i_scasw();
1751 break;
1752
1753
1754 case 0xb0: // i_mov_ald8
1755 m_regs.b[AL] = fetch();
1756 CLK(MOV_RI8);
1757 break;
1758
1759 case 0xb1: // i_mov_cld8
1760 m_regs.b[CL] = fetch();
1761 CLK(MOV_RI8);
1762 break;
1763
1764 case 0xb2: // i_mov_dld8
1765 m_regs.b[DL] = fetch();
1766 CLK(MOV_RI8);
1767 break;
1768
1769 case 0xb3: // i_mov_bld8
1770 m_regs.b[BL] = fetch();
1771 CLK(MOV_RI8);
1772 break;
1773
1774 case 0xb4: // i_mov_ahd8
1775 m_regs.b[AH] = fetch();
1776 CLK(MOV_RI8);
1777 break;
1778
1779 case 0xb5: // i_mov_chd8
1780 m_regs.b[CH] = fetch();
1781 CLK(MOV_RI8);
1782 break;
1783
1784 case 0xb6: // i_mov_dhd8
1785 m_regs.b[DH] = fetch();
1786 CLK(MOV_RI8);
1787 break;
1788
1789 case 0xb7: // i_mov_bhd8
1790 m_regs.b[BH] = fetch();
1791 CLK(MOV_RI8);
1792 break;
1793
1794
1795 case 0xb8: // i_mov_axd16
1796 m_regs.b[AL] = fetch();
1797 m_regs.b[AH] = fetch();
1798 CLK(MOV_RI16);
1799 break;
1800
1801 case 0xb9: // i_mov_cxd16
1802 m_regs.b[CL] = fetch();
1803 m_regs.b[CH] = fetch();
1804 CLK(MOV_RI16);
1805 break;
1806
1807 case 0xba: // i_mov_dxd16
1808 m_regs.b[DL] = fetch();
1809 m_regs.b[DH] = fetch();
1810 CLK(MOV_RI16);
1811 break;
1812
1813 case 0xbb: // i_mov_bxd16
1814 m_regs.b[BL] = fetch();
1815 m_regs.b[BH] = fetch();
1816 CLK(MOV_RI16);
1817 break;
1818
1819 case 0xbc: // i_mov_spd16
1820 m_regs.b[SPL] = fetch();
1821 m_regs.b[SPH] = fetch();
1822 CLK(MOV_RI16);
1823 break;
1824
1825 case 0xbd: // i_mov_bpd16
1826 m_regs.b[BPL] = fetch();
1827 m_regs.b[BPH] = fetch();
1828 CLK(MOV_RI16);
1829 break;
1830
1831 case 0xbe: // i_mov_sid16
1832 m_regs.b[SIL] = fetch();
1833 m_regs.b[SIH] = fetch();
1834 CLK(MOV_RI16);
1835 break;
1836
1837 case 0xbf: // i_mov_did16
1838 m_regs.b[DIL] = fetch();
1839 m_regs.b[DIH] = fetch();
1840 CLK(MOV_RI16);
1841 break;
1842
1843 case 0xc0: // 0xc0 is 0xc2 - see (*)
1844 case 0xc2: // i_ret_d16
1845 {
1846 uint32_t count = fetch_word();
1847 m_ip = POP();
1848 m_regs.w[SP] += count;
1849 CLK(RET_NEAR_IMM);
1850 }
1851 break;
1852
1853 case 0xc1: // 0xc1 is 0xc3 - see (*)
1854 case 0xc3: // i_ret
1855 m_ip = POP();
1856 CLK(RET_NEAR);
1857 break;
1858
1859 case 0xc4: // i_les_dw
1860 m_modrm = fetch();
1861 RegWord( GetRMWord() );
1862 m_sregs[ES] = GetnextRMWord();
1863 CLK(LOAD_PTR);
1864 break;
1865
1866 case 0xc5: // i_lds_dw
1867 m_modrm = fetch();
1868 RegWord( GetRMWord() );
1869 m_sregs[DS] = GetnextRMWord();
1870 CLK(LOAD_PTR);
1871 break;
1872
1873 case 0xc6: // i_mov_bd8
1874 m_modrm = fetch();
1875 PutImmRMByte();
1876 CLKM(MOV_RI8,MOV_MI8);
1877 break;
1878
1879 case 0xc7: // i_mov_wd16
1880 m_modrm = fetch();
1881 PutImmRMWord();
1882 CLKM(MOV_RI16,MOV_MI16);
1883 break;
1884
1885 case 0xc8: // 0xc8 = 0xca - see (*)
1886 case 0xca: // i_retf_d16
1887 {
1888 uint32_t count = fetch_word();
1889 m_ip = POP();
1890 m_sregs[CS] = POP();
1891 m_regs.w[SP] += count;
1892 CLK(RET_FAR_IMM);
1893 }
1894 break;
1895
1896 case 0xc9: // 0xc9 = 0xcb - see (*)
1897 case 0xcb: // i_retf
1898 m_ip = POP();
1899 m_sregs[CS] = POP();
1900 CLK(RET_FAR);
1901 break;
1902
1903 case 0xcc: // i_int3
1904 interrupt(3, 0);
1905 CLK(INT3);
1906 break;
1907
1908 case 0xcd: // i_int
1909 interrupt(fetch(), 0);
1910 CLK(INT_IMM);
1911 break;
1912
1913 case 0xce: // i_into
1914 if (OF)
1915 {
1916 interrupt(4, 0);
1917 CLK(INTO_T);
1918 }
1919 else
1920 CLK(INTO_NT);
1921 break;
1922
1923 case 0xcf: // i_iret
1924 m_ip = POP();
1925 m_sregs[CS] = POP();
1926 i_popf();
1927 CLK(IRET);
1928 break;
1929
1930 case 0xd0: // i_rotshft_b
1931 m_modrm = fetch();
1932 m_src = GetRMByte();
1933 m_dst = m_src;
1934 CLKM(ROT_REG_1,ROT_M8_1);
1935 switch ( m_modrm & 0x38 )
1936 {
1937 case 0x00: ROL_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1938 case 0x08: ROR_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1939 case 0x10: ROLC_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1940 case 0x18: RORC_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1941 case 0x30:
1942 case 0x20: SHL_BYTE(1); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1943 case 0x28: SHR_BYTE(1); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1944 case 0x38: SHRA_BYTE(1); m_OverVal = 0; break;
1945 }
1946 break;
1947
1948 case 0xd1: // i_rotshft_w
1949 m_modrm = fetch();
1950 m_src = GetRMWord();
1951 m_dst = m_src;
1952 CLKM(ROT_REG_1,ROT_M8_1);
1953 switch ( m_modrm & 0x38 )
1954 {
1955 case 0x00: ROL_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1956 case 0x08: ROR_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1957 case 0x10: ROLC_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1958 case 0x18: RORC_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1959 case 0x30:
1960 case 0x20: SHL_WORD(1); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1961 case 0x28: SHR_WORD(1); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1962 case 0x38: SHRA_WORD(1); m_OverVal = 0; break;
1963 }
1964 break;
1965
1966 case 0xd4: // i_aam
1967 {
1968 uint8_t base = fetch();
1969 if(!base)
1970 {
1971 interrupt(0);
1972 break;
1973 }
1974 m_regs.b[AH] = m_regs.b[AL] / base;
1975 m_regs.b[AL] %= base;
1976 set_SZPF_Word(m_regs.w[AX]);
1977 CLK(AAM);
1978 break;
1979 }
1980
1981 case 0xd5: // i_aad
1982 {
1983 uint8_t base = fetch();
1984 m_regs.b[AL] = m_regs.b[AH] * base + m_regs.b[AL];
1985 m_regs.b[AH] = 0;
1986 set_SZPF_Byte(m_regs.b[AL]);
1987 CLK(AAD);
1988 break;
1989 }
1990
1991 case 0xd6: // i_salc
1992 m_regs.b[AL] = (CF ? 0xff : 0);
1993 CLK(ALU_RR8); // is sbb al,al
1994 break;
1995
1996 case 0xd7: // i_trans
1997 m_regs.b[AL] = GetMemB( DS, m_regs.w[BX] + m_regs.b[AL] );
1998 CLK(XLAT);
1999 break;
2000
2001 case 0xe0: // i_loopne
2002 {
2003 int8_t disp = (int8_t)fetch();
2004
2005 m_regs.w[CX]--;
2006 if (!ZF && m_regs.w[CX])
2007 {
2008 m_ip = m_ip + disp;
2009 CLK(LOOP_T);
2010 }
2011 else
2012 CLK(LOOP_NT);
2013 }
2014 break;
2015
2016 case 0xe1: // i_loope
2017 {
2018 int8_t disp = (int8_t)fetch();
2019
2020 m_regs.w[CX]--;
2021 if (ZF && m_regs.w[CX])
2022 {
2023 m_ip = m_ip + disp;
2024 CLK(LOOPE_T);
2025 }
2026 else
2027 CLK(LOOPE_NT);
2028 }
2029 break;
2030
2031 case 0xe2: // i_loop
2032 {
2033 int8_t disp = (int8_t)fetch();
2034
2035 m_regs.w[CX]--;
2036 if (m_regs.w[CX])
2037 {
2038 m_ip = m_ip + disp;
2039 CLK(LOOP_T);
2040 }
2041 else
2042 CLK(LOOP_NT);
2043 }
2044 break;
2045
2046 case 0xe3: // i_jcxz
2047 {
2048 int8_t disp = (int8_t)fetch();
2049
2050 if (m_regs.w[CX] == 0)
2051 {
2052 m_ip = m_ip + disp;
2053 CLK(JCXZ_T);
2054 }
2055 else
2056 CLK(JCXZ_NT);
2057 }
2058 break;
2059
2060 case 0xe4: // i_inal
2061 if (m_lock) m_lock_handler(1);
2062 m_regs.b[AL] = read_port_byte( fetch() );
2063 if (m_lock) { m_lock_handler(0); m_lock = false; }
2064 CLK(IN_IMM8);
2065 break;
2066
2067 case 0xe5: // i_inax
2068 {
2069 uint8_t port = fetch();
2070
2071 m_regs.w[AX] = read_port_word(port);
2072 CLK(IN_IMM16);
2073 }
2074 break;
2075
2076 case 0xe6: // i_outal
2077 write_port_byte( fetch(), m_regs.b[AL]);
2078 CLK(OUT_IMM8);
2079 break;
2080
2081 case 0xe7: // i_outax
2082 {
2083 uint8_t port = fetch();
2084
2085 write_port_word(port, m_regs.w[AX]);
2086 CLK(OUT_IMM16);
2087 }
2088 break;
2089
2090
2091 case 0xe8: // i_call_d16
2092 {
2093 int16_t tmp = (int16_t)fetch_word();
2094
2095 PUSH(m_ip);
2096 m_ip = m_ip + tmp;
2097 CLK(CALL_NEAR);
2098 }
2099 break;
2100
2101 case 0xe9: // i_jmp_d16
2102 {
2103 int16_t offset = (int16_t)fetch_word();
2104 m_ip += offset;
2105 CLK(JMP_NEAR);
2106 }
2107 break;
2108
2109 case 0xea: // i_jmp_far
2110 {
2111 uint16_t tmp = fetch_word();
2112 uint16_t tmp1 = fetch_word();
2113
2114 m_sregs[CS] = tmp1;
2115 m_ip = tmp;
2116 CLK(JMP_FAR);
2117 }
2118 break;
2119
2120 case 0xeb: // i_jmp_d8
2121 {
2122 int tmp = (int)((int8_t)fetch());
2123
2124 CLK(JMP_SHORT);
2125 if (tmp==-2 && m_no_interrupt==0 && (m_pending_irq==0) && m_icount>0)
2126 {
2127 m_icount%=12; /* cycle skip */
2128 }
2129 m_ip = (uint16_t)(m_ip+tmp);
2130 }
2131 break;
2132
2133 case 0xec: // i_inaldx
2134 m_regs.b[AL] = read_port_byte(m_regs.w[DX]);
2135 CLK(IN_DX8);
2136 break;
2137
2138 case 0xed: // i_inaxdx
2139 {
2140 uint32_t port = m_regs.w[DX];
2141
2142 m_regs.w[AX] = read_port_word(port);
2143 CLK(IN_DX16);
2144 }
2145 break;
2146
2147 case 0xee: // i_outdxal
2148 write_port_byte(m_regs.w[DX], m_regs.b[AL]);
2149 CLK(OUT_DX8);
2150 break;
2151
2152 case 0xef: // i_outdxax
2153 {
2154 uint32_t port = m_regs.w[DX];
2155
2156 write_port_word(port, m_regs.w[AX]);
2157 CLK(OUT_DX16);
2158 }
2159 break;
2160
2161
2162 case 0xf0: // i_lock
2163 case 0xf1: // 0xf1 is 0xf0; verified on real CPU
2164 //logerror("%06x: Warning - BUSLOCK\n", m_pc); // Why warn for using lock instruction?
2165 m_lock = true;
2166 m_no_interrupt = 1;
2167 CLK(NOP);
2168 break;
2169
2170 case 0xf2: // i_repne
2171 {
2172 bool invalid = false;
2173 uint8_t next = repx_op();
2174 uint16_t c = m_regs.w[CX];
2175
2176 switch (next)
2177 {
2178 case 0xa4: CLK(OVERRIDE); if (c) do { i_movsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2179 case 0xa5: CLK(OVERRIDE); if (c) do { i_movsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2180 case 0xa6: CLK(OVERRIDE); if (c) do { i_cmpsb(); c--; } while (c>0 && !ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2181 case 0xa7: CLK(OVERRIDE); if (c) do { i_cmpsw(); c--; } while (c>0 && !ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2182 case 0xaa: CLK(OVERRIDE); if (c) do { i_stosb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2183 case 0xab: CLK(OVERRIDE); if (c) do { i_stosw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2184 case 0xac: CLK(OVERRIDE); if (c) do { i_lodsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2185 case 0xad: CLK(OVERRIDE); if (c) do { i_lodsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2186 case 0xae: CLK(OVERRIDE); if (c) do { i_scasb(); c--; } while (c>0 && !ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2187 case 0xaf: CLK(OVERRIDE); if (c) do { i_scasw(); c--; } while (c>0 && !ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2188 default:
2189 logerror("%06x: REPNE invalid\n", m_pc);
2190 // Decrement IP so the normal instruction will be executed next
2191 m_ip--;
2192 invalid = true;
2193 break;
2194 }
2195 if(c && !invalid)
2196 {
2197 if(!(ZF && ((next & 6) == 6)))
2198 m_ip = m_prev_ip;
2199 }
2200 }
2201 break;
2202
2203 case 0xf3: // i_repe
2204 {
2205 bool invalid = false;
2206 uint8_t next = repx_op();
2207 uint16_t c = m_regs.w[CX];
2208
2209 switch (next)
2210 {
2211 case 0xa4: CLK(OVERRIDE); if (c) do { i_movsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2212 case 0xa5: CLK(OVERRIDE); if (c) do { i_movsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2213 case 0xa6: CLK(OVERRIDE); if (c) do { i_cmpsb(); c--; } while (c>0 && ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2214 case 0xa7: CLK(OVERRIDE); if (c) do { i_cmpsw(); c--; } while (c>0 && ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2215 case 0xaa: CLK(OVERRIDE); if (c) do { i_stosb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2216 case 0xab: CLK(OVERRIDE); if (c) do { i_stosw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2217 case 0xac: CLK(OVERRIDE); if (c) do { i_lodsb(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2218 case 0xad: CLK(OVERRIDE); if (c) do { i_lodsw(); c--; } while (c>0 && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2219 case 0xae: CLK(OVERRIDE); if (c) do { i_scasb(); c--; } while (c>0 && ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2220 case 0xaf: CLK(OVERRIDE); if (c) do { i_scasw(); c--; } while (c>0 && ZF && m_icount>0); m_regs.w[CX]=c; m_seg_prefix = false; m_seg_prefix_next = false; break;
2221 default:
2222 logerror("%06x: REPE invalid\n", m_pc);
2223 // Decrement IP so the normal instruction will be executed next
2224 m_ip--;
2225 invalid = true;
2226 break;
2227 }
2228 if(c && !invalid)
2229 {
2230 if(!(!ZF && ((next & 6) == 6)))
2231 m_ip = m_prev_ip;
2232 }
2233 }
2234 break;
2235
2236 case 0xf4: // i_hlt
2237 //logerror("%s: %06x: HALT\n", tag(), m_pc);
2238 m_icount = 0;
2239 m_halt = true;
2240 break;
2241
2242 case 0xf5: // i_cmc
2243 m_CarryVal = !m_CarryVal;
2244 CLK(FLAG_OPS);
2245 break;
2246
2247 case 0xf6: // i_f6pre
2248 {
2249 uint32_t tmp;
2250 uint32_t uresult,uresult2;
2251 int32_t result,result2;
2252
2253 m_modrm = fetch();
2254 tmp = GetRMByte();
2255 switch ( m_modrm & 0x38 )
2256 {
2257 case 0x00: /* TEST */
2258 case 0x08: /* TEST (alias) */
2259 tmp &= fetch();
2260 m_CarryVal = m_OverVal = 0;
2261 set_SZPF_Byte(tmp);
2262 CLKM(ALU_RI8,ALU_MI8_RO);
2263 break;
2264 case 0x10: /* NOT */
2265 PutbackRMByte(~tmp);
2266 CLKM(NEGNOT_R8,NEGNOT_M8);
2267 break;
2268 case 0x18: /* NEG */
2269 m_dst = 0;
2270 m_src = tmp;
2271 set_CFB(SUBB());
2272 PutbackRMByte(m_dst);
2273 CLKM(NEGNOT_R8,NEGNOT_M8);
2274 break;
2275 case 0x20: /* MUL */
2276 uresult = m_regs.b[AL] * tmp;
2277 m_regs.w[AX] = (uint16_t)uresult;
2278 m_CarryVal = m_OverVal = (m_regs.b[AH]!=0) ? 1 : 0;
2279 set_ZF(m_regs.w[AX]);
2280 CLKM(MUL_R8,MUL_M8);
2281 break;
2282 case 0x28: /* IMUL */
2283 result = (int16_t)((int8_t)m_regs.b[AL])*(int16_t)((int8_t)tmp);
2284 m_regs.w[AX] = (uint16_t)result;
2285 m_CarryVal = m_OverVal = (m_regs.b[AH]!=0) ? 1 : 0;
2286 set_ZF(m_regs.w[AX]);
2287 CLKM(IMUL_R8,IMUL_M8);
2288 break;
2289 case 0x30: /* DIV */
2290 if (tmp)
2291 {
2292 uresult = m_regs.w[AX];
2293 uresult2 = uresult % tmp;
2294 if ((uresult /= tmp) > 0xff)
2295 {
2296 interrupt(0);
2297 }
2298 else
2299 {
2300 m_regs.b[AL] = uresult;
2301 m_regs.b[AH] = uresult2;
2302 }
2303 }
2304 else
2305 {
2306 interrupt(0);
2307 }
2308 CLKM(DIV_R8,DIV_M8);
2309 break;
2310 case 0x38: /* IDIV */
2311 if (tmp)
2312 {
2313 result = (int16_t)m_regs.w[AX];
2314 result2 = result % (int16_t)((int8_t)tmp);
2315 if ((result /= (int16_t)((int8_t)tmp)) > 0xff)
2316 {
2317 interrupt(0);
2318 }
2319 else
2320 {
2321 m_regs.b[AL] = result;
2322 m_regs.b[AH] = result2;
2323 }
2324 }
2325 else
2326 {
2327 interrupt(0);
2328 }
2329 CLKM(IDIV_R8,IDIV_M8);
2330 break;
2331 }
2332 }
2333 break;
2334
2335
2336 case 0xf7: // i_f7pre
2337 {
2338 uint32_t tmp,tmp2;
2339 uint32_t uresult,uresult2;
2340 int32_t result,result2;
2341
2342 m_modrm = fetch();
2343 tmp = GetRMWord();
2344 switch ( m_modrm & 0x38 )
2345 {
2346 case 0x00: /* TEST */
2347 case 0x08: /* TEST (alias) */
2348 tmp2 = fetch_word();
2349 tmp &= tmp2;
2350 m_CarryVal = m_OverVal = 0;
2351 set_SZPF_Word(tmp);
2352 CLKM(ALU_RI16,ALU_MI16_RO);
2353 break;
2354 case 0x10: /* NOT */
2355 PutbackRMWord(~tmp);
2356 CLKM(NEGNOT_R16,NEGNOT_M16);
2357 break;
2358 case 0x18: /* NEG */
2359 m_dst = 0;
2360 m_src = tmp;
2361 set_CFW(SUBX());
2362 PutbackRMWord(m_dst);
2363 CLKM(NEGNOT_R16,NEGNOT_M16);
2364 break;
2365 case 0x20: /* MUL */
2366 uresult = m_regs.w[AX]*tmp;
2367 m_regs.w[AX] = uresult & 0xffff;
2368 m_regs.w[DX] = ((uint32_t)uresult)>>16;
2369 m_CarryVal = m_OverVal = (m_regs.w[DX] != 0) ? 1 : 0;
2370 set_ZF(m_regs.w[AX] | m_regs.w[DX]);
2371 CLKM(MUL_R16,MUL_M16);
2372 break;
2373 case 0x28: /* IMUL */
2374 result = (int32_t)((int16_t)m_regs.w[AX]) * (int32_t)((int16_t)tmp);
2375 m_regs.w[AX] = result & 0xffff;
2376 m_regs.w[DX] = result >> 16;
2377 m_CarryVal = m_OverVal = (m_regs.w[DX] != 0) ? 1 : 0;
2378 set_ZF(m_regs.w[AX] | m_regs.w[DX]);
2379 CLKM(IMUL_R16,IMUL_M16);
2380 break;
2381 case 0x30: /* DIV */
2382 if (tmp)
2383 {
2384 uresult = (((uint32_t)m_regs.w[DX]) << 16) | m_regs.w[AX];
2385 uresult2 = uresult % tmp;
2386 if ((uresult /= tmp) > 0xffff)
2387 {
2388 interrupt(0);
2389 }
2390 else
2391 {
2392 m_regs.w[AX] = uresult;
2393 m_regs.w[DX] = uresult2;
2394 }
2395 }
2396 else
2397 {
2398 interrupt(0);
2399 }
2400 CLKM(DIV_R16,DIV_M16);
2401 break;
2402 case 0x38: /* IDIV */
2403 if (tmp)
2404 {
2405 result = ((uint32_t)m_regs.w[DX] << 16) + m_regs.w[AX];
2406 result2 = result % (int32_t)((int16_t)tmp);
2407 if ((result /= (int32_t)((int16_t)tmp)) > 0xffff)
2408 {
2409 interrupt(0);
2410 }
2411 else
2412 {
2413 m_regs.w[AX] = result;
2414 m_regs.w[DX] = result2;
2415 }
2416 }
2417 else
2418 {
2419 interrupt(0);
2420 }
2421 CLKM(IDIV_R16,IDIV_M16);
2422 break;
2423 }
2424 }
2425 break;
2426
2427
2428 case 0xf8: // i_clc
2429 m_CarryVal = 0;
2430 CLK(FLAG_OPS);
2431 break;
2432
2433 case 0xf9: // i_stc
2434 m_CarryVal = 1;
2435 CLK(FLAG_OPS);
2436 break;
2437
2438 case 0xfa: // i_cli
2439 m_IF = 0;
2440 CLK(FLAG_OPS);
2441 break;
2442
2443 case 0xfb: // i_sti
2444 m_IF = 1;
2445 m_no_interrupt = 1;
2446 CLK(FLAG_OPS);
2447 break;
2448
2449 case 0xfc: // i_cld
2450 m_DF = 0;
2451 CLK(FLAG_OPS);
2452 break;
2453
2454 case 0xfd: // i_std
2455 m_DF = 1;
2456 CLK(FLAG_OPS);
2457 break;
2458
2459 case 0xfe: // i_fepre
2460 {
2461 uint32_t tmp, tmp1;
2462 m_modrm = fetch();
2463 tmp = GetRMByte();
2464 switch ( m_modrm & 0x38 )
2465 {
2466 case 0x00: /* INC */
2467 tmp1 = tmp+1;
2468 m_OverVal = (tmp==0x7f);
2469 set_AF(tmp1,tmp,1);
2470 set_SZPF_Byte(tmp1);
2471 PutbackRMByte(tmp1);
2472 CLKM(INCDEC_R8,INCDEC_M8);
2473 break;
2474 case 0x08: /* DEC */
2475 tmp1 = tmp-1;
2476 m_OverVal = (tmp==0x80);
2477 set_AF(tmp1,tmp,1);
2478 set_SZPF_Byte(tmp1);
2479 PutbackRMByte(tmp1);
2480 CLKM(INCDEC_R8,INCDEC_M8);
2481 break;
2482 default:
2483 logerror("%06x: FE Pre with unimplemented mod\n", m_pc);
2484 break;
2485 }
2486 }
2487 break;
2488
2489 case 0xff: // i_ffpre
2490 {
2491 uint32_t tmp, tmp1;
2492 m_modrm = fetch();
2493 tmp = GetRMWord();
2494 switch ( m_modrm & 0x38 )
2495 {
2496 case 0x00: /* INC */
2497 tmp1 = tmp+1;
2498 m_OverVal = (tmp==0x7fff);
2499 set_AF(tmp1,tmp,1);
2500 set_SZPF_Word(tmp1);
2501 PutbackRMWord(tmp1);
2502 CLKM(INCDEC_R16,INCDEC_M16);
2503 break;
2504 case 0x08: /* DEC */
2505 tmp1 = tmp-1;
2506 m_OverVal = (tmp==0x8000);
2507 set_AF(tmp1,tmp,1);
2508 set_SZPF_Word(tmp1);
2509 PutbackRMWord(tmp1);
2510 CLKM(INCDEC_R16,INCDEC_M16);
2511 break;
2512 case 0x10: /* CALL */
2513 PUSH(m_ip);
2514 m_ip = tmp;
2515 CLKM(CALL_R16,CALL_M16);
2516 break;
2517 case 0x18: /* CALL FAR */
2518 tmp1 = m_sregs[CS];
2519 m_sregs[CS] = GetnextRMWord();
2520 PUSH(tmp1);
2521 PUSH(m_ip);
2522 m_ip = tmp;
2523 CLK(CALL_M32);
2524 break;
2525 case 0x20: /* JMP */
2526 m_ip = tmp;
2527 CLKM(JMP_R16,JMP_M16);
2528 break;
2529 case 0x28: /* JMP FAR */
2530 m_ip = tmp;
2531 m_sregs[CS] = GetnextRMWord();
2532 CLK(JMP_M32);
2533 break;
2534 case 0x30:
2535 PUSH(tmp);
2536 CLKM(PUSH_R16,PUSH_M16);
2537 break;
2538 default:
2539 m_icount -= 10;
2540 logerror("%06x: FF Pre with unimplemented mod\n", m_pc);
2541 break;
2542 }
2543 }
2544 break;
2545 default:
2546 return false;
2547 }
2548 return true;
2549 }
2550