static UINT16 I386OP(shift_rotate16)(UINT8 modrm, UINT32 value, UINT8 shift)
{
	UINT16 src = value;
	UINT16 dst = value;

	if( shift == 0 ) {
		CYCLES_RM(modrm, 3, 7);
	} else if( shift == 1 ) {

		switch( (modrm >> 3) & 0x7 )
		{
			case 0:			/* ROL rm16, 1 */
				I.CF = (src & 0x8000) ? 1 : 0;
				dst = (src << 1) + I.CF;
				I.OF = ((src ^ dst) & 0x8000) ? 1 : 0;
				CYCLES_RM(modrm, 3, 7);
				break;
			case 1:			/* ROR rm16, 1 */
				I.CF = (src & 0x1) ? 1 : 0;
				dst = (I.CF << 15) | (src >> 1);
				I.OF = ((src ^ dst) & 0x8000) ? 1 : 0;
				CYCLES_RM(modrm, 3, 7);
				break;
			case 2:			/* RCL rm16, 1 */
				dst = (src << 1) + I.CF;
				I.CF = (src & 0x8000) ? 1 : 0;
				I.OF = ((src ^ dst) & 0x8000) ? 1 : 0;
				CYCLES_RM(modrm, 9, 10);
				break;
			case 3:			/* RCR rm16, 1 */
				dst = (I.CF << 15) | (src >> 1);
				I.CF = src & 0x1;
				I.OF = ((src ^ dst) & 0x8000) ? 1 : 0;
				CYCLES_RM(modrm, 9, 10);
				break;
			case 4:			/* SHL/SAL rm16, 1 */
			case 6:
				dst = src << 1;
				I.CF = (src & 0x8000) ? 1 : 0;
				I.OF = (((I.CF << 15) ^ dst) & 0x8000) ? 1 : 0;
				SetSZPF16(dst);
				CYCLES_RM(modrm, 3, 7);
				break;
			case 5:			/* SHR rm16, 1 */
				dst = src >> 1;
				I.CF = src & 0x1;
				I.OF = (dst & 0x8000) ? 1 : 0;
				SetSZPF16(dst);
				CYCLES_RM(modrm, 3, 7);
				break;
			case 7:			/* SAR rm16, 1 */
				dst = (INT16)(src) >> 1;
				I.CF = src & 0x1;
				I.OF = 0;
				SetSZPF16(dst);
				CYCLES_RM(modrm, 3, 7);
				break;
		}
	} else {

		switch( (modrm >> 3) & 0x7 )
		{
			case 0:			/* ROL rm16, i8 */
				dst = ((src & ((UINT16)0xffff >> shift)) << shift) |
					  ((src & ((UINT16)0xffff << (16-shift))) >> (16-shift));
				I.CF = (src >> (16-shift)) & 0x1;
				CYCLES_RM(modrm, 3, 7);
				break;
			case 1:			/* ROR rm16, i8 */
				dst = ((src & ((UINT16)0xffff << shift)) >> shift) |
					  ((src & ((UINT16)0xffff >> (16-shift))) << (16-shift));
				I.CF = (src >> (shift-1)) & 0x1;
				CYCLES_RM(modrm, 3, 7);
				break;
			case 2:			/* RCL rm16, i8 */
				dst = ((src & ((UINT16)0xffff >> shift)) << shift) |
					  ((src & ((UINT16)0xffff << (17-shift))) >> (17-shift)) |
					  (I.CF << (shift-1));
				I.CF = (src >> (16-shift)) & 0x1;
				CYCLES_RM(modrm, 9, 10);
				break;
			case 3:			/* RCR rm16, i8 */
				dst = ((src & ((UINT16)0xffff << shift)) >> shift) |
					  ((src & ((UINT16)0xffff >> (16-shift))) << (17-shift)) |
					  (I.CF << (16-shift));
				I.CF = (src >> (shift-1)) & 0x1;
				CYCLES_RM(modrm, 9, 10);
				break;
			case 4:			/* SHL/SAL rm16, i8 */
			case 6:
				dst = src << shift;
				I.CF = (src & (1 << (16-shift))) ? 1 : 0;
				SetSZPF16(dst);
				CYCLES_RM(modrm, 3, 7);
				break;
			case 5:			/* SHR rm16, i8 */
				dst = src >> shift;
				I.CF = (src & (1 << (shift-1))) ? 1 : 0;
				SetSZPF16(dst);
				CYCLES_RM(modrm, 3, 7);
				break;
			case 7:			/* SAR rm16, i8 */
				dst = (INT16)src >> shift;
				I.CF = (src & (1 << (shift-1))) ? 1 : 0;
				SetSZPF16(dst);
				CYCLES_RM(modrm, 3, 7);
				break;
		}

	}
	return dst;
}



static void I386OP(adc_rm16_r16)(void)		// Opcode 0x11
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm);
		dst = LOAD_RM16(modrm);
		src = ADD16(src, I.CF);
		dst = ADD16(dst, src);
		STORE_RM16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm);
		dst = READ16(ea);
		src = ADD16(src, I.CF);
		dst = ADD16(dst, src);
		WRITE16(ea, dst);
		CYCLES(C_ALU_REG_MEM);
	}
}

static void I386OP(adc_r16_rm16)(void)		// Opcode 0x13
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
		dst = LOAD_REG16(modrm);
		src = ADD16(src, I.CF);
		dst = ADD16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
		dst = LOAD_REG16(modrm);
		src = ADD16(src, I.CF);
		dst = ADD16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_MEM_REG);
	}
}

static void I386OP(adc_ax_i16)(void)		// Opcode 0x15
{
	UINT16 src, dst;
	src = FETCH16();
	dst = REG16(AX);
	src = ADD16(src, I.CF);
	dst = ADD16(dst, src);
	REG16(AX) = dst;
	CYCLES(C_ALU_I_ACC);
}

static void I386OP(add_rm16_r16)(void)		// Opcode 0x01
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm);
		dst = LOAD_RM16(modrm);
		dst = ADD16(dst, src);
		STORE_RM16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm);
		dst = READ16(ea);
		dst = ADD16(dst, src);
		WRITE16(ea, dst);
		CYCLES(C_ALU_REG_MEM);
	}
}

static void I386OP(add_r16_rm16)(void)		// Opcode 0x03
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
		dst = LOAD_REG16(modrm);
		dst = ADD16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
		dst = LOAD_REG16(modrm);
		dst = ADD16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_MEM_REG);
	}
}

static void I386OP(add_ax_i16)(void)		// Opcode 0x05
{
	UINT16 src, dst;
	src = FETCH16();
	dst = REG16(AX);
	dst = ADD16(dst, src);
	REG16(AX) = dst;
	CYCLES(C_ALU_I_ACC);
}

static void I386OP(and_rm16_r16)(void)		// Opcode 0x21
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm);
		dst = LOAD_RM16(modrm);
		dst = AND16(dst, src);
		STORE_RM16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm);
		dst = READ16(ea);
		dst = AND16(dst, src);
		WRITE16(ea, dst);
		CYCLES(C_ALU_REG_MEM);
	}
}

static void I386OP(and_r16_rm16)(void)		// Opcode 0x23
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
		dst = LOAD_REG16(modrm);
		dst = AND16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
		dst = LOAD_REG16(modrm);
		dst = AND16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_MEM_REG);
	}
}

static void I386OP(and_ax_i16)(void)		// Opcode 0x25
{
	UINT16 src, dst;
	src = FETCH16();
	dst = REG16(AX);
	dst = AND16(dst, src);
	REG16(AX) = dst;
	CYCLES(C_ALU_I_ACC);
}

static void I386OP(bsf_r16_rm16)(void)		// Opcode 0x0f bc
{
	UINT16 src, dst, temp;
	UINT8 modrm = FETCH();

	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
	}

	dst = 0;

	if( src == 0 ) {
		I.ZF = 1;
	} else {
		I.ZF = 0;
		temp = 0;
		while( (src & (1 << temp)) == 0 ) {
			temp++;
			dst = temp;
			CYCLES(3);
		}
	}
	CYCLES(11);
	STORE_REG16(modrm, dst);
}

static void I386OP(bsr_r16_rm16)(void)		// Opcode 0x0f bd
{
	UINT16 src, dst, temp;
	UINT8 modrm = FETCH();

	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
	}

	dst = 0;

	if( src == 0 ) {
		I.ZF = 1;
	} else {
		I.ZF = 0;
		temp = 15;
		while( (src & (1 << temp)) == 0 ) {
			temp--;
			dst = temp;
			CYCLES(3);
		}
	}
	CYCLES(9);
	STORE_REG16(modrm, dst);
}


static void I386OP(bt_rm16_r16)(void)		// Opcode 0x0f a3
{
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 dst = LOAD_RM16(modrm);
		UINT16 bit = LOAD_REG16(modrm);

		if( dst & (1 << bit) )
			I.CF = 1;
		else
			I.CF = 0;

		CYCLES(3);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 dst = READ16(ea);
		UINT16 bit = LOAD_REG16(modrm);

		if( dst & (1 << bit) )
			I.CF = 1;
		else
			I.CF = 0;

		CYCLES(12);
	}
}

