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