1 // license:BSD-3-Clause
2 // copyright-holders:Carl
3 /****************************************************************************
5 NEC V20/V30/V33 emulator modified back to a 8086/80186 emulator
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(!).
12 ****************************************************************************/
17 #include "i86inline.h"
19 #define I8086_NMI_INT_VECTOR 2
21 const uint8_t i8086_cpu_device::m_i8086_timing[] =
23 51,32, /* exception, IRET */
24 2, 0, 4, 2, /* INTs */
25 2, /* segment overrides */
26 2, 4, 4, /* flag operations */
27 4, 4,83,60, /* arithmetic adjusts */
28 4, 4, /* decimal adjusts */
29 2, 5, /* sign extension */
30 2,24, 2, 2, 3,11, /* misc */
32 15,15,15, /* direct JMPs */
33 11,18,24, /* indirect JMPs */
34 19,28, /* direct CALLs */
35 16,21,37, /* indirect CALLs */
36 20,32,24,31, /* returns */
37 4,16, 6,18, /* conditional JMPs */
38 5,17, 6,18, /* loops */
40 10,14, 8,12, /* port reads */
41 10,14, 8,12, /* port writes */
43 2, 8, 9, /* move, 8-bit */
44 4,10, /* move, 8-bit immediate */
45 2, 8, 9, /* move, 16-bit */
46 4,10, /* move, 16-bit immediate */
47 10,10,10,10, /* move, AL/AX memory */
48 2, 8, 2, 9, /* move, segment registers */
49 4,17, /* exchange, 8-bit */
50 4,17, 3, /* exchange, 16-bit */
52 15,24,14,14, /* pushes */
53 12,25,12,12, /* pops */
55 3, 9,16, /* ALU ops, 8-bit */
56 4,17,10, /* ALU ops, 8-bit immediate */
57 3, 9,16, /* ALU ops, 16-bit */
58 4,17,10, /* ALU ops, 16-bit immediate */
59 4,17,10, /* ALU ops, 16-bit w/8-bit immediate */
60 70,118,76,128, /* MUL */
61 80,128,86,138, /* IMUL */
62 80,144,86,154, /* DIV */
63 101,165,107,175,/* IDIV */
64 3, 2,15,15, /* INC/DEC */
65 3, 3,16,16, /* NEG/NOT */
67 2, 8, 4, /* reg shift/rotate */
68 15,20, 4, /* m8 shift/rotate */
69 15,20, 4, /* m16 shift/rotate */
71 22, 9,21, /* CMPS 8-bit */
72 22, 9,21, /* CMPS 16-bit */
73 15, 9,14, /* SCAS 8-bit */
74 15, 9,14, /* SCAS 16-bit */
75 12, 9,11, /* LODS 8-bit */
76 12, 9,11, /* LODS 16-bit */
77 11, 9,10, /* STOS 8-bit */
78 11, 9,10, /* STOS 16-bit */
79 18, 9,17, /* MOVS 8-bit */
80 18, 9,17, /* MOVS 16-bit */
83 /***************************************************************************/
85 /***************************************************************************/
88 /***************************************************************************/
90 const device_type I8086 = device_creator<i8086_cpu_device>;
91 const device_type I8088 = device_creator<i8088_cpu_device>;
93 i8088_cpu_device::i8088_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
94 : i8086_cpu_device(mconfig, I8088, "I8088", tag, owner, clock, "i8088", __FILE__, 8)
96 memcpy(m_timing, m_i8086_timing, sizeof(m_i8086_timing));
100 i8086_cpu_device::i8086_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
101 : i8086_common_cpu_device(mconfig, I8086, "I8086", tag, owner, clock, "i8086", __FILE__)
102 , m_program_config("program", ENDIANNESS_LITTLE, 16, 20, 0)
103 , m_opcodes_config("opcodes", ENDIANNESS_LITTLE, 16, 20, 0)
104 , m_io_config("io", ENDIANNESS_LITTLE, 16, 16, 0)
106 memcpy(m_timing, m_i8086_timing, sizeof(m_i8086_timing));
107 m_fetch_xor = BYTE_XOR_LE(0);
110 i8086_cpu_device::i8086_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source, int data_bus_size)
111 : i8086_common_cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
112 , m_program_config("program", ENDIANNESS_LITTLE, data_bus_size, 20, 0)
113 , m_opcodes_config("opcodes", ENDIANNESS_LITTLE, data_bus_size, 20, 0)
114 , m_io_config("io", ENDIANNESS_LITTLE, data_bus_size, 16, 0)
118 const address_space_config *i8086_cpu_device::memory_space_config(address_spacenum spacenum) const
122 case AS_PROGRAM: return &m_program_config;
123 case AS_IO: return &m_io_config;
124 case AS_DECRYPTED_OPCODES: return has_configured_map(AS_DECRYPTED_OPCODES) ? &m_opcodes_config : nullptr;
125 default: return nullptr;
129 uint8_t i8086_cpu_device::fetch_op()
132 data = m_direct_opcodes->read_byte(pc(), m_fetch_xor);
137 uint8_t i8086_cpu_device::fetch()
140 data = m_direct_opcodes->read_byte(pc(), m_fetch_xor);
145 void i8086_cpu_device::execute_run()
149 if ( m_seg_prefix_next )
152 m_seg_prefix_next = false;
157 m_seg_prefix = false;
160 if ( m_pending_irq && (m_no_interrupt == 0) )
162 if ( m_pending_irq & NMI_IRQ )
164 interrupt(I8086_NMI_INT_VECTOR);
165 m_pending_irq &= ~NMI_IRQ;
169 /* the actual vector is retrieved after pushing flags */
170 /* and clearing the IF */
175 /* Trap should allow one instruction to be executed.
176 CPUID.ASM (by Bob Smith, 1985) suggests that in situations where m_no_interrupt is 1,
177 (directly after POP SS / MOV_SREG), single step IRQs don't fire.
181 if ( (m_fire_trap >= 2) && (m_no_interrupt == 0) )
183 m_fire_trap = 0; // reset trap flag upon entry
192 /* No interrupt allowed between last instruction and this one */
193 if ( m_no_interrupt )
202 debugger_instruction_hook( this, pc() );
205 uint8_t op = fetch_op();
214 case 0xd2: // i_rotshft_bcl
222 CLKM(ROT_REG_BASE,ROT_M8_BASE);
223 m_icount -= m_timing[ROT_REG_BIT] * c;
226 switch ( m_modrm & 0x38 )
228 case 0x00: do { ROL_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
229 case 0x08: do { ROR_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
230 case 0x10: do { ROLC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
231 case 0x18: do { RORC_BYTE(); c--; } while (c>0); PutbackRMByte(m_dst); break;
233 case 0x20: SHL_BYTE(c); break;
234 case 0x28: SHR_BYTE(c); break;
235 case 0x38: SHRA_BYTE(c); break;
241 case 0xd3: // i_rotshft_wcl
249 CLKM(ROT_REG_BASE,ROT_M16_BASE);
250 m_icount -= m_timing[ROT_REG_BIT] * c;
253 switch ( m_modrm & 0x38 )
255 case 0x00: do { ROL_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
256 case 0x08: do { ROR_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
257 case 0x10: do { ROLC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
258 case 0x18: do { RORC_WORD(); c--; } while (c>0); PutbackRMWord(m_dst); break;
260 case 0x20: SHL_WORD(c); break;
261 case 0x28: SHR_WORD(c); break;
262 case 0x38: SHRA_WORD(c); break;
272 logerror("%06x: Invalid Opcode %02x\n", pc(), op);
280 void i8086_cpu_device::device_start()
282 i8086_common_cpu_device::device_start();
283 state_add( I8086_ES, "ES", m_sregs[ES] ).formatstr("%04X");
284 state_add( I8086_CS, "CS", m_sregs[CS] ).callimport().formatstr("%04X");
285 state_add( I8086_SS, "SS", m_sregs[SS] ).formatstr("%04X");
286 state_add( I8086_DS, "DS", m_sregs[DS] ).formatstr("%04X");
287 state_add( I8086_VECTOR, "V", m_int_vector).formatstr("%02X");
289 state_add( I8086_PC, "PC", m_pc ).callimport().formatstr("%05X");
290 state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%05X").noshow();
291 state_add( I8086_HALT, "HALT", m_halt ).mask(1);
294 i8086_common_cpu_device::i8086_common_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, const char *source)
295 : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
305 , m_lock_handler(*this)
307 static const BREGS reg_name[8]={ AL, CL, DL, BL, AH, CH, DH, BH };
309 /* Set up parity lookup table. */
310 for (uint16_t i = 0;i < 256; i++)
313 for (uint16_t j = i; j > 0; j >>= 1)
317 m_parity_table[i] = !(c & 1);
320 for (uint16_t i = 0; i < 256; i++)
322 m_Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3];
323 m_Mod_RM.reg.w[i] = (WREGS) ( (i & 0x38) >> 3) ;
326 for (uint16_t i = 0xc0; i < 0x100; i++)
328 m_Mod_RM.RM.w[i] = (WREGS)( i & 7 );
329 m_Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7];
332 memset(&m_regs, 0x00, sizeof(m_regs));
333 memset(m_sregs, 0x00, sizeof(m_sregs));
337 //-------------------------------------------------
338 // state_import - import state into the device,
339 // after it has been set
340 //-------------------------------------------------
342 void i8086_common_cpu_device::state_import(const device_state_entry &entry)
344 switch (entry.index())
348 m_pc = (m_sregs[CS] << 4) + m_ip;
352 case STATE_GENPCBASE:
353 if (m_pc - (m_sregs[CS] << 4) > 0xffff)
354 m_sregs[CS] = m_pc >> 4;
355 m_ip = m_pc - (m_sregs[CS] << 4);
361 //-------------------------------------------------
362 // state_string_export - export state as a string
364 //-------------------------------------------------
366 void i8086_common_cpu_device::state_string_export(const device_state_entry &entry, std::string &str) const
368 switch (entry.index())
372 uint16_t flags = CompressFlags();
373 str = string_format("%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
374 flags & 0x8000 ? '1':'.',
375 flags & 0x4000 ? '1':'.',
376 flags & 0x2000 ? '1':'.',
377 flags & 0x1000 ? '1':'.',
378 flags & 0x0800 ? 'O':'.',
379 flags & 0x0400 ? 'D':'.',
380 flags & 0x0200 ? 'I':'.',
381 flags & 0x0100 ? 'T':'.',
382 flags & 0x0080 ? 'S':'.',
383 flags & 0x0040 ? 'Z':'.',
384 flags & 0x0020 ? '0':'.',
385 flags & 0x0010 ? 'A':'.',
386 flags & 0x0008 ? '0':'.',
387 flags & 0x0004 ? 'P':'.',
388 flags & 0x0002 ? '1':'.',
389 flags & 0x0001 ? 'C':'.');
395 void i8086_common_cpu_device::device_start()
397 m_program = &space(AS_PROGRAM);
398 m_opcodes = has_space(AS_DECRYPTED_OPCODES) ? &space(AS_DECRYPTED_OPCODES) : m_program;
399 m_direct = &m_program->direct();
400 m_direct_opcodes = &m_opcodes->direct();
401 m_io = &space(AS_IO);
403 save_item(NAME(m_regs.w));
404 save_item(NAME(m_sregs));
405 save_item(NAME(m_ip));
406 save_item(NAME(m_prev_ip));
407 save_item(NAME(m_TF));
408 save_item(NAME(m_IF));
409 save_item(NAME(m_DF));
410 save_item(NAME(m_MF));
411 save_item(NAME(m_NT));
412 save_item(NAME(m_IOPL));
413 save_item(NAME(m_SignVal));
414 save_item(NAME(m_int_vector));
415 save_item(NAME(m_pending_irq));
416 save_item(NAME(m_nmi_state));
417 save_item(NAME(m_irq_state));
418 save_item(NAME(m_AuxVal));
419 save_item(NAME(m_OverVal));
420 save_item(NAME(m_ZeroVal));
421 save_item(NAME(m_CarryVal));
422 save_item(NAME(m_ParityVal));
423 save_item(NAME(m_seg_prefix));
424 save_item(NAME(m_seg_prefix_next));
425 save_item(NAME(m_prefix_seg));
426 save_item(NAME(m_halt));
428 // Register state for debugger
429 state_add( I8086_IP, "IP", m_ip ).callimport().formatstr("%04X");
430 state_add( I8086_AX, "AX", m_regs.w[AX] ).formatstr("%04X");
431 state_add( I8086_CX, "CX", m_regs.w[CS] ).formatstr("%04X");
432 state_add( I8086_DX, "DX", m_regs.w[DX] ).formatstr("%04X");
433 state_add( I8086_BX, "BX", m_regs.w[BX] ).formatstr("%04X");
434 state_add( I8086_SP, "SP", m_regs.w[SP] ).formatstr("%04X");
435 state_add( I8086_BP, "BP", m_regs.w[BP] ).formatstr("%04X");
436 state_add( I8086_SI, "SI", m_regs.w[SI] ).formatstr("%04X");
437 state_add( I8086_DI, "DI", m_regs.w[DI] ).formatstr("%04X");
439 state_add(STATE_GENFLAGS, "GENFLAGS", m_TF).formatstr("%16s").noshow();
441 m_icountptr = &m_icount;
443 m_lock_handler.resolve_safe();
447 void i8086_common_cpu_device::device_reset()
460 m_sregs[CS] = 0xffff;
472 m_IOPL = 3; // 8086 IOPL always 3
473 m_NT = 1; // 8086 NT always 1
474 m_MF = 1; // 8086 MF always 1, 80286 always 0
482 m_seg_prefix = false;
483 m_seg_prefix_next = false;
496 void i8086_common_cpu_device::interrupt(int int_num, int trap)
498 PUSH( CompressFlags() );
503 int_num = standard_irq_callback(0);
505 m_irq_state = CLEAR_LINE;
506 m_pending_irq &= ~INT_IRQ;
509 uint16_t dest_off = read_word( int_num * 4 + 0 );
510 uint16_t dest_seg = read_word( int_num * 4 + 2 );
515 m_sregs[CS] = dest_seg;
519 void i8086_common_cpu_device::execute_set_input( int inptnum, int state )
521 if (inptnum == INPUT_LINE_NMI)
523 if ( m_nmi_state == state )
528 if (state != CLEAR_LINE)
530 m_pending_irq |= NMI_IRQ;
533 else if (inptnum == INPUT_LINE_TEST)
535 m_test_state = state;
540 if (state == CLEAR_LINE)
542 m_pending_irq &= ~INT_IRQ;
546 m_pending_irq |= INT_IRQ;
551 offs_t i8086_common_cpu_device::disasm_disassemble(std::ostream &stream, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options)
553 extern int i386_dasm_one(std::ostream &stream, offs_t eip, const uint8_t *oprom, int mode);
554 return i386_dasm_one(stream, pc, oprom, 1);
557 uint8_t i8086_common_cpu_device::read_port_byte(uint16_t port)
559 return m_io->read_byte(port);
562 uint16_t i8086_common_cpu_device::read_port_word(uint16_t port)
564 return m_io->read_word_unaligned(port);
567 void i8086_common_cpu_device::write_port_byte(uint16_t port, uint8_t data)
569 m_io->write_byte(port, data);
572 void i8086_common_cpu_device::write_port_word(uint16_t port, uint16_t data)
574 m_io->write_word_unaligned(port, data);
577 uint32_t i8086_common_cpu_device::calc_addr(int seg, uint16_t offset, int size, int op, bool override)
579 if ( m_seg_prefix && (seg==DS || seg==SS) && override )
581 return (m_sregs[m_prefix_seg] << 4) + offset;
585 return (m_sregs[seg] << 4) + offset;
589 bool i8086_common_cpu_device::common_op(uint8_t op)
593 case 0x00: // i_add_br8
596 PutbackRMByte(m_dst);
597 CLKM(ALU_RR8,ALU_MR8);
600 case 0x01: // i_add_wr16
603 PutbackRMWord(m_dst);
604 CLKM(ALU_RR16,ALU_MR16);
607 case 0x02: // i_add_r8b
611 CLKM(ALU_RR8,ALU_RM8);
614 case 0x03: // i_add_r16w
618 CLKM(ALU_RR16,ALU_RM16);
621 case 0x04: // i_add_ald8
624 m_regs.b[AL] = m_dst;
628 case 0x05: // i_add_axd16
631 m_regs.w[AX] = m_dst;
635 case 0x06: // i_push_es
640 case 0x07: // i_pop_es
645 case 0x08: // i_or_br8
648 PutbackRMByte(m_dst);
649 CLKM(ALU_RR8,ALU_MR8);
652 case 0x09: // i_or_wr16
655 PutbackRMWord(m_dst);
656 CLKM(ALU_RR16,ALU_MR16);
659 case 0x0a: // i_or_r8b
663 CLKM(ALU_RR8,ALU_RM8);
666 case 0x0b: // i_or_r16w
670 CLKM(ALU_RR16,ALU_RM16);
673 case 0x0c: // i_or_ald8
676 m_regs.b[AL] = m_dst;
680 case 0x0d: // i_or_axd16
683 m_regs.w[AX] = m_dst;
687 case 0x0e: // i_push_cs
692 case 0x10: // i_adc_br8
696 uint32_t tmpcf = ADDB();
697 PutbackRMByte(m_dst);
699 CLKM(ALU_RR8,ALU_MR8);
702 case 0x11: // i_adc_wr16
706 uint32_t tmpcf = ADDX();
707 PutbackRMWord(m_dst);
709 CLKM(ALU_RR16,ALU_MR16);
713 case 0x12: // i_adc_r8b
718 CLKM(ALU_RR8,ALU_RM8);
721 case 0x13: // i_adc_r16w
726 CLKM(ALU_RR16,ALU_RM16);
729 case 0x14: // i_adc_ald8
733 m_regs.b[AL] = m_dst;
737 case 0x15: // i_adc_axd16
741 m_regs.w[AX] = m_dst;
745 case 0x16: // i_push_ss
750 case 0x17: // i_pop_ss
756 case 0x18: // i_sbb_br8
762 PutbackRMByte(m_dst);
764 CLKM(ALU_RR8,ALU_MR8);
768 case 0x19: // i_sbb_wr16
774 PutbackRMWord(m_dst);
776 CLKM(ALU_RR16,ALU_MR16);
780 case 0x1a: // i_sbb_r8b
785 CLKM(ALU_RR8,ALU_RM8);
788 case 0x1b: // i_sbb_r16w
793 CLKM(ALU_RR16,ALU_RM16);
796 case 0x1c: // i_sbb_ald8
800 m_regs.b[AL] = m_dst;
804 case 0x1d: // i_sbb_axd16
808 m_regs.w[AX] = m_dst;
812 case 0x1e: // i_push_ds
817 case 0x1f: // i_pop_ds
823 case 0x20: // i_and_br8
826 PutbackRMByte(m_dst);
827 CLKM(ALU_RR8,ALU_MR8);
830 case 0x21: // i_and_wr16
833 PutbackRMWord(m_dst);
834 CLKM(ALU_RR16,ALU_MR16);
837 case 0x22: // i_and_r8b
841 CLKM(ALU_RR8,ALU_RM8);
844 case 0x23: // i_and_r16w
848 CLKM(ALU_RR16,ALU_RM16);
851 case 0x24: // i_and_ald8
854 m_regs.b[AL] = m_dst;
858 case 0x25: // i_and_axd16
861 m_regs.w[AX] = m_dst;
866 m_seg_prefix_next = true;
877 case 0x28: // i_sub_br8
880 PutbackRMByte(m_dst);
881 CLKM(ALU_RR8,ALU_MR8);
884 case 0x29: // i_sub_wr16
887 PutbackRMWord(m_dst);
888 CLKM(ALU_RR16,ALU_MR16);
891 case 0x2a: // i_sub_r8b
895 CLKM(ALU_RR8,ALU_RM8);
898 case 0x2b: // i_sub_r16w
902 CLKM(ALU_RR16,ALU_RM16);
905 case 0x2c: // i_sub_ald8
908 m_regs.b[AL] = m_dst;
912 case 0x2d: // i_sub_axd16
915 m_regs.w[AX] = m_dst;
920 m_seg_prefix_next = true;
931 case 0x30: // i_xor_br8
934 PutbackRMByte(m_dst);
935 CLKM(ALU_RR8,ALU_MR8);
938 case 0x31: // i_xor_wr16
941 PutbackRMWord(m_dst);
942 CLKM(ALU_RR16,ALU_RM16);
945 case 0x32: // i_xor_r8b
949 CLKM(ALU_RR8,ALU_RM8);
952 case 0x33: // i_xor_r16w
956 CLKM(ALU_RR16,ALU_RM16);
959 case 0x34: // i_xor_ald8
962 m_regs.b[AL] = m_dst;
966 case 0x35: // i_xor_axd16
969 m_regs.w[AX] = m_dst;
974 m_seg_prefix_next = true;
980 ADJB(6, (m_regs.b[AL] > 0xf9) ? 2 : 1);
985 case 0x38: // i_cmp_br8
988 CLKM(ALU_RR8,ALU_RM8);
991 case 0x39: // i_cmp_wr16
994 CLKM(ALU_RR16,ALU_RM16);
997 case 0x3a: // i_cmp_r8b
1000 CLKM(ALU_RR8,ALU_RM8);
1003 case 0x3b: // i_cmp_r16w
1006 CLKM(ALU_RR16,ALU_RM16);
1009 case 0x3c: // i_cmp_ald8
1015 case 0x3d: // i_cmp_axd16
1022 m_seg_prefix_next = true;
1028 ADJB(-6, (m_regs.b[AL] < 6) ? -2 : -1);
1033 case 0x40: // i_inc_ax
1038 case 0x41: // i_inc_cx
1043 case 0x42: // i_inc_dx
1048 case 0x43: // i_inc_bx
1053 case 0x44: // i_inc_sp
1058 case 0x45: // i_inc_bp
1063 case 0x46: // i_inc_si
1068 case 0x47: // i_inc_di
1074 case 0x48: // i_dec_ax
1079 case 0x49: // i_dec_cx
1084 case 0x4a: // i_dec_dx
1089 case 0x4b: // i_dec_bx
1094 case 0x4c: // i_dec_sp
1099 case 0x4d: // i_dec_bp
1104 case 0x4e: // i_dec_si
1109 case 0x4f: // i_dec_di
1115 case 0x50: // i_push_ax
1120 case 0x51: // i_push_cx
1125 case 0x52: // i_push_dx
1130 case 0x53: // i_push_bx
1135 case 0x54: // i_push_sp
1136 PUSH(m_regs.w[SP]-2);
1140 case 0x55: // i_push_bp
1145 case 0x56: // i_push_si
1150 case 0x57: // i_push_di
1156 case 0x58: // i_pop_ax
1157 m_regs.w[AX] = POP();
1161 case 0x59: // i_pop_cx
1162 m_regs.w[CX] = POP();
1166 case 0x5a: // i_pop_dx
1167 m_regs.w[DX] = POP();
1171 case 0x5b: // i_pop_bx
1172 m_regs.w[BX] = POP();
1176 case 0x5c: // i_pop_sp
1177 m_regs.w[SP] = POP();
1181 case 0x5d: // i_pop_bp
1182 m_regs.w[BP] = POP();
1186 case 0x5e: // i_pop_si
1187 m_regs.w[SI] = POP();
1191 case 0x5f: // i_pop_di
1192 m_regs.w[DI] = POP();
1196 // 8086 'invalid opcodes', as documented at http://www.os2museum.com/wp/?p=2147 and tested on real hardware
1197 // - 0x60 - 0x6f are aliases to 0x70 - 0x7f.
1198 // - 0xc0, 0xc1, 0xc8, 0xc9 are also aliases where the CPU ignores BIT 1 (*).
1199 // - 0xf1 is an alias to 0xf0.
1201 // Instructions are used in the boot sector for some versions of
1202 // MS-DOS (e.g. the DEC Rainbow-100 version of DOS 2.x)
1239 case 0x77: // i_jnce
1265 JMP((SF!=OF)&&(!ZF));
1275 JMP((ZF)||(SF!=OF));
1279 case 0x7f: // i_jnle
1280 JMP((SF==OF)&&(!ZF));
1284 case 0x80: // i_80pre
1288 m_dst = GetRMByte();
1290 if (m_modrm >=0xc0 ) { CLK(ALU_RI8); }
1291 else if ((m_modrm & 0x38)==0x38) { CLK(ALU_MI8_RO); }
1292 else { CLK(ALU_MI8); }
1293 switch (m_modrm & 0x38)
1295 case 0x00: set_CFB(ADDB()); PutbackRMByte(m_dst); break;
1296 case 0x08: ORB(); PutbackRMByte(m_dst); break;
1297 case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break;
1298 case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break;
1299 case 0x20: ANDB(); PutbackRMByte(m_dst); break;
1300 case 0x28: set_CFB(SUBB()); PutbackRMByte(m_dst); break;
1301 case 0x30: XORB(); PutbackRMByte(m_dst); break;
1302 case 0x38: set_CFB(SUBB()); break; /* CMP */
1308 case 0x81: // i_81pre
1312 m_dst = GetRMWord();
1313 m_src = fetch_word();
1314 if (m_modrm >=0xc0 ) { CLK(ALU_RI16); }
1315 else if ((m_modrm & 0x38)==0x38) { CLK(ALU_MI16_RO); }
1316 else { CLK(ALU_MI16); }
1317 switch (m_modrm & 0x38)
1319 case 0x00: set_CFW(ADDX()); PutbackRMWord(m_dst); break;
1320 case 0x08: ORW(); PutbackRMWord(m_dst); break;
1321 case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break;
1322 case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break;
1323 case 0x20: ANDX(); PutbackRMWord(m_dst); break;
1324 case 0x28: set_CFW(SUBX()); PutbackRMWord(m_dst); break;
1325 case 0x30: XORW(); PutbackRMWord(m_dst); break;
1326 case 0x38: set_CFW(SUBX()); break; /* CMP */
1332 case 0x82: // i_82pre
1336 m_dst = GetRMByte();
1337 m_src = (int8_t)fetch();
1338 if (m_modrm >=0xc0 ) { CLK(ALU_RI8); }
1339 else if ((m_modrm & 0x38)==0x38) { CLK(ALU_MI8_RO); }
1340 else { CLK(ALU_MI8); }
1341 switch (m_modrm & 0x38)
1343 case 0x00: set_CFB(ADDB()); PutbackRMByte(m_dst); break;
1344 case 0x08: ORB(); PutbackRMByte(m_dst); break;
1345 case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break;
1346 case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBB(); PutbackRMByte(m_dst); set_CFB(tmpcf); break;
1347 case 0x20: ANDB(); PutbackRMByte(m_dst); break;
1348 case 0x28: set_CFB(SUBB()); PutbackRMByte(m_dst); break;
1349 case 0x30: XORB(); PutbackRMByte(m_dst); break;
1350 case 0x38: set_CFB(SUBB()); break; /* CMP */
1356 case 0x83: // i_83pre
1360 m_dst = GetRMWord();
1361 m_src = (uint16_t)((int16_t)((int8_t)fetch()));
1362 if (m_modrm >=0xc0 ) { CLK(ALU_R16I8); }
1363 else if ((m_modrm & 0x38)==0x38) { CLK(ALU_M16I8_RO); }
1364 else { CLK(ALU_M16I8); }
1365 switch (m_modrm & 0x38)
1367 case 0x00: set_CFW(ADDX()); PutbackRMWord(m_dst); break;
1368 case 0x08: ORW(); PutbackRMWord(m_dst); break;
1369 case 0x10: m_src += CF ? 1 : 0; tmpcf = ADDX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break;
1370 case 0x18: m_src += CF ? 1 : 0; tmpcf = SUBX(); PutbackRMWord(m_dst); set_CFW(tmpcf); break;
1371 case 0x20: ANDX(); PutbackRMWord(m_dst); break;
1372 case 0x28: set_CFW(SUBX()); PutbackRMWord(m_dst); break;
1373 case 0x30: XORW(); PutbackRMWord(m_dst); break;
1374 case 0x38: set_CFW(SUBX()); break; /* CMP */
1380 case 0x84: // i_test_br8
1383 CLKM(ALU_RR8,ALU_RM8);
1386 case 0x85: // i_test_wr16
1389 CLKM(ALU_RR16,ALU_RM16);
1392 case 0x86: // i_xchg_br8
1395 PutbackRMByte(m_src);
1396 CLKM(XCHG_RR8,XCHG_RM8);
1399 case 0x87: // i_xchg_wr16
1402 PutbackRMWord(m_src);
1403 CLKM(XCHG_RR16,XCHG_RM16);
1407 case 0x88: // i_mov_br8
1411 CLKM(ALU_RR8,ALU_MR8);
1414 case 0x89: // i_mov_wr16
1418 CLKM(ALU_RR16,ALU_MR16);
1421 case 0x8a: // i_mov_r8b
1423 m_src = GetRMByte();
1425 CLKM(ALU_RR8,ALU_RM8);
1428 case 0x8b: // i_mov_r16w
1430 m_src = GetRMWord();
1432 CLKM(ALU_RR16,ALU_RM16);
1435 case 0x8c: // i_mov_wsreg
1437 PutRMWord(m_sregs[(m_modrm & 0x18) >> 3]); // confirmed on hw: modrm bit 5 ignored
1438 CLKM(MOV_RS,MOV_MS);
1443 get_ea(0, I8086_NONE);
1448 case 0x8e: // i_mov_sregw
1450 m_src = GetRMWord();
1451 m_sregs[(m_modrm & 0x18) >> 3] = m_src; // confirmed on hw: modrm bit 5 ignored
1452 CLKM(MOV_SR,MOV_SM);
1453 m_no_interrupt = 1; // Disable IRQ after load segment register.
1456 case 0x8f: // i_popw
1459 CLKM(POP_R16,POP_M16);
1466 case 0x91: // i_xchg_axcx
1471 case 0x92: // i_xchg_axdx
1476 case 0x93: // i_xchg_axbx
1481 case 0x94: // i_xchg_axsp
1486 case 0x95: // i_xchg_axbp
1491 case 0x96: // i_xchg_axsi
1496 case 0x97: // i_xchg_axdi
1503 m_regs.b[AH] = (m_regs.b[AL] & 0x80) ? 0xff : 0;
1508 m_regs.w[DX] = (m_regs.b[AH] & 0x80) ? 0xffff : 0;
1512 case 0x9a: // i_call_far
1514 uint16_t tmp = fetch_word();
1515 uint16_t tmp2 = fetch_word();
1524 case 0x9b: // i_wait
1525 // Wait for assertion of /TEST
1526 if (m_test_state == 0)
1535 case 0x9c: // i_pushf
1536 PUSH( CompressFlags() );
1540 case 0x9d: // i_popf
1544 case 0x9e: // i_sahf
1546 uint32_t tmp = (CompressFlags() & 0xff00) | (m_regs.b[AH] & 0xd5);
1552 case 0x9f: // i_lahf
1553 m_regs.b[AH] = CompressFlags();
1558 case 0xa0: // i_mov_aldisp
1560 uint32_t addr = fetch_word();
1561 m_regs.b[AL] = GetMemB(DS, addr);
1566 case 0xa1: // i_mov_axdisp
1568 uint32_t addr = fetch_word();
1569 m_regs.w[AX] = GetMemW(DS, addr);
1574 case 0xa2: // i_mov_dispal
1576 uint32_t addr = fetch_word();
1577 PutMemB(DS, addr, m_regs.b[AL]);
1582 case 0xa3: // i_mov_dispax
1584 uint32_t addr = fetch_word();
1585 PutMemW(DS, addr, m_regs.w[AX]);
1590 case 0xa4: // i_movsb
1594 case 0xa5: // i_movsw
1598 case 0xa6: // i_cmpsb
1602 case 0xa7: // i_cmpsw
1607 case 0xa8: // i_test_ald8
1613 case 0xa9: // i_test_axd16
1619 case 0xaa: // i_stosb
1623 case 0xab: // i_stosw
1627 case 0xac: // i_lodsb
1631 case 0xad: // i_lodsw
1635 case 0xae: // i_scasb
1639 case 0xaf: // i_scasw
1644 case 0xb0: // i_mov_ald8
1645 m_regs.b[AL] = fetch();
1649 case 0xb1: // i_mov_cld8
1650 m_regs.b[CL] = fetch();
1654 case 0xb2: // i_mov_dld8
1655 m_regs.b[DL] = fetch();
1659 case 0xb3: // i_mov_bld8
1660 m_regs.b[BL] = fetch();
1664 case 0xb4: // i_mov_ahd8
1665 m_regs.b[AH] = fetch();
1669 case 0xb5: // i_mov_chd8
1670 m_regs.b[CH] = fetch();
1674 case 0xb6: // i_mov_dhd8
1675 m_regs.b[DH] = fetch();
1679 case 0xb7: // i_mov_bhd8
1680 m_regs.b[BH] = fetch();
1685 case 0xb8: // i_mov_axd16
1686 m_regs.b[AL] = fetch();
1687 m_regs.b[AH] = fetch();
1691 case 0xb9: // i_mov_cxd16
1692 m_regs.b[CL] = fetch();
1693 m_regs.b[CH] = fetch();
1697 case 0xba: // i_mov_dxd16
1698 m_regs.b[DL] = fetch();
1699 m_regs.b[DH] = fetch();
1703 case 0xbb: // i_mov_bxd16
1704 m_regs.b[BL] = fetch();
1705 m_regs.b[BH] = fetch();
1709 case 0xbc: // i_mov_spd16
1710 m_regs.b[SPL] = fetch();
1711 m_regs.b[SPH] = fetch();
1715 case 0xbd: // i_mov_bpd16
1716 m_regs.b[BPL] = fetch();
1717 m_regs.b[BPH] = fetch();
1721 case 0xbe: // i_mov_sid16
1722 m_regs.b[SIL] = fetch();
1723 m_regs.b[SIH] = fetch();
1727 case 0xbf: // i_mov_did16
1728 m_regs.b[DIL] = fetch();
1729 m_regs.b[DIH] = fetch();
1733 case 0xc0: // 0xc0 is 0xc2 - see (*)
1734 case 0xc2: // i_ret_d16
1736 uint32_t count = fetch_word();
1738 m_regs.w[SP] += count;
1743 case 0xc1: // 0xc1 is 0xc3 - see (*)
1749 case 0xc4: // i_les_dw
1751 RegWord( GetRMWord() );
1752 m_sregs[ES] = GetnextRMWord();
1756 case 0xc5: // i_lds_dw
1758 RegWord( GetRMWord() );
1759 m_sregs[DS] = GetnextRMWord();
1763 case 0xc6: // i_mov_bd8
1766 CLKM(MOV_RI8,MOV_MI8);
1769 case 0xc7: // i_mov_wd16
1772 CLKM(MOV_RI16,MOV_MI16);
1775 case 0xc8: // 0xc8 = 0xca - see (*)
1776 case 0xca: // i_retf_d16
1778 uint32_t count = fetch_word();
1780 m_sregs[CS] = POP();
1781 m_regs.w[SP] += count;
1786 case 0xc9: // 0xc9 = 0xcb - see (*)
1787 case 0xcb: // i_retf
1789 m_sregs[CS] = POP();
1793 case 0xcc: // i_int3
1799 interrupt(fetch(), 0);
1803 case 0xce: // i_into
1813 case 0xcf: // i_iret
1815 m_sregs[CS] = POP();
1820 case 0xd0: // i_rotshft_b
1822 m_src = GetRMByte();
1824 CLKM(ROT_REG_1,ROT_M8_1);
1825 switch ( m_modrm & 0x38 )
1827 case 0x00: ROL_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1828 case 0x08: ROR_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1829 case 0x10: ROLC_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1830 case 0x18: RORC_BYTE(); PutbackRMByte(m_dst); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1832 case 0x20: SHL_BYTE(1); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1833 case 0x28: SHR_BYTE(1); m_OverVal = (m_src ^ m_dst) & 0x80; break;
1834 case 0x38: SHRA_BYTE(1); m_OverVal = 0; break;
1838 case 0xd1: // i_rotshft_w
1840 m_src = GetRMWord();
1842 CLKM(ROT_REG_1,ROT_M8_1);
1843 switch ( m_modrm & 0x38 )
1845 case 0x00: ROL_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1846 case 0x08: ROR_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1847 case 0x10: ROLC_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1848 case 0x18: RORC_WORD(); PutbackRMWord(m_dst); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1850 case 0x20: SHL_WORD(1); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1851 case 0x28: SHR_WORD(1); m_OverVal = (m_src ^ m_dst) & 0x8000; break;
1852 case 0x38: SHRA_WORD(1); m_OverVal = 0; break;
1858 uint8_t base = fetch();
1864 m_regs.b[AH] = m_regs.b[AL] / base;
1865 m_regs.b[AL] %= base;
1866 set_SZPF_Word(m_regs.w[AX]);
1873 uint8_t base = fetch();
1874 m_regs.b[AL] = m_regs.b[AH] * base + m_regs.b[AL];
1876 set_SZPF_Byte(m_regs.b[AL]);
1881 case 0xd6: // i_salc
1882 m_regs.b[AL] = (CF ? 0xff : 0);
1883 CLK(ALU_RR8); // is sbb al,al
1886 case 0xd7: // i_trans
1887 m_regs.b[AL] = GetMemB( DS, m_regs.w[BX] + m_regs.b[AL] );
1902 logerror("%06x: Unimplemented floating point escape %02x%02x\n", pc(), op, m_modrm);
1906 case 0xe0: // i_loopne
1908 int8_t disp = (int8_t)fetch();
1911 if (!ZF && m_regs.w[CX])
1921 case 0xe1: // i_loope
1923 int8_t disp = (int8_t)fetch();
1926 if (ZF && m_regs.w[CX])
1936 case 0xe2: // i_loop
1938 int8_t disp = (int8_t)fetch();
1951 case 0xe3: // i_jcxz
1953 int8_t disp = (int8_t)fetch();
1955 if (m_regs.w[CX] == 0)
1965 case 0xe4: // i_inal
1966 if (m_lock) m_lock_handler(1);
1967 m_regs.b[AL] = read_port_byte( fetch() );
1968 if (m_lock) { m_lock_handler(0); m_lock = false; }
1972 case 0xe5: // i_inax
1974 uint8_t port = fetch();
1976 m_regs.w[AX] = read_port_word(port);
1981 case 0xe6: // i_outal
1982 write_port_byte( fetch(), m_regs.b[AL]);
1986 case 0xe7: // i_outax
1988 uint8_t port = fetch();
1990 write_port_word(port, m_regs.w[AX]);
1996 case 0xe8: // i_call_d16
1998 int16_t tmp = (int16_t)fetch_word();
2006 case 0xe9: // i_jmp_d16
2008 int16_t offset = (int16_t)fetch_word();
2014 case 0xea: // i_jmp_far
2016 uint16_t tmp = fetch_word();
2017 uint16_t tmp1 = fetch_word();
2025 case 0xeb: // i_jmp_d8
2027 int tmp = (int)((int8_t)fetch());
2030 if (tmp==-2 && m_no_interrupt==0 && (m_pending_irq==0) && m_icount>0)
2032 m_icount%=12; /* cycle skip */
2034 m_ip = (uint16_t)(m_ip+tmp);
2038 case 0xec: // i_inaldx
2039 m_regs.b[AL] = read_port_byte(m_regs.w[DX]);
2043 case 0xed: // i_inaxdx
2045 uint32_t port = m_regs.w[DX];
2047 m_regs.w[AX] = read_port_word(port);
2052 case 0xee: // i_outdxal
2053 write_port_byte(m_regs.w[DX], m_regs.b[AL]);
2057 case 0xef: // i_outdxax
2059 uint32_t port = m_regs.w[DX];
2061 write_port_word(port, m_regs.w[AX]);
2067 case 0xf0: // i_lock
2068 case 0xf1: // 0xf1 is 0xf0; verified on real CPU
2069 logerror("%06x: Warning - BUSLOCK\n", pc());
2075 case 0xf2: // i_repne
2077 bool invalid = false;
2078 uint8_t next = repx_op();
2079 uint16_t c = m_regs.w[CX];
2083 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;
2084 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;
2085 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;
2086 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;
2087 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;
2088 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;
2089 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;
2090 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;
2091 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;
2092 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;
2094 logerror("%06x: REPNE invalid\n", pc());
2095 // Decrement IP so the normal instruction will be executed next
2102 if(!(ZF && ((next & 6) == 6)))
2108 case 0xf3: // i_repe
2110 bool invalid = false;
2111 uint8_t next = repx_op();
2112 uint16_t c = m_regs.w[CX];
2116 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;
2117 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;
2118 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;
2119 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;
2120 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;
2121 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;
2122 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;
2123 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;
2124 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;
2125 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;
2127 logerror("%06x: REPE invalid\n", pc());
2128 // Decrement IP so the normal instruction will be executed next
2135 if(!(!ZF && ((next & 6) == 6)))
2142 //logerror("%s: %06x: HALT\n", tag(), pc());
2148 m_CarryVal = !m_CarryVal;
2152 case 0xf6: // i_f6pre
2155 uint32_t uresult,uresult2;
2156 int32_t result,result2;
2160 switch ( m_modrm & 0x38 )
2162 case 0x00: /* TEST */
2163 case 0x08: /* TEST (alias) */
2165 m_CarryVal = m_OverVal = 0;
2167 CLKM(ALU_RI8,ALU_MI8_RO);
2169 case 0x10: /* NOT */
2170 PutbackRMByte(~tmp);
2171 CLKM(NEGNOT_R8,NEGNOT_M8);
2173 case 0x18: /* NEG */
2174 m_CarryVal = (tmp!=0) ? 1 : 0;
2177 PutbackRMByte(tmp&0xff);
2178 CLKM(NEGNOT_R8,NEGNOT_M8);
2180 case 0x20: /* MUL */
2181 uresult = m_regs.b[AL] * tmp;
2182 m_regs.w[AX] = (uint16_t)uresult;
2183 m_CarryVal = m_OverVal = (m_regs.b[AH]!=0) ? 1 : 0;
2184 set_ZF(m_regs.w[AX]);
2185 CLKM(MUL_R8,MUL_M8);
2187 case 0x28: /* IMUL */
2188 result = (int16_t)((int8_t)m_regs.b[AL])*(int16_t)((int8_t)tmp);
2189 m_regs.w[AX] = (uint16_t)result;
2190 m_CarryVal = m_OverVal = (m_regs.b[AH]!=0) ? 1 : 0;
2191 set_ZF(m_regs.w[AX]);
2192 CLKM(IMUL_R8,IMUL_M8);
2194 case 0x30: /* DIV */
2197 uresult = m_regs.w[AX];
2198 uresult2 = uresult % tmp;
2199 if ((uresult /= tmp) > 0xff)
2205 m_regs.b[AL] = uresult;
2206 m_regs.b[AH] = uresult2;
2213 CLKM(DIV_R8,DIV_M8);
2215 case 0x38: /* IDIV */
2218 result = (int16_t)m_regs.w[AX];
2219 result2 = result % (int16_t)((int8_t)tmp);
2220 if ((result /= (int16_t)((int8_t)tmp)) > 0xff)
2226 m_regs.b[AL] = result;
2227 m_regs.b[AH] = result2;
2234 CLKM(IDIV_R8,IDIV_M8);
2241 case 0xf7: // i_f7pre
2244 uint32_t uresult,uresult2;
2245 int32_t result,result2;
2249 switch ( m_modrm & 0x38 )
2251 case 0x00: /* TEST */
2252 case 0x08: /* TEST (alias) */
2253 tmp2 = fetch_word();
2255 m_CarryVal = m_OverVal = 0;
2257 CLKM(ALU_RI16,ALU_MI16_RO);
2259 case 0x10: /* NOT */
2260 PutbackRMWord(~tmp);
2261 CLKM(NEGNOT_R16,NEGNOT_M16);
2263 case 0x18: /* NEG */
2264 m_CarryVal = (tmp!=0) ? 1 : 0;
2268 CLKM(NEGNOT_R16,NEGNOT_M16);
2270 case 0x20: /* MUL */
2271 uresult = m_regs.w[AX]*tmp;
2272 m_regs.w[AX] = uresult & 0xffff;
2273 m_regs.w[DX] = ((uint32_t)uresult)>>16;
2274 m_CarryVal = m_OverVal = (m_regs.w[DX] != 0) ? 1 : 0;
2275 set_ZF(m_regs.w[AX] | m_regs.w[DX]);
2276 CLKM(MUL_R16,MUL_M16);
2278 case 0x28: /* IMUL */
2279 result = (int32_t)((int16_t)m_regs.w[AX]) * (int32_t)((int16_t)tmp);
2280 m_regs.w[AX] = result & 0xffff;
2281 m_regs.w[DX] = result >> 16;
2282 m_CarryVal = m_OverVal = (m_regs.w[DX] != 0) ? 1 : 0;
2283 set_ZF(m_regs.w[AX] | m_regs.w[DX]);
2284 CLKM(IMUL_R16,IMUL_M16);
2286 case 0x30: /* DIV */
2289 uresult = (((uint32_t)m_regs.w[DX]) << 16) | m_regs.w[AX];
2290 uresult2 = uresult % tmp;
2291 if ((uresult /= tmp) > 0xffff)
2297 m_regs.w[AX] = uresult;
2298 m_regs.w[DX] = uresult2;
2305 CLKM(DIV_R16,DIV_M16);
2307 case 0x38: /* IDIV */
2310 result = ((uint32_t)m_regs.w[DX] << 16) + m_regs.w[AX];
2311 result2 = result % (int32_t)((int16_t)tmp);
2312 if ((result /= (int32_t)((int16_t)tmp)) > 0xffff)
2318 m_regs.w[AX] = result;
2319 m_regs.w[DX] = result2;
2326 CLKM(IDIV_R16,IDIV_M16);
2363 case 0xfe: // i_fepre
2368 switch ( m_modrm & 0x38 )
2370 case 0x00: /* INC */
2372 m_OverVal = (tmp==0x7f);
2374 set_SZPF_Byte(tmp1);
2375 PutbackRMByte(tmp1);
2376 CLKM(INCDEC_R8,INCDEC_M8);
2378 case 0x08: /* DEC */
2380 m_OverVal = (tmp==0x80);
2382 set_SZPF_Byte(tmp1);
2383 PutbackRMByte(tmp1);
2384 CLKM(INCDEC_R8,INCDEC_M8);
2387 logerror("%06x: FE Pre with unimplemented mod\n", pc());
2393 case 0xff: // i_ffpre
2398 switch ( m_modrm & 0x38 )
2400 case 0x00: /* INC */
2402 m_OverVal = (tmp==0x7fff);
2404 set_SZPF_Word(tmp1);
2405 PutbackRMWord(tmp1);
2406 CLKM(INCDEC_R16,INCDEC_M16);
2408 case 0x08: /* DEC */
2410 m_OverVal = (tmp==0x8000);
2412 set_SZPF_Word(tmp1);
2413 PutbackRMWord(tmp1);
2414 CLKM(INCDEC_R16,INCDEC_M16);
2416 case 0x10: /* CALL */
2419 CLKM(CALL_R16,CALL_M16);
2421 case 0x18: /* CALL FAR */
2423 m_sregs[CS] = GetnextRMWord();
2429 case 0x20: /* JMP */
2431 CLKM(JMP_R16,JMP_M16);
2433 case 0x28: /* JMP FAR */
2435 m_sregs[CS] = GetnextRMWord();
2440 CLKM(PUSH_R16,PUSH_M16);
2443 logerror("%06x: FF Pre with unimplemented mod\n", pc());