static void I386OP(btc_rm16_r16)(void)		// Opcode 0x0f bb
{
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 dst = LOAD_RM16(modrm);
		UINT16 bit = LOAD_REG16(modrm);

		if( dst & (1 << bit) )
			I.CF = 1;
		else
			I.CF = 0;
		dst ^= (1 << bit);

		STORE_RM16(modrm, dst);
		CYCLES(6);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 dst = READ16(ea);
		UINT16 bit = LOAD_REG16(modrm);

		if( dst & (1 << bit) )
			I.CF = 1;
		else
			I.CF = 0;
		dst ^= (1 << bit);

		WRITE16(ea, dst);
		CYCLES(13);
	}
}

static void I386OP(btr_rm16_r16)(void)		// Opcode 0x0f b3
{
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 dst = LOAD_RM16(modrm);
		UINT16 bit = LOAD_REG16(modrm);

		if( dst & (1 << bit) )
			I.CF = 1;
		else
			I.CF = 0;
		dst &= ~(1 << bit);

		STORE_RM16(modrm, dst);
		CYCLES(6);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 dst = READ16(ea);
		UINT16 bit = LOAD_REG16(modrm);

		if( dst & (1 << bit) )
			I.CF = 1;
		else
			I.CF = 0;
		dst &= ~(1 << bit);

		WRITE16(ea, dst);
		CYCLES(13);
	}
}

static void I386OP(bts_rm16_r16)(void)		// Opcode 0x0f ab
{
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 dst = LOAD_RM16(modrm);
		UINT16 bit = LOAD_REG16(modrm);

		if( dst & (1 << bit) )
			I.CF = 1;
		else
			I.CF = 0;
		dst |= (1 << bit);

		STORE_RM16(modrm, dst);
		CYCLES(6);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 dst = READ16(ea);
		UINT16 bit = LOAD_REG16(modrm);

		if( dst & (1 << bit) )
			I.CF = 1;
		else
			I.CF = 0;
		dst |= (1 << bit);

		WRITE16(ea, dst);
		CYCLES(13);
	}
}

static void I386OP(call_abs16)(void)		// Opcode 0x9a
{
	UINT16 offset = FETCH16();
	UINT16 ptr = FETCH16();

	if( PROTECTED_MODE ) {
		/* TODO */
		osd_die("i386: call_abs16 in protected mode unimplemented\n");
	} else {
		if (I.sreg[CS].d)
		{
			PUSH32( I.sreg[CS].selector );
			PUSH32( I.eip );
		}
		else
		{
			PUSH16( I.sreg[CS].selector );
			PUSH16( I.eip );
		}
		I.sreg[CS].selector = ptr;
		I.eip = offset;
		CYCLES(17 + 1);		/* TODO: Timing = 17 + m */
	}
	CHANGE_PC(I.eip);
}

static void I386OP(call_rel16)(void)		// Opcode 0xe8
{
	INT16 disp = FETCH16();

	PUSH16( I.eip );
	if (I.sreg[CS].d)
		I.eip += disp;
	else
		I.eip = (I.eip & 0xFFFF0000) | (UINT16) (I.eip + disp);
	CHANGE_PC(I.eip);
	CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
}

static void I386OP(cbw)(void)				// Opcode 0x98
{
	REG16(AX) = (INT16)((INT8)REG8(AL));
	CYCLES(3);
}

static void I386OP(cmp_rm16_r16)(void)		// Opcode 0x39
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm);
		dst = LOAD_RM16(modrm);
		SUB16(dst, src);
		CYCLES(C_CMP_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm);
		dst = READ16(ea);
		SUB16(dst, src);
		CYCLES(C_CMP_REG_MEM);
	}
}

static void I386OP(cmp_r16_rm16)(void)		// Opcode 0x3b
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
		dst = LOAD_REG16(modrm);
		SUB16(dst, src);
		CYCLES(C_CMP_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
		dst = LOAD_REG16(modrm);
		SUB16(dst, src);
		CYCLES(C_CMP_MEM_REG);
	}
}

static void I386OP(cmp_ax_i16)(void)		// Opcode 0x3d
{
	UINT16 src, dst;
	src = FETCH16();
	dst = REG16(AX);
	SUB16(dst, src);
	CYCLES(C_CMP_I_ACC);
}

static void I386OP(cmpsw)(void)				// Opcode 0xa7
{
	UINT32 eas, ead;
	UINT16 src, dst;
	if( I.segment_prefix ) {
		eas = i386_translate( I.segment_override, I.sreg[CS].d ? REG32(ESI) : REG16(SI) );
	} else {
		eas = i386_translate( DS, I.sreg[CS].d ? REG32(ESI) : REG16(SI) );
	}
	ead = i386_translate( ES, I.sreg[CS].d ? REG32(EDI) : REG16(DI) );
	src = READ16(eas);
	dst = READ16(ead);
	SUB16(dst, src);
	BUMP_SI(2);
	BUMP_DI(2);
	CYCLES(10);
}

static void I386OP(cwd)(void)				// Opcode 0x99
{
	if( REG16(AX) & 0x8000 ) {
		REG16(DX) = 0xffff;
	} else {
		REG16(DX) = 0x0000;
	}
	CYCLES(2);
}

static void I386OP(dec_ax)(void)			// Opcode 0x48
{
	REG16(AX) = DEC16( REG16(AX) );
	CYCLES(2);
}

static void I386OP(dec_cx)(void)			// Opcode 0x49
{
	REG16(CX) = DEC16( REG16(CX) );
	CYCLES(2);
}

static void I386OP(dec_dx)(void)			// Opcode 0x4a
{
	REG16(DX) = DEC16( REG16(DX) );
	CYCLES(2);
}

static void I386OP(dec_bx)(void)			// Opcode 0x4b
{
	REG16(BX) = DEC16( REG16(BX) );
	CYCLES(2);
}

static void I386OP(dec_sp)(void)			// Opcode 0x4c
{
	REG16(SP) = DEC16( REG16(SP) );
	CYCLES(2);
}

static void I386OP(dec_bp)(void)			// Opcode 0x4d
{
	REG16(BP) = DEC16( REG16(BP) );
	CYCLES(2);
}

static void I386OP(dec_si)(void)			// Opcode 0x4e
{
	REG16(SI) = DEC16( REG16(SI) );
	CYCLES(2);
}

static void I386OP(dec_di)(void)			// Opcode 0x4f
{
	REG16(DI) = DEC16( REG16(DI) );
	CYCLES(2);
}

static void I386OP(imul_r16_rm16)(void)		// Opcode 0x0f af
{
	UINT8 modrm = FETCH();
	INT32 result;
	INT32 src, dst;
	if( modrm >= 0xc0 ) {
		src = (INT32)(INT16)LOAD_RM16(modrm);
		CYCLES(12);		/* TODO: Correct multiply timing */
	} else {
		UINT32 ea = GetEA(modrm);
		src = (INT32)(INT16)READ16(ea);
		CYCLES(15);		/* TODO: Correct multiply timing */
	}

	dst = (INT32)(INT16)LOAD_REG16(modrm);
	result = src * dst;

	STORE_REG16(modrm, (UINT16)result);

	I.CF = I.OF = !(result == (INT32)(INT16)result);
}

static void I386OP(imul_r16_rm16_i16)(void)	// Opcode 0x69
{
	UINT8 modrm = FETCH();
	INT32 result;
	INT32 src, dst;
	if( modrm >= 0xc0 ) {
		dst = (INT32)(INT16)LOAD_RM16(modrm);
		CYCLES(12);		/* TODO: Correct multiply timing */
	} else {
		UINT32 ea = GetEA(modrm);
		dst = (INT32)(INT16)READ16(ea);
		CYCLES(15);		/* TODO: Correct multiply timing */
	}

	src = (INT32)(INT16)FETCH16();
	result = src * dst;

	STORE_REG16(modrm, (UINT16)result);

	I.CF = I.OF = !(result == (INT32)(INT16)result);
}

static void I386OP(imul_r16_rm16_i8)(void)	// Opcode 0x6b
{
	UINT8 modrm = FETCH();
	INT32 result;
	INT32 src, dst;
	if( modrm >= 0xc0 ) {
		dst = (INT32)(INT16)LOAD_RM16(modrm);
		CYCLES(12);		/* TODO: Correct multiply timing */
	} else {
		UINT32 ea = GetEA(modrm);
		dst = (INT32)(INT16)READ16(ea);
		CYCLES(15);		/* TODO: Correct multiply timing */
	}

	src = (INT32)(INT8)FETCH();
	result = src * dst;

	STORE_REG16(modrm, (UINT16)result);

	I.CF = I.OF = !(result == (INT32)(INT16)result);
}

static void I386OP(in_ax_i8)(void)			// Opcode 0xe5
{
	UINT16 port = FETCH();
	UINT16 data = READPORT16(port);
	REG16(AX) = data;
}

static void I386OP(in_ax_dx)(void)			// Opcode 0xed
{
	UINT16 port = REG16(DX);
	UINT16 data = READPORT16(port);
	REG16(AX) = data;
}

static void I386OP(inc_ax)(void)			// Opcode 0x40
{
	REG16(AX) = INC16( REG16(AX) );
	CYCLES(2);
}

static void I386OP(inc_cx)(void)			// Opcode 0x41
{
	REG16(CX) = INC16( REG16(CX) );
	CYCLES(2);
}

static void I386OP(inc_dx)(void)			// Opcode 0x42
{
	REG16(DX) = INC16( REG16(DX) );
	CYCLES(2);
}

static void I386OP(inc_bx)(void)			// Opcode 0x43
{
	REG16(BX) = INC16( REG16(BX) );
	CYCLES(2);
}

static void I386OP(inc_sp)(void)			// Opcode 0x44
{
	REG16(SP) = INC16( REG16(SP) );
	CYCLES(2);
}

static void I386OP(inc_bp)(void)			// Opcode 0x45
{
	REG16(BP) = INC16( REG16(BP) );
	CYCLES(2);
}

static void I386OP(inc_si)(void)			// Opcode 0x46
{
	REG16(SI) = INC16( REG16(SI) );
	CYCLES(2);
}

static void I386OP(inc_di)(void)			// Opcode 0x47
{
	REG16(DI) = INC16( REG16(DI) );
	CYCLES(2);
}

static void I386OP(iret16)(void)			// Opcode 0xcf
{
	if( PROTECTED_MODE ) {
		/* TODO: Virtual 8086-mode */
		/* TODO: Nested task */
		/* TODO: #SS(0) exception */
		/* TODO: All the protection-related stuff... */
		I.eip = POP16();
		I.sreg[CS].selector = POP16();
		set_flags( POP16() );
		CHANGE_PC(I.eip);
		i386_load_segment_descriptor(CS);
		CYCLES(38);		/* TODO: Correct timing */
	} else {
		/* TODO: #SS(0) exception */
		/* TODO: #GP(0) exception */
		I.eip = POP16();
		I.sreg[CS].selector = POP16();
		set_flags( POP16() );
		CHANGE_PC(I.eip);
		i386_load_segment_descriptor(CS);
		CYCLES(22);
	}
}

static void I386OP(ja_rel16)(void)			// Opcode 0x0f 87
{
	INT16 disp = FETCH16();
	if( I.CF == 0 && I.ZF == 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jbe_rel16)(void)			// Opcode 0x0f 86
{
	INT16 disp = FETCH16();
	if( I.CF != 0 || I.ZF != 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jc_rel16)(void)			// Opcode 0x0f 82
{
	INT16 disp = FETCH16();
	if( I.CF != 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jg_rel16)(void)			// Opcode 0x0f 8f
{
	INT16 disp = FETCH16();
	if( I.ZF == 0 && (I.SF == I.OF) ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jge_rel16)(void)			// Opcode 0x0f 8d
{
	INT16 disp = FETCH16();
	if( (I.SF == I.OF) ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jl_rel16)(void)			// Opcode 0x0f 8c
{
	INT16 disp = FETCH16();
	if( (I.SF != I.OF) ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jle_rel16)(void)			// Opcode 0x0f 8e
{
	INT16 disp = FETCH16();
	if( I.ZF != 0 || (I.SF != I.OF) ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jnc_rel16)(void)			// Opcode 0x0f 83
{
	INT16 disp = FETCH16();
	if( I.CF == 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jno_rel16)(void)			// Opcode 0x0f 81
{
	INT16 disp = FETCH16();
	if( I.OF == 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jnp_rel16)(void)			// Opcode 0x0f 8b
{
	INT16 disp = FETCH16();
	if( I.PF == 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jns_rel16)(void)			// Opcode 0x0f 89
{
	INT16 disp = FETCH16();
	if( I.SF == 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jnz_rel16)(void)			// Opcode 0x0f 85
{
	INT16 disp = FETCH16();
	if( I.ZF == 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jo_rel16)(void)			// Opcode 0x0f 80
{
	INT16 disp = FETCH16();
	if( I.OF != 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jp_rel16)(void)			// Opcode 0x0f 8a
{
	INT16 disp = FETCH16();
	if( I.PF != 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(js_rel16)(void)			// Opcode 0x0f 88
{
	INT16 disp = FETCH16();
	if( I.SF != 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jz_rel16)(void)			// Opcode 0x0f 84
{
	INT16 disp = FETCH16();
	if( I.ZF != 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
	} else {
		CYCLES(3);
	}
}

static void I386OP(jcxz16)(void)			// Opcode 0xe3
{
	INT8 disp = FETCH();
	if( REG16(CX) == 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
		CYCLES(9 + 1);		/* TODO: Timing = 9 + m */
	} else {
		CYCLES(5);
	}
}

static void I386OP(jmp_rel16)(void)			// Opcode 0xe9
{
	INT16 disp = FETCH16();
	/* TODO: Segment limit */
	I.eip += disp;
	CHANGE_PC(I.eip);
	CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
}

static void I386OP(jmp_abs16)(void)			// Opcode 0xea
{
	UINT16 address = FETCH16();
	UINT16 segment = FETCH16();

	if( PROTECTED_MODE ) {
		/* TODO: #GP */
		/* TODO: access rights, etc. */
		I.eip = address;
		I.sreg[CS].selector = segment;
		i386_load_segment_descriptor(CS);
		CHANGE_PC(I.eip);
		CYCLES(27 + 1);		/* TODO: correct timing */
	} else {
		I.eip = address;
		I.sreg[CS].selector = segment;
		i386_load_segment_descriptor(CS);
		CHANGE_PC(I.eip);
		CYCLES(12 + 1);		/* TODO: Timing = 12 + m */
	}
}

static void I386OP(lea16)(void)				// Opcode 0x8d
{
	UINT8 modrm = FETCH();
	UINT32 ea = GetNonTranslatedEA(modrm);
	STORE_REG16(modrm, ea);
	CYCLES(2);
}

static void I386OP(leave16)(void)			// Opcode 0xc9
{
	REG16(SP) = REG16(BP);
	REG16(BP) = POP16();
	CYCLES(4);
}

static void I386OP(lodsw)(void)				// Opcode 0xad
{
	UINT32 eas;
	if( I.segment_prefix ) {
		eas = i386_translate( I.segment_override, I.sreg[CS].d ? REG32(ESI) : REG16(SI) );
	} else {
		eas = i386_translate( DS, I.sreg[CS].d ? REG32(ESI) : REG16(SI) );
	}
	REG16(AX) = READ16(eas);
	BUMP_SI(2);
	CYCLES(5);
}

static void I386OP(loop16)(void)			// Opcode 0xe2
{
	INT8 disp = FETCH();
	REG16(CX)--;
	if( REG16(CX) != 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
	}
	CYCLES(11 + 1);		/* TODO: Timing = 11 + m */
}

static void I386OP(loopne16)(void)			// Opcode 0xe0
{
	INT8 disp = FETCH();
	REG16(CX)--;
	if( REG16(CX) != 0 && I.ZF == 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
	}
	CYCLES(11 + 1);		/* TODO: Timing = 11 + m */
}

static void I386OP(loopz16)(void)			// Opcode 0xe1
{
	INT8 disp = FETCH();
	REG16(CX)--;
	if( REG16(CX) != 0 && I.ZF != 0 ) {
		I.eip += disp;
		CHANGE_PC(I.eip);
	}
	CYCLES(11 + 1);		/* TODO: Timing = 11 + m */
}

static void I386OP(mov_rm16_r16)(void)		// Opcode 0x89
{
	UINT16 src;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm);
		STORE_RM16(modrm, src);
		CYCLES(C_MOV_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm);
		WRITE16(ea, src);
		CYCLES(C_MOV_REG_MEM);
	}
}

static void I386OP(mov_r16_rm16)(void)		// Opcode 0x8b
{
	UINT16 src;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
		STORE_REG16(modrm, src);
		CYCLES(C_MOV_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
		STORE_REG16(modrm, src);
		CYCLES(C_MOV_MEM_REG);
	}
}

static void I386OP(mov_rm16_i16)(void)		// Opcode 0xc7
{
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 value = FETCH16();
		STORE_RM16(modrm, value);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 value = FETCH16();
		WRITE16(ea, value);
	}
	CYCLES(2);
}

static void I386OP(mov_ax_m16)(void)		// Opcode 0xa1
{
	UINT32 offset, ea;
	if( I.address_size ) {
		offset = FETCH32();
	} else {
		offset = FETCH16();
	}
	/* TODO: Not sure if this is correct... */
	if( I.segment_prefix ) {
		ea = i386_translate( I.segment_override, offset );
	} else {
		ea = i386_translate( DS, offset );
	}
	REG16(AX) = READ16(ea);
	CYCLES(4);
}

static void I386OP(mov_m16_ax)(void)		// Opcode 0xa3
{
	UINT32 offset, ea;
	if( I.address_size ) {
		offset = FETCH32();
	} else {
		offset = FETCH16();
	}
	/* TODO: Not sure if this is correct... */
	if( I.segment_prefix ) {
		ea = i386_translate( I.segment_override, offset );
	} else {
		ea = i386_translate( DS, offset );
	}
	WRITE16( ea, REG16(AX) );
	CYCLES(2);
}

static void I386OP(mov_ax_i16)(void)		// Opcode 0xb8
{
	REG16(AX) = FETCH16();
	CYCLES(2);
}

static void I386OP(mov_cx_i16)(void)		// Opcode 0xb9
{
	REG16(CX) = FETCH16();
	CYCLES(2);
}

static void I386OP(mov_dx_i16)(void)		// Opcode 0xba
{
	REG16(DX) = FETCH16();
	CYCLES(2);
}

static void I386OP(mov_bx_i16)(void)		// Opcode 0xbb
{
	REG16(BX) = FETCH16();
	CYCLES(2);
}

static void I386OP(mov_sp_i16)(void)		// Opcode 0xbc
{
	REG16(SP) = FETCH16();
	CYCLES(2);
}

static void I386OP(mov_bp_i16)(void)		// Opcode 0xbd
{
	REG16(BP) = FETCH16();
	CYCLES(2);
}

static void I386OP(mov_si_i16)(void)		// Opcode 0xbe
{
	REG16(SI) = FETCH16();
	CYCLES(2);
}

static void I386OP(mov_di_i16)(void)		// Opcode 0xbf
{
	REG16(DI) = FETCH16();
	CYCLES(2);
}

static void I386OP(movsw)(void)				// Opcode 0xa5
{
	UINT32 eas, ead;
	UINT16 v;
	if( I.segment_prefix ) {
		eas = i386_translate( I.segment_override, I.sreg[CS].d ? REG32(ESI) : REG16(SI) );
	} else {
		eas = i386_translate( DS, I.sreg[CS].d ? REG32(ESI) : REG16(SI) );
	}
	ead = i386_translate( ES, I.sreg[CS].d ? REG32(EDI) : REG16(DI) );
	v = READ16(eas);
	WRITE16(ead, v);
	BUMP_SI(2);
	BUMP_DI(2);
	CYCLES(8);
}

static void I386OP(movsx_r16_rm8)(void)		// Opcode 0x0f be
{
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		INT16 src = (INT8)LOAD_RM8(modrm);
		STORE_REG16(modrm, src);
		CYCLES(3);
	} else {
		UINT32 ea = GetEA(modrm);
		INT16 src = (INT8)READ8(ea);
		STORE_REG16(modrm, src);
		CYCLES(6);
	}
}

static void I386OP(movzx_r16_rm8)(void)		// Opcode 0x0f b6
{
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 src = (UINT8)LOAD_RM8(modrm);
		STORE_REG16(modrm, src);
		CYCLES(3);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 src = (UINT8)READ8(ea);
		STORE_REG16(modrm, src);
		CYCLES(6);
	}
}

static void I386OP(or_rm16_r16)(void)		// Opcode 0x09
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm);
		dst = LOAD_RM16(modrm);
		dst = OR16(dst, src);
		STORE_RM16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm);
		dst = READ16(ea);
		dst = OR16(dst, src);
		WRITE16(ea, dst);
		CYCLES(C_ALU_REG_MEM);
	}
}

static void I386OP(or_r16_rm16)(void)		// Opcode 0x0b
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
		dst = LOAD_REG16(modrm);
		dst = OR16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
		dst = LOAD_REG16(modrm);
		dst = OR16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_MEM_REG);
	}
}

static void I386OP(or_ax_i16)(void)			// Opcode 0x0d
{
	UINT16 src, dst;
	src = FETCH16();
	dst = REG16(AX);
	dst = OR16(dst, src);
	REG16(AX) = dst;
	CYCLES(C_ALU_I_ACC);
}

static void I386OP(out_ax_i8)(void)			// Opcode 0xe7
{
	UINT16 port = FETCH();
	UINT16 data = REG16(AX);
	WRITEPORT16(port, data);
}

static void I386OP(out_ax_dx)(void)			// Opcode 0xef
{
	UINT16 port = REG16(DX);
	UINT16 data = REG16(AX);
	WRITEPORT16(port, data);
}

static void I386OP(pop_ax)(void)			// Opcode 0x58
{
	REG16(AX) = POP16();
	CYCLES(4);
}

static void I386OP(pop_cx)(void)			// Opcode 0x59
{
	REG16(CX) = POP16();
	CYCLES(4);
}

static void I386OP(pop_dx)(void)			// Opcode 0x5a
{
	REG16(DX) = POP16();
	CYCLES(4);
}

static void I386OP(pop_bx)(void)			// Opcode 0x5b
{
	REG16(BX) = POP16();
	CYCLES(4);
}

static void I386OP(pop_sp)(void)			// Opcode 0x5c
{
	REG16(SP) = POP16();
	CYCLES(4);
}

static void I386OP(pop_bp)(void)			// Opcode 0x5d
{
	REG16(BP) = POP16();
	CYCLES(4);
}

static void I386OP(pop_si)(void)			// Opcode 0x5e
{
	REG16(SI) = POP16();
	CYCLES(4);
}

static void I386OP(pop_di)(void)			// Opcode 0x5f
{
	REG16(DI) = POP16();
	CYCLES(4);
}

static void I386OP(pop_ds16)(void)			// Opcode 0x1f
{
	I.sreg[DS].selector = POP16();
	if( PROTECTED_MODE ) {
		i386_load_segment_descriptor(DS);
		CYCLES(21);
	} else {
		CYCLES(7);
	}
}

static void I386OP(pop_es16)(void)			// Opcode 0x07
{
	I.sreg[ES].selector = POP16();
	if( PROTECTED_MODE ) {
		i386_load_segment_descriptor(ES);
		CYCLES(21);
	} else {
		CYCLES(7);
	}
}

static void I386OP(pop_fs16)(void)			// Opcode 0x0f a1
{
	I.sreg[FS].selector = POP16();
	if( PROTECTED_MODE ) {
		i386_load_segment_descriptor(FS);
		CYCLES(21);
	} else {
		CYCLES(7);
	}
}

static void I386OP(pop_gs16)(void)			// Opcode 0x0f a9
{
	I.sreg[GS].selector = POP16();
	if( PROTECTED_MODE ) {
		i386_load_segment_descriptor(GS);
		CYCLES(21);
	} else {
		CYCLES(7);
	}
}

static void I386OP(pop_ss16)(void)			// Opcode 0x17
{
	I.sreg[SS].selector = POP16();
	if( PROTECTED_MODE ) {
		i386_load_segment_descriptor(SS);
		CYCLES(21);
	} else {
		CYCLES(7);
	}
}

static void I386OP(pop_rm16)(void)			// Opcode 0x8f
{
	UINT8 modrm = FETCH();
	UINT16 value = POP16();

	if( modrm >= 0xc0 ) {
		STORE_RM16(modrm, value);
	} else {
		UINT32 ea = GetEA(modrm);
		WRITE16(ea, value);
	}
	CYCLES(5);
}

static void I386OP(popa)(void)				// Opcode 0x61
{
	REG16(DI) = POP16();
	REG16(SI) = POP16();
	REG16(BP) = POP16();
	REG16(SP) += 2;
	REG16(BX) = POP16();
	REG16(DX) = POP16();
	REG16(CX) = POP16();
	REG16(AX) = POP16();
	CYCLES(24);
}

static void I386OP(popf)(void)				// Opcode 0x9d
{
	UINT16 value = POP16();
	set_flags(value);
	CYCLES(5);
}

static void I386OP(push_ax)(void)			// Opcode 0x50
{
	PUSH16( REG16(AX) );
	CYCLES(2);
}

static void I386OP(push_cx)(void)			// Opcode 0x51
{
	PUSH16( REG16(CX) );
	CYCLES(2);
}

static void I386OP(push_dx)(void)			// Opcode 0x52
{
	PUSH16( REG16(DX) );
	CYCLES(2);
}

static void I386OP(push_bx)(void)			// Opcode 0x53
{
	PUSH16( REG16(BX) );
	CYCLES(2);
}

static void I386OP(push_sp)(void)			// Opcode 0x54
{
	PUSH16( REG16(SP) );
	CYCLES(2);
}

static void I386OP(push_bp)(void)			// Opcode 0x55
{
	PUSH16( REG16(BP) );
	CYCLES(2);
}

static void I386OP(push_si)(void)			// Opcode 0x56
{
	PUSH16( REG16(SI) );
	CYCLES(2);
}

static void I386OP(push_di)(void)			// Opcode 0x57
{
	PUSH16( REG16(DI) );
	CYCLES(2);
}

static void I386OP(push_cs16)(void)			// Opcode 0x0e
{
	PUSH16( I.sreg[CS].selector );
	CYCLES(2);
}

static void I386OP(push_ds16)(void)			// Opcode 0x1e
{
	PUSH16( I.sreg[DS].selector );
	CYCLES(2);
}

static void I386OP(push_es16)(void)			// Opcode 0x06
{
	PUSH16( I.sreg[ES].selector );
	CYCLES(2);
}

static void I386OP(push_fs16)(void)			// Opcode 0x0f a0
{
	PUSH16( I.sreg[FS].selector );
	CYCLES(2);
}

static void I386OP(push_gs16)(void)			// Opcode 0x0f a8
{
	PUSH16( I.sreg[GS].selector );
	CYCLES(2);
}

static void I386OP(push_ss16)(void)			// Opcode 0x16
{
	PUSH16( I.sreg[SS].selector );
	CYCLES(2);
}

static void I386OP(push_i16)(void)			// Opcode 0x68
{
	UINT16 value = FETCH16();
	PUSH16(value);
	CYCLES(2);
}

static void I386OP(pusha)(void)				// Opcode 0x60
{
	UINT16 temp = REG16(SP);
	PUSH16( REG16(AX) );
	PUSH16( REG16(CX) );
	PUSH16( REG16(DX) );
	PUSH16( REG16(BX) );
	PUSH16( temp );
	PUSH16( REG16(BP) );
	PUSH16( REG16(SI) );
	PUSH16( REG16(DI) );
	CYCLES(18);
}

static void I386OP(pushf)(void)				// Opcode 0x9c
{
	PUSH16( get_flags() & 0xffff );
	CYCLES(4);
}

static void I386OP(ret_near16_i16)(void)	// Opcode 0xc2
{
	INT16 disp = FETCH16();
	I.eip = POP16();
	REG16(SP) += disp;
	CHANGE_PC(I.eip);
	CYCLES(10 + 1);		/* TODO: Timing = 10 + m */
}

static void I386OP(ret_near16)(void)		// Opcode 0xc3
{
	I.eip = POP16();
	CHANGE_PC(I.eip);
	CYCLES(10 + 1);		/* TODO: Timing = 10 + m */
}

static void I386OP(sbb_rm16_r16)(void)		// Opcode 0x19
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm) + I.CF;
		dst = LOAD_RM16(modrm);
		dst = SUB16(dst, src);
		STORE_RM16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm) + I.CF;
		dst = READ16(ea);
		dst = SUB16(dst, src);
		WRITE16(ea, dst);
		CYCLES(C_ALU_REG_MEM);
	}
}

static void I386OP(sbb_r16_rm16)(void)		// Opcode 0x1b
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm) + I.CF;
		dst = LOAD_REG16(modrm);
		dst = SUB16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea) + I.CF;
		dst = LOAD_REG16(modrm);
		dst = SUB16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_MEM_REG);
	}
}

static void I386OP(sbb_ax_i16)(void)		// Opcode 0x1d
{
	UINT16 src, dst;
	src = FETCH16() + I.CF;
	dst = REG16(AX);
	dst = SUB16(dst, src);
	REG16(AX) = dst;
	CYCLES(C_ALU_I_ACC);
}

static void I386OP(scasw)(void)				// Opcode 0xaf
{
	UINT32 eas;
	UINT16 src, dst;
	eas = i386_translate( ES, I.sreg[CS].d ? REG32(EDI) : REG16(DI) );
	src = READ16(eas);
	dst = REG16(AX);
	SUB16(dst, src);
	BUMP_DI(2);
	CYCLES(8);
}

static void I386OP(shld16_i8)(void)			// Opcode 0x0f a4
{
	/* TODO: Correct flags */
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 dst = LOAD_RM16(modrm);
		UINT16 upper = LOAD_REG16(modrm);
		UINT8 shift = FETCH();
		if( shift > 31 || shift == 0 ) {

		} else if( shift > 15 ) {
			I.CF = (dst & (1 << (16-shift))) ? 1 : 0;
			dst = (upper << (shift-16)) | (upper >> (32-shift));
			SetSZPF16(dst);
		} else {
			I.CF = (dst & (1 << (16-shift))) ? 1 : 0;
			dst = (dst << shift) | (upper >> (16-shift));
			SetSZPF16(dst);
		}
		STORE_RM16(modrm, dst);
		CYCLES(3);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 dst = READ16(ea);
		UINT16 upper = LOAD_REG16(modrm);
		UINT8 shift = FETCH();
		if( shift > 31 || shift == 0 ) {

		} else if( shift > 15 ) {
			I.CF = (dst & (1 << (16-shift))) ? 1 : 0;
			dst = (upper << (shift-16)) | (upper >> (32-shift));
			SetSZPF16(dst);
		} else {
			I.CF = (dst & (1 << (16-shift))) ? 1 : 0;
			dst = (dst << shift) | (upper >> (16-shift));
			SetSZPF16(dst);
		}
		WRITE16(ea, dst);
		CYCLES(7);
	}
}

static void I386OP(shld16_cl)(void)			// Opcode 0x0f a5
{
	/* TODO: Correct flags */
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 dst = LOAD_RM16(modrm);
		UINT16 upper = LOAD_REG16(modrm);
		UINT8 shift = REG8(CL);
		if( shift > 31 || shift == 0 ) {

		} else if( shift > 15 ) {
			I.CF = (dst & (1 << (16-shift))) ? 1 : 0;
			dst = (upper << (shift-16)) | (upper >> (32-shift));
			SetSZPF16(dst);
		} else {
			I.CF = (dst & (1 << (16-shift))) ? 1 : 0;
			dst = (dst << shift) | (upper >> (16-shift));
			SetSZPF16(dst);
		}
		STORE_RM16(modrm, dst);
		CYCLES(3);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 dst = READ16(ea);
		UINT16 upper = LOAD_REG16(modrm);
		UINT8 shift = REG8(CL);
		if( shift > 31 || shift == 0 ) {

		} else if( shift > 15 ) {
			I.CF = (dst & (1 << (16-shift))) ? 1 : 0;
			dst = (upper << (shift-16)) | (upper >> (32-shift));
			SetSZPF16(dst);
		} else {
			I.CF = (dst & (1 << (16-shift))) ? 1 : 0;
			dst = (dst << shift) | (upper >> (16-shift));
			SetSZPF16(dst);
		}
		WRITE16(ea, dst);
		CYCLES(7);
	}
}

static void I386OP(shrd16_i8)(void)			// Opcode 0x0f ac
{
	/* TODO: Correct flags */
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 dst = LOAD_RM16(modrm);
		UINT16 upper = LOAD_REG16(modrm);
		UINT8 shift = FETCH();
		if( shift > 15 || shift == 0) {

		} else {
			I.CF = (dst & (1 << (shift-1))) ? 1 : 0;
			dst = (dst >> shift) | (upper << (16-shift));
			SetSZPF16(dst);
		}
		STORE_RM16(modrm, dst);
		CYCLES(3);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 dst = READ16(ea);
		UINT16 upper = LOAD_REG16(modrm);
		UINT8 shift = FETCH();
		if( shift > 15 || shift == 0) {

		} else {
			I.CF = (dst & (1 << (shift-1))) ? 1 : 0;
			dst = (dst >> shift) | (upper << (16-shift));
			SetSZPF16(dst);
		}
		WRITE16(ea, dst);
		CYCLES(7);
	}
}

static void I386OP(shrd16_cl)(void)			// Opcode 0x0f ad
{
	/* TODO: Correct flags */
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 dst = LOAD_RM16(modrm);
		UINT16 upper = LOAD_REG16(modrm);
		UINT8 shift = REG8(CL);
		if( shift > 15 || shift == 0) {

		} else {
			I.CF = (dst & (1 << (shift-1))) ? 1 : 0;
			dst = (dst >> shift) | (upper << (16-shift));
			SetSZPF16(dst);
		}
		STORE_RM16(modrm, dst);
		CYCLES(3);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 dst = READ16(ea);
		UINT16 upper = LOAD_REG16(modrm);
		UINT8 shift = REG8(CL);
		if( shift > 15 || shift == 0) {

		} else {
			I.CF = (dst & (1 << (shift-1))) ? 1 : 0;
			dst = (dst >> shift) | (upper << (16-shift));
			SetSZPF16(dst);
		}
		WRITE16(ea, dst);
		CYCLES(7);
	}
}

static void I386OP(stosw)(void)				// Opcode 0xab
{
	UINT32 ead;
	ead = i386_translate( ES, I.sreg[CS].d ? REG32(EDI) : REG16(DI) );
	WRITE16(ead, REG16(AX));
	BUMP_DI(2);
	CYCLES(5);
}

static void I386OP(sub_rm16_r16)(void)		// Opcode 0x29
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm);
		dst = LOAD_RM16(modrm);
		dst = SUB16(dst, src);
		STORE_RM16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm);
		dst = READ16(ea);
		dst = SUB16(dst, src);
		WRITE16(ea, dst);
		CYCLES(C_ALU_REG_MEM);
	}
}

static void I386OP(sub_r16_rm16)(void)		// Opcode 0x2b
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
		dst = LOAD_REG16(modrm);
		dst = SUB16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
		dst = LOAD_REG16(modrm);
		dst = SUB16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_MEM_REG);
	}
}

static void I386OP(sub_ax_i16)(void)		// Opcode 0x2d
{
	UINT16 src, dst;
	src = FETCH16();
	dst = REG16(AX);
	dst = SUB16(dst, src);
	REG16(AX) = dst;
	CYCLES(C_ALU_I_ACC);
}

static void I386OP(test_ax_i16)(void)		// Opcode 0xa9
{
	UINT16 src = FETCH16();
	UINT16 dst = REG16(AX);
	dst = src & dst;
	SetSZPF16(dst);
	I.CF = 0;
	I.OF = 0;
	CYCLES(C_ALU_I_ACC);
}

static void I386OP(test_rm16_r16)(void)		// Opcode 0x85
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm);
		dst = LOAD_RM16(modrm);
		dst = src & dst;
		SetSZPF16(dst);
		I.CF = 0;
		I.OF = 0;
		CYCLES(2);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm);
		dst = READ16(ea);
		dst = src & dst;
		SetSZPF16(dst);
		I.CF = 0;
		I.OF = 0;
		CYCLES(5);
	}
}

static void I386OP(xchg_ax_cx)(void)		// Opcode 0x91
{
	UINT16 temp;
	temp = REG16(AX);
	REG16(AX) = REG16(CX);
	REG16(CX) = temp;
	CYCLES(3);
}

static void I386OP(xchg_ax_dx)(void)		// Opcode 0x92
{
	UINT16 temp;
	temp = REG16(AX);
	REG16(AX) = REG16(DX);
	REG16(DX) = temp;
	CYCLES(3);
}

static void I386OP(xchg_ax_bx)(void)		// Opcode 0x93
{
	UINT16 temp;
	temp = REG16(AX);
	REG16(AX) = REG16(BX);
	REG16(BX) = temp;
	CYCLES(3);
}

static void I386OP(xchg_ax_sp)(void)		// Opcode 0x94
{
	UINT16 temp;
	temp = REG16(AX);
	REG16(AX) = REG16(SP);
	REG16(SP) = temp;
	CYCLES(3);
}

static void I386OP(xchg_ax_bp)(void)		// Opcode 0x95
{
	UINT16 temp;
	temp = REG16(AX);
	REG16(AX) = REG16(BP);
	REG16(BP) = temp;
	CYCLES(3);
}

static void I386OP(xchg_ax_si)(void)		// Opcode 0x96
{
	UINT16 temp;
	temp = REG16(AX);
	REG16(AX) = REG16(SI);
	REG16(SI) = temp;
	CYCLES(3);
}

static void I386OP(xchg_ax_di)(void)		// Opcode 0x97
{
	UINT16 temp;
	temp = REG16(AX);
	REG16(AX) = REG16(DI);
	REG16(DI) = temp;
	CYCLES(3);
}

static void I386OP(xchg_r16_rm16)(void)		// Opcode 0x87
{
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		UINT16 src = LOAD_RM16(modrm);
		UINT16 dst = LOAD_REG16(modrm);
		STORE_REG16(modrm, src);
		STORE_RM16(modrm, dst);
		CYCLES(3);
	} else {
		UINT32 ea = GetEA(modrm);
		UINT16 src = READ16(ea);
		UINT16 dst = LOAD_REG16(modrm);
		STORE_REG16(modrm, src);
		WRITE16(ea, dst);
		CYCLES(5);
	}
}

static void I386OP(xor_rm16_r16)(void)		// Opcode 0x31
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_REG16(modrm);
		dst = LOAD_RM16(modrm);
		dst = XOR16(dst, src);
		STORE_RM16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = LOAD_REG16(modrm);
		dst = READ16(ea);
		dst = XOR16(dst, src);
		WRITE16(ea, dst);
		CYCLES(C_ALU_REG_MEM);
	}
}

static void I386OP(xor_r16_rm16)(void)		// Opcode 0x33
{
	UINT16 src, dst;
	UINT8 modrm = FETCH();
	if( modrm >= 0xc0 ) {
		src = LOAD_RM16(modrm);
		dst = LOAD_REG16(modrm);
		dst = XOR16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_REG_REG);
	} else {
		UINT32 ea = GetEA(modrm);
		src = READ16(ea);
		dst = LOAD_REG16(modrm);
		dst = XOR16(dst, src);
		STORE_REG16(modrm, dst);
		CYCLES(C_ALU_MEM_REG);
	}
}

static void I386OP(xor_ax_i16)(void)		// Opcode 0x35
{
	UINT16 src, dst;
	src = FETCH16();
	dst = REG16(AX);
	dst = XOR16(dst, src);
	REG16(AX) = dst;
	CYCLES(C_ALU_I_ACC);
}



static void I386OP(group81_16)(void)		// Opcode 0x81
{
	UINT32 ea;
	UINT16 src, dst;
	UINT8 modrm = FETCH();

	switch( (modrm >> 3) & 0x7 )
	{
		case 0:		// ADD Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = FETCH16();
				dst = ADD16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = FETCH16();
				dst = ADD16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 1:		// OR Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = FETCH16();
				dst = OR16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = FETCH16();
				dst = OR16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 2:		// ADC Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = FETCH16();
				src = ADD16(src, I.CF);
				dst = ADD16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = FETCH16();
				src = ADD16(src, I.CF);
				dst = ADD16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 3:		// SBB Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = FETCH16() + I.CF;
				dst = SUB16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = FETCH16() + I.CF;
				dst = SUB16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 4:		// AND Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = FETCH16();
				dst = AND16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = FETCH16();
				dst = AND16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 5:		// SUB Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = FETCH16();
				dst = SUB16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = FETCH16();
				dst = SUB16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 6:		// XOR Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = FETCH16();
				dst = XOR16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = FETCH16();
				dst = XOR16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 7:		// CMP Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = FETCH16();
				SUB16(dst, src);
				CYCLES(C_CMP_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = FETCH16();
				SUB16(dst, src);
				CYCLES(C_CMP_REG_MEM);
			}
			break;
	}
}

static void I386OP(group83_16)(void)		// Opcode 0x83
{
	UINT32 ea;
	UINT16 src, dst;
	UINT8 modrm = FETCH();

	switch( (modrm >> 3) & 0x7 )
	{
		case 0:		// ADD Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = ADD16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = ADD16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 1:		// OR Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = OR16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = OR16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 2:		// ADC Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = (UINT16)(INT16)(INT8)FETCH();
				src = ADD16(src, I.CF);
				dst = ADD16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = (UINT16)(INT16)(INT8)FETCH();
				src = ADD16(src, I.CF);
				dst = ADD16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 3:		// SBB Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = ((UINT16)(INT16)(INT8)FETCH()) + I.CF;
				dst = SUB16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = ((UINT16)(INT16)(INT8)FETCH()) + I.CF;
				dst = SUB16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 4:		// AND Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = AND16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = AND16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 5:		// SUB Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = SUB16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = SUB16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 6:		// XOR Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = XOR16(dst, src);
				STORE_RM16(modrm, dst);
				CYCLES(C_ALU_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = (UINT16)(INT16)(INT8)FETCH();
				dst = XOR16(dst, src);
				WRITE16(ea, dst);
				CYCLES(C_ALU_REG_MEM);
			}
			break;
		case 7:		// CMP Rm16, i16
			if( modrm >= 0xc0 ) {
				dst = LOAD_RM16(modrm);
				src = (UINT16)(INT16)(INT8)FETCH();
				SUB16(dst, src);
				CYCLES(C_CMP_REG_REG);
			} else {
				ea = GetEA(modrm);
				dst = READ16(ea);
				src = (UINT16)(INT16)(INT8)FETCH();
				SUB16(dst, src);
				CYCLES(C_CMP_REG_MEM);
			}
			break;
	}
}

static void I386OP(groupC1_16)(void)		// Opcode 0xc1
{
	UINT16 dst;
	UINT8 modrm = FETCH();
	UINT8 shift;

	if( modrm >= 0xc0 ) {
		dst = LOAD_RM16(modrm);
		shift = FETCH() & 0x1f;
		dst = i386_shift_rotate16(modrm, dst, shift);
		STORE_RM16(modrm, dst);
	} else {
		UINT32 ea = GetEA(modrm);
		dst = READ16(ea);
		shift = FETCH() & 0x1f;
		dst = i386_shift_rotate16(modrm, dst, shift);
		WRITE16(ea, dst);
	}
}

static void I386OP(groupD1_16)(void)		// Opcode 0xd1
{
	UINT16 dst;
	UINT8 modrm = FETCH();

	if( modrm >= 0xc0 ) {
		dst = LOAD_RM16(modrm);
		dst = i386_shift_rotate16(modrm, dst, 1);
		STORE_RM16(modrm, dst);
	} else {
		UINT32 ea = GetEA(modrm);
		dst = READ16(ea);
		dst = i386_shift_rotate16(modrm, dst, 1);
		WRITE16(ea, dst);
	}
}

static void I386OP(groupD3_16)(void)		// Opcode 0xd3
{
	UINT16 dst;
	UINT8 modrm = FETCH();

	if( modrm >= 0xc0 ) {
		dst = LOAD_RM16(modrm);
		dst = i386_shift_rotate16(modrm, dst, REG8(CL));
		STORE_RM16(modrm, dst);
	} else {
		UINT32 ea = GetEA(modrm);
		dst = READ16(ea);
		dst = i386_shift_rotate16(modrm, dst, REG8(CL));
		WRITE16(ea, dst);
	}
}

static void I386OP(groupF7_16)(void)		// Opcode 0xf7
{
	UINT8 modrm = FETCH();

	switch( (modrm >> 3) & 0x7 )
	{
		case 0:			/* TEST Rm16, i16 */
			if( modrm >= 0xc0 ) {
				UINT16 dst = LOAD_RM16(modrm);
				UINT16 src = FETCH16();
				dst &= src;
				I.CF = I.OF = I.AF = 0;
				SetSZPF16(dst);
				CYCLES(2);
			} else {
				UINT32 ea = GetEA(modrm);
				UINT16 dst = READ16(ea);
				UINT16 src = FETCH16();
				dst &= src;
				I.CF = I.OF = I.AF = 0;
				SetSZPF16(dst);
				CYCLES(5);
			}
			break;
		case 2:			/* NOT Rm16 */
			if( modrm >= 0xc0 ) {
				UINT16 dst = LOAD_RM16(modrm);
				dst = ~dst;
				STORE_RM16(modrm, dst);
				CYCLES(2);
			} else {
				UINT32 ea = GetEA(modrm);
				UINT16 dst = READ16(ea);
				dst = ~dst;
				WRITE16(ea, dst);
				CYCLES(6);
			}
			break;
		case 3:			/* NEG Rm16 */
			if( modrm >= 0xc0 ) {
				UINT16 dst = LOAD_RM16(modrm);
				dst = SUB16( 0, dst );
				STORE_RM16(modrm, dst);
				CYCLES(2);
			} else {
				UINT32 ea = GetEA(modrm);
				UINT16 dst = READ16(ea);
				dst = SUB16( 0, dst );
				WRITE16(ea, dst);
				CYCLES(6);
			}
			break;
		case 4:			/* MUL AX, Rm16 */
			{
				UINT32 result;
				UINT16 src, dst;
				if( modrm >= 0xc0 ) {
					src = LOAD_RM16(modrm);
					CYCLES(12);		/* TODO: Correct multiply timing */
				} else {
					UINT32 ea = GetEA(modrm);
					src = READ16(ea);
					CYCLES(15);		/* TODO: Correct multiply timing */
				}

				dst = REG16(AX);
				result = (UINT32)src * (UINT32)dst;
				REG16(DX) = (UINT16)(result >> 16);
				REG16(AX) = (UINT16)result;

				I.CF = I.OF = (REG16(DX) != 0);
			}
			break;
		case 5:			/* IMUL AX, Rm16 */
			{
				INT32 result;
				INT32 src, dst;
				if( modrm >= 0xc0 ) {
					src = (INT32)(INT16)LOAD_RM16(modrm);
					CYCLES(12);		/* TODO: Correct multiply timing */
				} else {
					UINT32 ea = GetEA(modrm);
					src = (INT32)(INT16)READ16(ea);
					CYCLES(15);		/* TODO: Correct multiply timing */
				}

				dst = (INT32)(INT16)REG16(AX);
				result = src * dst;

				REG16(DX) = (UINT16)(result >> 16);
				REG16(AX) = (UINT16)result;

				I.CF = I.OF = !(result == (INT32)(INT16)result);
			}
			break;
		case 6:			/* DIV AX, Rm16 */
			{
				UINT32 quotient, remainder, result;
				UINT16 src;
				if( modrm >= 0xc0 ) {
					src = LOAD_RM16(modrm);
					CYCLES(22);
				} else {
					UINT32 ea = GetEA(modrm);
					src = READ16(ea);
					CYCLES(25);
				}

				quotient = ((UINT32)(REG16(DX)) << 16) | (UINT32)(REG16(AX));
				if( src ) {
					remainder = quotient % (UINT32)src;
					result = quotient / (UINT32)src;
					if( result > 0xffff ) {
						/* TODO: Divide error */
					} else {
						REG16(DX) = (UINT16)remainder;
						REG16(AX) = (UINT16)result;
					}
				} else {
					/* TODO: Divide by zero */
				}
			}
			break;
		case 7:			/* IDIV EAX, Rm32 */
			{
				INT32 quotient, remainder, result;
				UINT16 src;
				if( modrm >= 0xc0 ) {
					src = LOAD_RM16(modrm);
					CYCLES(27);
				} else {
					UINT32 ea = GetEA(modrm);
					src = READ16(ea);
					CYCLES(30);
				}

				quotient = (((INT32)REG16(DX)) << 16) | ((UINT32)REG16(AX));
				if( src ) {
					remainder = quotient % (INT32)(INT16)src;
					result = quotient / (INT32)(INT16)src;
					if( result > 0xffff ) {
						/* TODO: Divide error */
					} else {
						REG16(DX) = (UINT16)remainder;
						REG16(AX) = (UINT16)result;
					}
				} else {
					/* TODO: Divide by zero */
				}
			}
			break;
	}
}

static void I386OP(groupFF_16)(void)		// Opcode 0xff
{
	UINT8 modrm = FETCH();

	switch( (modrm >> 3) & 0x7 )
	{
		case 0:			/* INC Rm16 */
			if( modrm >= 0xc0 ) {
				UINT16 dst = LOAD_RM16(modrm);
				dst = INC16(dst);
				STORE_RM16(modrm, dst);
				CYCLES(2);
			} else {
				UINT32 ea = GetEA(modrm);
				UINT16 dst = READ16(ea);
				dst = INC16(dst);
				WRITE16(ea, dst);
				CYCLES(6);
			}
			break;
		case 1:			/* DEC Rm16 */
			if( modrm >= 0xc0 ) {
				UINT16 dst = LOAD_RM16(modrm);
				dst = DEC16(dst);
				STORE_RM16(modrm, dst);
				CYCLES(2);
			} else {
				UINT32 ea = GetEA(modrm);
				UINT16 dst = READ16(ea);
				dst = DEC16(dst);
				WRITE16(ea, dst);
				CYCLES(6);
			}
			break;
		case 2:			/* CALL Rm16 */
			{
				UINT16 address;
				if( modrm >= 0xc0 ) {
					address = LOAD_RM16(modrm);
					CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
				} else {
					UINT32 ea = GetEA(modrm);
					address = READ16(ea);
					CYCLES(10 + 1);		/* TODO: Timing = 10 + m */
				}
				PUSH16( I.eip );
				I.eip = address;
				CHANGE_PC(I.eip);
			}
			break;
		case 3:			/* CALL FAR Rm16 */
			{
				UINT16 address, selector;
				if( modrm >= 0xc0 ) {
					osd_die("NYI");
				} else {
					UINT32 ea = GetEA(modrm);
					address = READ16(ea + 0);
					selector = READ16(ea + 2);
					CYCLES(10 + 1);		/* TODO: Timing = 10 + m */
				}
				PUSH16( I.sreg[CS].selector );
				PUSH16( I.eip );
				I.sreg[CS].selector = selector;
				i386_load_segment_descriptor( CS );
				I.eip = address;
				I.performed_intersegment_jump = 1;
				CHANGE_PC(I.eip);
			}
			break;
		case 4:			/* JMP Rm16 */
			{
				UINT16 address;
				if( modrm >= 0xc0 ) {
					address = LOAD_RM16(modrm);
					CYCLES(7 + 1);		/* TODO: Timing = 7 + m */
				} else {
					UINT32 ea = GetEA(modrm);
					address = READ16(ea);
					CYCLES(10 + 1);		/* TODO: Timing = 10 + m */
				}
				I.eip = address;
				CHANGE_PC(I.eip);
			}
			break;
		case 5:			/* JMP FAR Rm16 */
			{
				UINT16 address, selector;
				if( modrm >= 0xc0 ) {
					osd_die("NYI");
				} else {
					UINT32 ea = GetEA(modrm);
					address = READ16(ea + 0);
					selector = READ16(ea + 2);
					CYCLES(10 + 1);		/* TODO: Timing = 10 + m */
				}
				I.sreg[CS].selector = selector;
				i386_load_segment_descriptor( CS );
				I.eip = address;
				I.performed_intersegment_jump = 1;
				CHANGE_PC(I.eip);
			}
			break;
		case 6:			/* PUSH Rm16 */
			{
				UINT16 value;
				if( modrm >= 0xc0 ) {
					value = LOAD_RM16(modrm);
				} else {
					UINT32 ea = GetEA(modrm);
					value = READ16(ea);
				}
				PUSH16(value);
				CYCLES(5);
			}
			break;
		case 7:
			I386OP(invalid)();
			break;
		default:
			osd_die("i386: groupFF_16 /%d unimplemented\n", (modrm >> 3) & 0x7);
			break;
	}
}

static void I386OP(group0F00_16)(void)			// Opcode 0x0f 00
{
	UINT32 address, ea;
	UINT8 modrm = FETCH();

	switch( (modrm >> 3) & 0x7 )
	{
		case 2:			/* LLDT */
			if ( PROTECTED_MODE && !V8086_MODE )
			{
				if( modrm >= 0xc0 ) {
					address = LOAD_RM16(modrm);
					ea = i386_translate( CS, address );
				} else {
					ea = GetEA(modrm);
				}
				I.ldtr.segment = READ16(ea);
			}
			else
			{
				i386_trap(6);
			}
			break;

		case 3:			/* LTR */
			if ( PROTECTED_MODE && !V8086_MODE )
			{
				if( modrm >= 0xc0 ) {
					address = LOAD_RM16(modrm);
					ea = i386_translate( CS, address );
				} else {
					ea = GetEA(modrm);
				}
				I.task.segment = READ16(ea);
			}
			else
			{
				i386_trap(6);
			}
			break;

		default:
			osd_die("i386: group0F00_16 /%d unimplemented\n", (modrm >> 3) & 0x7);
			break;
	}
}

static void I386OP(group0F01_16)(void)		// Opcode 0x0f 01
{
	UINT8 modrm = FETCH();
	UINT16 address;
	UINT32 ea;

	switch( (modrm >> 3) & 0x7 )
	{
		case 0:			/* SGDT */
			{
				if( modrm >= 0xc0 ) {
					address = LOAD_RM16(modrm);
					ea = i386_translate( CS, address );
				} else {
					ea = GetEA(modrm);
				}
				WRITE16(ea, I.gdtr.limit);
				WRITE32(ea + 2, I.gdtr.base & 0xffffff);
				CYCLES(9);
				break;
			}
		case 2:			/* LGDT */
			{
				if( modrm >= 0xc0 ) {
					address = LOAD_RM16(modrm);
					ea = i386_translate( CS, address );
				} else {
					ea = GetEA(modrm);
				}
				I.gdtr.limit = READ16(ea);
				I.gdtr.base = READ32(ea + 2) & 0xffffff;
				CYCLES(11);
				break;
			}
		case 3:			/* LIDT */
			{
				if( modrm >= 0xc0 ) {
					address = LOAD_RM16(modrm);
					ea = i386_translate( CS, address );
				} else {
					ea = GetEA(modrm);
				}
				I.idtr.limit = READ16(ea);
				I.idtr.base = READ32(ea + 2) & 0xffffff;
				CYCLES(11);
				break;
			}
		case 4:			/* SMSW */
			{
				if( modrm >= 0xc0 ) {
					STORE_RM16(modrm, I.cr[0]);
				} else {
					UINT32 ea = GetEA(modrm);
					WRITE16(ea, I.cr[0]);
				}
				CYCLES(0);	// TODO: Specify cycle count
				break;
			}
		case 6:			/* LMSW */
			{
				// TODO: Check for protection fault
				UINT8 b;
				if( modrm >= 0xc0 ) {
					b = LOAD_RM8(modrm);
				} else {
					ea = GetEA(modrm);
				b = READ8(ea);
				}
				I.cr[0] &= ~0x03;
				I.cr[0] |= b & 0x03;
				break;
			}
		default:
			osd_die("i386: unimplemented opcode 0x0f 01 /%d at %08X\n", (modrm >> 3) & 0x7, I.eip - 2);
			break;
	}
}

static void I386OP(group0FBA_16)(void)		// Opcode 0x0f ba
{
	UINT8 modrm = FETCH();

	switch( (modrm >> 3) & 0x7 )
	{
		case 4:			/* BT Rm16, i8 */
			if( modrm >= 0xc0 ) {
				UINT16 dst = LOAD_RM16(modrm);
				UINT8 bit = FETCH();

				if( dst & (1 << bit) )
					I.CF = 1;
				else
					I.CF = 0;

				CYCLES(3);
			} else {
				UINT32 ea = GetEA(modrm);
				UINT16 dst = READ16(ea);
				UINT8 bit = FETCH();

				if( dst & (1 << bit) )
					I.CF = 1;
				else
					I.CF = 0;

				CYCLES(6);
			}
			break;
		case 5:			/* BTS Rm16, i8 */
			if( modrm >= 0xc0 ) {
				UINT16 dst = LOAD_RM16(modrm);
				UINT8 bit = FETCH();

				if( dst & (1 << bit) )
					I.CF = 1;
				else
					I.CF = 0;
				dst |= (1 << bit);

				STORE_RM16(modrm, dst);
				CYCLES(6);
			} else {
				UINT32 ea = GetEA(modrm);
				UINT16 dst = READ16(ea);
				UINT8 bit = FETCH();

				if( dst & (1 << bit) )
					I.CF = 1;
				else
					I.CF = 0;
				dst |= (1 << bit);

				WRITE16(ea, dst);
				CYCLES(8);
			}
			break;
		case 6:			/* BTR Rm16, i8 */
			if( modrm >= 0xc0 ) {
				UINT16 dst = LOAD_RM16(modrm);
				UINT8 bit = FETCH();

				if( dst & (1 << bit) )
					I.CF = 1;
				else
					I.CF = 0;
				dst &= ~(1 << bit);

				STORE_RM16(modrm, dst);
				CYCLES(6);
			} else {
				UINT32 ea = GetEA(modrm);
				UINT16 dst = READ16(ea);
				UINT8 bit = FETCH();

				if( dst & (1 << bit) )
					I.CF = 1;
				else
					I.CF = 0;
				dst &= ~(1 << bit);

				WRITE16(ea, dst);
				CYCLES(8);
			}
			break;
		case 7:			/* BTC Rm16, i8 */
			if( modrm >= 0xc0 ) {
				UINT16 dst = LOAD_RM16(modrm);
				UINT8 bit = FETCH();

				if( dst & (1 << bit) )
					I.CF = 1;
				else
					I.CF = 0;
				dst ^= (1 << bit);

				STORE_RM16(modrm, dst);
				CYCLES(6);
			} else {
				UINT32 ea = GetEA(modrm);
				UINT16 dst = READ16(ea);
				UINT8 bit = FETCH();

				if( dst & (1 << bit) )
					I.CF = 1;
				else
					I.CF = 0;
				dst ^= (1 << bit);

				WRITE16(ea, dst);
				CYCLES(8);
			}
			break;
		default:
			osd_die("i386: group0FBA_16 /%d unknown\n", (modrm >> 3) & 0x7);
			break;
	}
}

static void I386OP(bound_r16_m16_m16)(void)	// Opcode 0x62
{
	UINT8 modrm;
	INT16 val, low, high;

	modrm = FETCH();

	if (modrm >= 0xc0)
	{
		low = high = LOAD_RM16(modrm);
	}
	else
	{
		UINT32 ea = GetEA(modrm);
		low = READ16(ea + 0);
		high = READ16(ea + 2);
	}
	val = LOAD_REG16(modrm);

	if ((val < low) || (val > high))
		i386_trap(5);

	CYCLES(1);	// TODO: Find out correct cycle count
}

static void I386OP(retf16)(void)			// Opcode 0xcb
{
	I.eip = POP16();
	I.sreg[CS].selector = POP16();
	i386_load_segment_descriptor( CS );
	CHANGE_PC(I.eip);

	CYCLES(1);	// TODO: deduct proper cycle count
}

static void I386OP(retf_i16)(void)			// Opcode 0xca
{
	UINT16 count = FETCH16();

	I.eip = POP16();
	I.sreg[CS].selector = POP16();
	CHANGE_PC(I.eip);
	i386_load_segment_descriptor( CS );

	REG16(SP) += count;
	CYCLES(1);	// TODO: deduct proper cycle count
}

static void I386OP(xlat16)(void)			// Opcode 0xd7
{
	UINT32 ea;
	if( I.segment_prefix ) {
		ea = i386_translate( I.segment_override, REG16(BX) + REG8(AL) );
	} else {
		ea = i386_translate( DS, REG16(BX) + REG8(AL) );
	}
	REG8(AL) = READ8(ea);
}

static void I386OP(load_far_pointer16)(int s)
{
	UINT8 modrm = FETCH();

	if( modrm >= 0xc0 ) {
		osd_die("NYI");
	} else {
		UINT32 ea = GetEA(modrm);
		STORE_REG16(modrm, READ16(ea + 0));
		I.sreg[s].selector = READ16(ea + 2);
		i386_load_segment_descriptor( s );
	}

	CYCLES(1);	// TODO: Figure out exact cycle count
}

static void I386OP(lds16)(void)				// Opcode 0xc5
{
	I386OP(load_far_pointer16)(DS);
}

static void I386OP(lss16)(void)				// Opcode 0x0f 0xb2
{
	I386OP(load_far_pointer16)(SS);
}

static void I386OP(les16)(void)				// Opcode 0xc4
{
	I386OP(load_far_pointer16)(ES);
}

static void I386OP(lfs16)(void)				// Opcode 0x0f 0xb4
{
	I386OP(load_far_pointer16)(FS);
}

static void I386OP(lgs16)(void)				// Opcode 0x0f 0xb5
{
	I386OP(load_far_pointer16)(GS);
}

