+++ /dev/null
-// license:BSD-3-Clause
-// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
-#include "./i386_opdef.h"
-#include "./i386ops.h"
-
-/* seems to be defined on mingw-gcc */
-#undef i386
-
-#define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;}
-#define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;}
-
-UINT32 I386_OPS_BASE::I386OP(shift_rotate32)( UINT8 modrm, UINT32 value, UINT8 shift)
-{
- UINT32 dst, src;
- dst = value;
- src = value;
-
- if( shift == 0 ) {
- CYCLES_RM(modrm, 3, 7);
- } else if( shift == 1 ) {
- switch( (modrm >> 3) & 0x7 )
- {
- case 0: /* ROL rm32, 1 */
- cpustate->CF = (src & 0x80000000) ? 1 : 0;
- dst = (src << 1) + cpustate->CF;
- cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- case 1: /* ROR rm32, 1 */
- cpustate->CF = (src & 0x1) ? 1 : 0;
- dst = (cpustate->CF << 31) | (src >> 1);
- cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- case 2: /* RCL rm32, 1 */
- dst = (src << 1) + cpustate->CF;
- cpustate->CF = (src & 0x80000000) ? 1 : 0;
- cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
- CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
- break;
- case 3: /* RCR rm32, 1 */
- dst = (cpustate->CF << 31) | (src >> 1);
- cpustate->CF = src & 0x1;
- cpustate->OF = ((src ^ dst) & 0x80000000) ? 1 : 0;
- CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
- break;
- case 4: /* SHL/SAL rm32, 1 */
- case 6:
- dst = src << 1;
- cpustate->CF = (src & 0x80000000) ? 1 : 0;
- cpustate->OF = (((cpustate->CF << 31) ^ dst) & 0x80000000) ? 1 : 0;
- SetSZPF32(dst);
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- case 5: /* SHR rm32, 1 */
- dst = src >> 1;
- cpustate->CF = src & 0x1;
- cpustate->OF = (src & 0x80000000) ? 1 : 0;
- SetSZPF32(dst);
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- case 7: /* SAR rm32, 1 */
- dst = (INT32)(src) >> 1;
- cpustate->CF = src & 0x1;
- cpustate->OF = 0;
- SetSZPF32(dst);
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- }
-
- } else {
- shift &= 31;
- switch( (modrm >> 3) & 0x7 )
- {
- case 0: /* ROL rm32, i8 */
- dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) |
- ((src & ((UINT32)0xffffffff << (32-shift))) >> (32-shift));
- cpustate->CF = dst & 0x1;
- cpustate->OF = (dst & 1) ^ (dst >> 31);
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- case 1: /* ROR rm32, i8 */
- dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) |
- ((src & ((UINT32)0xffffffff >> (32-shift))) << (32-shift));
- cpustate->CF = (dst >> 31) & 0x1;
- cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- case 2: /* RCL rm32, i8 */
- dst = ((src & ((UINT32)0xffffffff >> shift)) << shift) |
- ((src & ((UINT32)0xffffffff << (33-shift))) >> (33-shift)) |
- (cpustate->CF << (shift-1));
- cpustate->CF = (src >> (32-shift)) & 0x1;
- cpustate->OF = cpustate->CF ^ ((dst >> 31) & 1);
- CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
- break;
- case 3: /* RCR rm32, i8 */
- dst = ((src & ((UINT32)0xffffffff << shift)) >> shift) |
- ((src & ((UINT32)0xffffffff >> (32-shift))) << (33-shift)) |
- (cpustate->CF << (32-shift));
- cpustate->CF = (src >> (shift-1)) & 0x1;
- cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
- CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
- break;
- case 4: /* SHL/SAL rm32, i8 */
- case 6:
- dst = src << shift;
- cpustate->CF = (src & (1 << (32-shift))) ? 1 : 0;
- SetSZPF32(dst);
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- case 5: /* SHR rm32, i8 */
- dst = src >> shift;
- cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
- SetSZPF32(dst);
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- case 7: /* SAR rm32, i8 */
- dst = (INT32)src >> shift;
- cpustate->CF = (src & (1 << (shift-1))) ? 1 : 0;
- SetSZPF32(dst);
- CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
- break;
- }
-
- }
- return dst;
-}
-
-void I386_OPS_BASE::I386OP(adc_rm32_r32)() // Opcode 0x11
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- dst = LOAD_RM32(modrm);
- dst = ADC32( dst, src, cpustate->CF);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1, 4);
- src = LOAD_REG32(modrm);
- dst = READ32(ea);
- dst = ADC32( dst, src, cpustate->CF);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(adc_r32_rm32)() // Opcode 0x13
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- dst = LOAD_REG32(modrm);
- dst = ADC32( dst, src, cpustate->CF);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = READ32(ea);
- dst = LOAD_REG32(modrm);
- dst = ADC32( dst, src, cpustate->CF);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(adc_eax_i32)() // Opcode 0x15
-{
- UINT32 src, dst;
- src = FETCH32();
- dst = REG32(EAX);
- dst = ADC32( dst, src, cpustate->CF);
- REG32(EAX) = dst;
- CYCLES(CYCLES_ALU_IMM_ACC);
-}
-
-void I386_OPS_BASE::I386OP(add_rm32_r32)() // Opcode 0x01
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- dst = LOAD_RM32(modrm);
- dst = ADD32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1, 4);
- src = LOAD_REG32(modrm);
- dst = READ32(ea);
- dst = ADD32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(add_r32_rm32)() // Opcode 0x03
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- dst = LOAD_REG32(modrm);
- dst = ADD32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = READ32(ea);
- dst = LOAD_REG32(modrm);
- dst = ADD32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(add_eax_i32)() // Opcode 0x05
-{
- UINT32 src, dst;
- src = FETCH32();
- dst = REG32(EAX);
- dst = ADD32(dst, src);
- REG32(EAX) = dst;
- CYCLES(CYCLES_ALU_IMM_ACC);
-}
-
-void I386_OPS_BASE::I386OP(and_rm32_r32)() // Opcode 0x21
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- dst = LOAD_RM32(modrm);
- dst = AND32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1, 4);
- src = LOAD_REG32(modrm);
- dst = READ32(ea);
- dst = AND32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(and_r32_rm32)() // Opcode 0x23
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- dst = LOAD_REG32(modrm);
- dst = AND32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = READ32(ea);
- dst = LOAD_REG32(modrm);
- dst = AND32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(and_eax_i32)() // Opcode 0x25
-{
- UINT32 src, dst;
- src = FETCH32();
- dst = REG32(EAX);
- dst = AND32(dst, src);
- REG32(EAX) = dst;
- CYCLES(CYCLES_ALU_IMM_ACC);
-}
-
-void I386_OPS_BASE::I386OP(bsf_r32_rm32)() // Opcode 0x0f bc
-{
- UINT32 src, dst, temp;
- UINT8 modrm = FETCH();
-
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = READ32(ea);
- }
-
- dst = 0;
-
- if( src == 0 ) {
- cpustate->ZF = 1;
- } else {
- cpustate->ZF = 0;
- temp = 0;
- while( (src & (1 << temp)) == 0 ) {
- temp++;
- dst = temp;
- CYCLES(CYCLES_BSF);
- }
- STORE_REG32(modrm, dst);
- }
- CYCLES(CYCLES_BSF_BASE);
-}
-
-void I386_OPS_BASE::I386OP(bsr_r32_rm32)() // Opcode 0x0f bd
-{
- UINT32 src, dst, temp;
- UINT8 modrm = FETCH();
-
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = READ32(ea);
- }
-
- dst = 0;
-
- if( src == 0 ) {
- cpustate->ZF = 1;
- } else {
- cpustate->ZF = 0;
- dst = temp = 31;
- while( (src & (1U << temp)) == 0 ) {
- temp--;
- dst = temp;
- CYCLES(CYCLES_BSR);
- }
- STORE_REG32(modrm, dst);
- }
- CYCLES(CYCLES_BSR_BASE);
-}
-
-void I386_OPS_BASE::I386OP(bt_rm32_r32)() // Opcode 0x0f a3
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT32 bit = LOAD_REG32(modrm);
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
-
- CYCLES(CYCLES_BT_REG_REG);
- } else {
- UINT8 segment;
- UINT32 ea = GetNonTranslatedEA(modrm,&segment);
- UINT32 bit = LOAD_REG32(modrm);
- ea += 4*(bit/32);
- ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),0,4);
- bit %= 32;
- UINT32 dst = READ32(ea);
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
-
- CYCLES(CYCLES_BT_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(btc_rm32_r32)() // Opcode 0x0f bb
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT32 bit = LOAD_REG32(modrm);
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst ^= (1 << bit);
-
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_BTC_REG_REG);
- } else {
- UINT8 segment;
- UINT32 ea = GetNonTranslatedEA(modrm,&segment);
- UINT32 bit = LOAD_REG32(modrm);
- ea += 4*(bit/32);
- ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4);
- bit %= 32;
- UINT32 dst = READ32(ea);
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst ^= (1 << bit);
-
- WRITE32(ea, dst);
- CYCLES(CYCLES_BTC_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(btr_rm32_r32)() // Opcode 0x0f b3
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT32 bit = LOAD_REG32(modrm);
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst &= ~(1 << bit);
-
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_BTR_REG_REG);
- } else {
- UINT8 segment;
- UINT32 ea = GetNonTranslatedEA(modrm,&segment);
- UINT32 bit = LOAD_REG32(modrm);
- ea += 4*(bit/32);
- ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4);
- bit %= 32;
- UINT32 dst = READ32(ea);
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst &= ~(1 << bit);
-
- WRITE32(ea, dst);
- CYCLES(CYCLES_BTR_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(bts_rm32_r32)() // Opcode 0x0f ab
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT32 bit = LOAD_REG32(modrm);
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst |= (1 << bit);
-
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_BTS_REG_REG);
- } else {
- UINT8 segment;
- UINT32 ea = GetNonTranslatedEA(modrm,&segment);
- UINT32 bit = LOAD_REG32(modrm);
- ea += 4*(bit/32);
- ea = i386_translate(segment,(cpustate->address_size)?ea:(ea&0xffff),1,4);
- bit %= 32;
- UINT32 dst = READ32(ea);
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst |= (1 << bit);
-
- WRITE32(ea, dst);
- CYCLES(CYCLES_BTS_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(call_abs32)() // Opcode 0x9a
-{
- UINT32 offset = FETCH32();
- UINT16 ptr = FETCH16();
-
- if(PROTECTED_MODE && !V8086_MODE)
- {
- i386_protected_mode_call(ptr,offset,0,1);
- }
- else
- {
- PUSH32SEG( cpustate->sreg[CS].selector );
- PUSH32( cpustate->eip );
- cpustate->sreg[CS].selector = ptr;
- cpustate->performed_intersegment_jump = 1;
- cpustate->eip = offset;
- i386_load_segment_descriptor(CS);
- }
- CYCLES(CYCLES_CALL_INTERSEG);
- CHANGE_PC(cpustate->eip);
-}
-
-void I386_OPS_BASE::I386OP(call_rel32)() // Opcode 0xe8
-{
- INT32 disp = FETCH32();
- PUSH32( cpustate->eip );
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */
-}
-
-void I386_OPS_BASE::I386OP(cdq)() // Opcode 0x99
-{
- if( REG32(EAX) & 0x80000000 ) {
- REG32(EDX) = 0xffffffff;
- } else {
- REG32(EDX) = 0x00000000;
- }
- CYCLES(CYCLES_CWD);
-}
-
-void I386_OPS_BASE::I386OP(cmp_rm32_r32)() // Opcode 0x39
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- dst = LOAD_RM32(modrm);
- SUB32(dst, src);
- CYCLES(CYCLES_CMP_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = LOAD_REG32(modrm);
- dst = READ32(ea);
- SUB32(dst, src);
- CYCLES(CYCLES_CMP_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(cmp_r32_rm32)() // Opcode 0x3b
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- dst = LOAD_REG32(modrm);
- SUB32(dst, src);
- CYCLES(CYCLES_CMP_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = READ32(ea);
- dst = LOAD_REG32(modrm);
- SUB32(dst, src);
- CYCLES(CYCLES_CMP_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(cmp_eax_i32)() // Opcode 0x3d
-{
- UINT32 src, dst;
- src = FETCH32();
- dst = REG32(EAX);
- SUB32(dst, src);
- CYCLES(CYCLES_CMP_IMM_ACC);
-}
-
-void I386_OPS_BASE::I386OP(cmpsd)() // Opcode 0xa7
-{
- UINT32 eas, ead, src, dst;
- if( cpustate->segment_prefix ) {
- eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
- } else {
- eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
- }
- ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0,4 );
- src = READ32(eas);
- dst = READ32(ead);
- SUB32(src,dst);
- BUMP_SI(4);
- BUMP_DI(4);
- CYCLES(CYCLES_CMPS);
-}
-
-void I386_OPS_BASE::I386OP(cwde)() // Opcode 0x98
-{
- REG32(EAX) = (INT32)((INT16)REG16(AX));
- CYCLES(CYCLES_CBW);
-}
-
-void I386_OPS_BASE::I386OP(dec_eax)() // Opcode 0x48
-{
- REG32(EAX) = DEC32( REG32(EAX) );
- CYCLES(CYCLES_DEC_REG);
-}
-
-void I386_OPS_BASE::I386OP(dec_ecx)() // Opcode 0x49
-{
- REG32(ECX) = DEC32( REG32(ECX) );
- CYCLES(CYCLES_DEC_REG);
-}
-
-void I386_OPS_BASE::I386OP(dec_edx)() // Opcode 0x4a
-{
- REG32(EDX) = DEC32( REG32(EDX) );
- CYCLES(CYCLES_DEC_REG);
-}
-
-void I386_OPS_BASE::I386OP(dec_ebx)() // Opcode 0x4b
-{
- REG32(EBX) = DEC32( REG32(EBX) );
- CYCLES(CYCLES_DEC_REG);
-}
-
-void I386_OPS_BASE::I386OP(dec_esp)() // Opcode 0x4c
-{
- REG32(ESP) = DEC32( REG32(ESP) );
- CYCLES(CYCLES_DEC_REG);
-}
-
-void I386_OPS_BASE::I386OP(dec_ebp)() // Opcode 0x4d
-{
- REG32(EBP) = DEC32( REG32(EBP) );
- CYCLES(CYCLES_DEC_REG);
-}
-
-void I386_OPS_BASE::I386OP(dec_esi)() // Opcode 0x4e
-{
- REG32(ESI) = DEC32( REG32(ESI) );
- CYCLES(CYCLES_DEC_REG);
-}
-
-void I386_OPS_BASE::I386OP(dec_edi)() // Opcode 0x4f
-{
- REG32(EDI) = DEC32( REG32(EDI) );
- CYCLES(CYCLES_DEC_REG);
-}
-
-void I386_OPS_BASE::I386OP(imul_r32_rm32)() // Opcode 0x0f af
-{
- UINT8 modrm = FETCH();
- INT64 result;
- INT64 src, dst;
- if( modrm >= 0xc0 ) {
- src = (INT64)(INT32)LOAD_RM32(modrm);
- CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = (INT64)(INT32)READ32(ea);
- CYCLES(CYCLES_IMUL32_REG_REG); /* TODO: Correct multiply timing */
- }
-
- dst = (INT64)(INT32)LOAD_REG32(modrm);
- result = src * dst;
-
- STORE_REG32(modrm, (UINT32)result);
-
- cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
-}
-
-void I386_OPS_BASE::I386OP(imul_r32_rm32_i32)() // Opcode 0x69
-{
- UINT8 modrm = FETCH();
- INT64 result;
- INT64 src, dst;
- if( modrm >= 0xc0 ) {
- dst = (INT64)(INT32)LOAD_RM32(modrm);
- CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- dst = (INT64)(INT32)READ32(ea);
- CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */
- }
-
- src = (INT64)(INT32)FETCH32();
- result = src * dst;
-
- STORE_REG32(modrm, (UINT32)result);
-
- cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
-}
-
-void I386_OPS_BASE::I386OP(imul_r32_rm32_i8)() // Opcode 0x6b
-{
- UINT8 modrm = FETCH();
- INT64 result;
- INT64 src, dst;
- if( modrm >= 0xc0 ) {
- dst = (INT64)(INT32)LOAD_RM32(modrm);
- CYCLES(CYCLES_IMUL32_REG_IMM_REG); /* TODO: Correct multiply timing */
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- dst = (INT64)(INT32)READ32(ea);
- CYCLES(CYCLES_IMUL32_MEM_IMM_REG); /* TODO: Correct multiply timing */
- }
-
- src = (INT64)(INT8)FETCH();
- result = src * dst;
-
- STORE_REG32(modrm, (UINT32)result);
-
- cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
-}
-
-void I386_OPS_BASE::I386OP(in_eax_i8)() // Opcode 0xe5
-{
- UINT16 port = FETCH();
- UINT32 data = READPORT32( port);
- REG32(EAX) = data;
- CYCLES(CYCLES_IN_VAR);
-}
-
-void I386_OPS_BASE::I386OP(in_eax_dx)() // Opcode 0xed
-{
- UINT16 port = REG16(DX);
- UINT32 data = READPORT32( port);
- REG32(EAX) = data;
- CYCLES(CYCLES_IN);
-}
-
-void I386_OPS_BASE::I386OP(inc_eax)() // Opcode 0x40
-{
- REG32(EAX) = INC32( REG32(EAX) );
- CYCLES(CYCLES_INC_REG);
-}
-
-void I386_OPS_BASE::I386OP(inc_ecx)() // Opcode 0x41
-{
- REG32(ECX) = INC32( REG32(ECX) );
- CYCLES(CYCLES_INC_REG);
-}
-
-void I386_OPS_BASE::I386OP(inc_edx)() // Opcode 0x42
-{
- REG32(EDX) = INC32( REG32(EDX) );
- CYCLES(CYCLES_INC_REG);
-}
-
-void I386_OPS_BASE::I386OP(inc_ebx)() // Opcode 0x43
-{
- REG32(EBX) = INC32( REG32(EBX) );
- CYCLES(CYCLES_INC_REG);
-}
-
-void I386_OPS_BASE::I386OP(inc_esp)() // Opcode 0x44
-{
- REG32(ESP) = INC32( REG32(ESP) );
- CYCLES(CYCLES_INC_REG);
-}
-
-void I386_OPS_BASE::I386OP(inc_ebp)() // Opcode 0x45
-{
- REG32(EBP) = INC32( REG32(EBP) );
- CYCLES(CYCLES_INC_REG);
-}
-
-void I386_OPS_BASE::I386OP(inc_esi)() // Opcode 0x46
-{
- REG32(ESI) = INC32( REG32(ESI) );
- CYCLES(CYCLES_INC_REG);
-}
-
-void I386_OPS_BASE::I386OP(inc_edi)() // Opcode 0x47
-{
- REG32(EDI) = INC32( REG32(EDI) );
- CYCLES(CYCLES_INC_REG);
-}
-
-void I386_OPS_BASE::I386OP(iret32)() // Opcode 0xcf
-{
- if( PROTECTED_MODE )
- {
- i386_protected_mode_iret(1);
- }
- else
- {
- /* TODO: #SS(0) exception */
- /* TODO: #GP(0) exception */
- cpustate->eip = POP32();
- cpustate->sreg[CS].selector = POP32() & 0xffff;
- set_flags( POP32() );
- i386_load_segment_descriptor(CS);
- CHANGE_PC(cpustate->eip);
- }
- CYCLES(CYCLES_IRET);
-}
-
-void I386_OPS_BASE::I386OP(ja_rel32)() // Opcode 0x0f 87
-{
- INT32 disp = FETCH32();
- if( cpustate->CF == 0 && cpustate->ZF == 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jbe_rel32)() // Opcode 0x0f 86
-{
- INT32 disp = FETCH32();
- if( cpustate->CF != 0 || cpustate->ZF != 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jc_rel32)() // Opcode 0x0f 82
-{
- INT32 disp = FETCH32();
- if( cpustate->CF != 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jg_rel32)() // Opcode 0x0f 8f
-{
- INT32 disp = FETCH32();
- if( cpustate->ZF == 0 && (cpustate->SF == cpustate->OF) ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jge_rel32)() // Opcode 0x0f 8d
-{
- INT32 disp = FETCH32();
- if(cpustate->SF == cpustate->OF) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jl_rel32)() // Opcode 0x0f 8c
-{
- INT32 disp = FETCH32();
- if( (cpustate->SF != cpustate->OF) ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jle_rel32)() // Opcode 0x0f 8e
-{
- INT32 disp = FETCH32();
- if( cpustate->ZF != 0 || (cpustate->SF != cpustate->OF) ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jnc_rel32)() // Opcode 0x0f 83
-{
- INT32 disp = FETCH32();
- if( cpustate->CF == 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jno_rel32)() // Opcode 0x0f 81
-{
- INT32 disp = FETCH32();
- if( cpustate->OF == 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jnp_rel32)() // Opcode 0x0f 8b
-{
- INT32 disp = FETCH32();
- if( cpustate->PF == 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jns_rel32)() // Opcode 0x0f 89
-{
- INT32 disp = FETCH32();
- if( cpustate->SF == 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jnz_rel32)() // Opcode 0x0f 85
-{
- INT32 disp = FETCH32();
- if( cpustate->ZF == 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jo_rel32)() // Opcode 0x0f 80
-{
- INT32 disp = FETCH32();
- if( cpustate->OF != 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jp_rel32)() // Opcode 0x0f 8a
-{
- INT32 disp = FETCH32();
- if( cpustate->PF != 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(js_rel32)() // Opcode 0x0f 88
-{
- INT32 disp = FETCH32();
- if( cpustate->SF != 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jz_rel32)() // Opcode 0x0f 84
-{
- INT32 disp = FETCH32();
- if( cpustate->ZF != 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
- } else {
- CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jcxz32)() // Opcode 0xe3
-{
- INT8 disp = FETCH();
- int val = (cpustate->address_size)?(REG32(ECX) == 0):(REG16(CX) == 0);
- if( val ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JCXZ); /* TODO: Timing = 9 + m */
- } else {
- CYCLES(CYCLES_JCXZ_NOBRANCH);
- }
-}
-
-void I386_OPS_BASE::I386OP(jmp_rel32)() // Opcode 0xe9
-{
- UINT32 disp = FETCH32();
- /* TODO: Segment limit */
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_JMP); /* TODO: Timing = 7 + m */
-}
-
-void I386_OPS_BASE::I386OP(jmp_abs32)() // Opcode 0xea
-{
- UINT32 address = FETCH32();
- UINT16 segment = FETCH16();
-
- if( PROTECTED_MODE && !V8086_MODE)
- {
- i386_protected_mode_jump(segment,address,0,1);
- }
- else
- {
- cpustate->eip = address;
- cpustate->sreg[CS].selector = segment;
- cpustate->performed_intersegment_jump = 1;
- i386_load_segment_descriptor(CS);
- CHANGE_PC(cpustate->eip);
- }
- CYCLES(CYCLES_JMP_INTERSEG);
-}
-
-void I386_OPS_BASE::I386OP(lea32)() // Opcode 0x8d
-{
- UINT8 modrm = FETCH();
- UINT32 ea = GetNonTranslatedEA(modrm,NULL);
- if (!cpustate->address_size)
- {
- ea &= 0xffff;
- }
- STORE_REG32(modrm, ea);
- CYCLES(CYCLES_LEA);
-}
-
-void I386_OPS_BASE::I386OP(enter32)() // Opcode 0xc8
-{
- UINT16 framesize = FETCH16();
- UINT8 level = FETCH() % 32;
- UINT8 x;
- UINT32 frameptr;
- PUSH32(REG32(EBP));
- if(!STACK_32BIT)
- frameptr = REG16(SP);
- else
- frameptr = REG32(ESP);
-
- if(level > 0)
- {
- for(x=1;x<level-1;x++)
- {
- REG32(EBP) -= 4;
- PUSH32(READ32(REG32(EBP)));
- }
- PUSH32(frameptr);
- }
- REG32(EBP) = frameptr;
- if(!STACK_32BIT)
- REG16(SP) -= framesize;
- else
- REG32(ESP) -= framesize;
- CYCLES(CYCLES_ENTER);
-}
-
-void I386_OPS_BASE::I386OP(leave32)() // Opcode 0xc9
-{
- if(!STACK_32BIT)
- REG16(SP) = REG16(BP);
- else
- REG32(ESP) = REG32(EBP);
- REG32(EBP) = POP32();
- CYCLES(CYCLES_LEAVE);
-}
-
-void I386_OPS_BASE::I386OP(lodsd)() // Opcode 0xad
-{
- UINT32 eas;
- if( cpustate->segment_prefix ) {
- eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
- } else {
- eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0,4 );
- }
- REG32(EAX) = READ32(eas);
- BUMP_SI(4);
- CYCLES(CYCLES_LODS);
-}
-
-void I386_OPS_BASE::I386OP(loop32)() // Opcode 0xe2
-{
- INT8 disp = FETCH();
- INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
- if( reg != 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- }
- CYCLES(CYCLES_LOOP); /* TODO: Timing = 11 + m */
-}
-
-void I386_OPS_BASE::I386OP(loopne32)() // Opcode 0xe0
-{
- INT8 disp = FETCH();
- INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
- if( reg != 0 && cpustate->ZF == 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- }
- CYCLES(CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */
-}
-
-void I386_OPS_BASE::I386OP(loopz32)() // Opcode 0xe1
-{
- INT8 disp = FETCH();
- INT32 reg = (cpustate->address_size)?--REG32(ECX):--REG16(CX);
- if( reg != 0 && cpustate->ZF != 0 ) {
- cpustate->eip += disp;
- CHANGE_PC(cpustate->eip);
- }
- CYCLES(CYCLES_LOOPZ); /* TODO: Timing = 11 + m */
-}
-
-void I386_OPS_BASE::I386OP(mov_rm32_r32)() // Opcode 0x89
-{
- UINT32 src;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- STORE_RM32(modrm, src);
- CYCLES(CYCLES_MOV_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1, 4);
- src = LOAD_REG32(modrm);
- WRITE32(ea, src);
- CYCLES(CYCLES_MOV_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(mov_r32_rm32)() // Opcode 0x8b
-{
- UINT32 src;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOV_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = READ32(ea);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOV_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(mov_rm32_i32)() // Opcode 0xc7
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 value = FETCH32();
- STORE_RM32(modrm, value);
- CYCLES(CYCLES_MOV_IMM_REG);
- } else {
- UINT32 ea = GetEA(modrm,1, 4);
- UINT32 value = FETCH32();
- WRITE32(ea, value);
- CYCLES(CYCLES_MOV_IMM_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(mov_eax_m32)() // Opcode 0xa1
-{
- UINT32 offset, ea;
- if( cpustate->address_size ) {
- offset = FETCH32();
- } else {
- offset = FETCH16();
- }
- if( cpustate->segment_prefix ) {
- ea = i386_translate( cpustate->segment_override, offset, 0,4 );
- } else {
- ea = i386_translate( DS, offset, 0,4 );
- }
- REG32(EAX) = READ32(ea);
- CYCLES(CYCLES_MOV_MEM_ACC);
-}
-
-void I386_OPS_BASE::I386OP(mov_m32_eax)() // Opcode 0xa3
-{
- UINT32 offset, ea;
- if( cpustate->address_size ) {
- offset = FETCH32();
- } else {
- offset = FETCH16();
- }
- if( cpustate->segment_prefix ) {
- ea = i386_translate( cpustate->segment_override, offset, 1, 4 );
- } else {
- ea = i386_translate( DS, offset, 1, 4 );
- }
- WRITE32( ea, REG32(EAX) );
- CYCLES(CYCLES_MOV_ACC_MEM);
-}
-
-void I386_OPS_BASE::I386OP(mov_eax_i32)() // Opcode 0xb8
-{
- REG32(EAX) = FETCH32();
- CYCLES(CYCLES_MOV_IMM_REG);
-}
-
-void I386_OPS_BASE::I386OP(mov_ecx_i32)() // Opcode 0xb9
-{
- REG32(ECX) = FETCH32();
- CYCLES(CYCLES_MOV_IMM_REG);
-}
-
-void I386_OPS_BASE::I386OP(mov_edx_i32)() // Opcode 0xba
-{
- REG32(EDX) = FETCH32();
- CYCLES(CYCLES_MOV_IMM_REG);
-}
-
-void I386_OPS_BASE::I386OP(mov_ebx_i32)() // Opcode 0xbb
-{
- REG32(EBX) = FETCH32();
- CYCLES(CYCLES_MOV_IMM_REG);
-}
-
-void I386_OPS_BASE::I386OP(mov_esp_i32)() // Opcode 0xbc
-{
- REG32(ESP) = FETCH32();
- CYCLES(CYCLES_MOV_IMM_REG);
-}
-
-void I386_OPS_BASE::I386OP(mov_ebp_i32)() // Opcode 0xbd
-{
- REG32(EBP) = FETCH32();
- CYCLES(CYCLES_MOV_IMM_REG);
-}
-
-void I386_OPS_BASE::I386OP(mov_esi_i32)() // Opcode 0xbe
-{
- REG32(ESI) = FETCH32();
- CYCLES(CYCLES_MOV_IMM_REG);
-}
-
-void I386_OPS_BASE::I386OP(mov_edi_i32)() // Opcode 0xbf
-{
- REG32(EDI) = FETCH32();
- CYCLES(CYCLES_MOV_IMM_REG);
-}
-
-void I386_OPS_BASE::I386OP(movsd)() // Opcode 0xa5
-{
- UINT32 eas, ead, v;
- if( cpustate->segment_prefix ) {
- eas = i386_translate( cpustate->segment_override, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 4 );
- } else {
- eas = i386_translate( DS, cpustate->address_size ? REG32(ESI) : REG16(SI), 0, 4 );
- }
- ead = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 4 );
- v = READ32(eas);
- WRITE32(ead, v);
- BUMP_SI(4);
- BUMP_DI(4);
- CYCLES(CYCLES_MOVS);
-}
-
-void I386_OPS_BASE::I386OP(movsx_r32_rm8)() // Opcode 0x0f be
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- INT32 src = (INT8)LOAD_RM8(modrm);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOVSX_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 1);
- INT32 src = (INT8)READ8(ea);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOVSX_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(movsx_r32_rm16)() // Opcode 0x0f bf
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- INT32 src = (INT16)LOAD_RM16(modrm);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOVSX_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 2);
- INT32 src = (INT16)READ16(ea);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOVSX_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(movzx_r32_rm8)() // Opcode 0x0f b6
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 src = (UINT8)LOAD_RM8(modrm);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOVZX_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 1);
- UINT32 src = (UINT8)READ8(ea);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOVZX_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(movzx_r32_rm16)() // Opcode 0x0f b7
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 src = (UINT16)LOAD_RM16(modrm);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOVZX_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 2);
- UINT32 src = (UINT16)READ16(ea);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_MOVZX_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(or_rm32_r32)() // Opcode 0x09
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- dst = LOAD_RM32(modrm);
- dst = OR32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1, 4);
- src = LOAD_REG32(modrm);
- dst = READ32(ea);
- dst = OR32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(or_r32_rm32)() // Opcode 0x0b
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- dst = LOAD_REG32(modrm);
- dst = OR32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = READ32(ea);
- dst = LOAD_REG32(modrm);
- dst = OR32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(or_eax_i32)() // Opcode 0x0d
-{
- UINT32 src, dst;
- src = FETCH32();
- dst = REG32(EAX);
- dst = OR32(dst, src);
- REG32(EAX) = dst;
- CYCLES(CYCLES_ALU_IMM_ACC);
-}
-
-void I386_OPS_BASE::I386OP(out_eax_i8)() // Opcode 0xe7
-{
- UINT16 port = FETCH();
- UINT32 data = REG32(EAX);
- WRITEPORT32( port, data);
- CYCLES(CYCLES_OUT_VAR);
-}
-
-void I386_OPS_BASE::I386OP(out_eax_dx)() // Opcode 0xef
-{
- UINT16 port = REG16(DX);
- UINT32 data = REG32(EAX);
- WRITEPORT32( port, data);
- CYCLES(CYCLES_OUT);
-}
-
-void I386_OPS_BASE::I386OP(pop_eax)() // Opcode 0x58
-{
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 4) == 0)
- REG32(EAX) = POP32();
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POP_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(pop_ecx)() // Opcode 0x59
-{
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 4) == 0)
- REG32(ECX) = POP32();
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POP_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(pop_edx)() // Opcode 0x5a
-{
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 4) == 0)
- REG32(EDX) = POP32();
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POP_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(pop_ebx)() // Opcode 0x5b
-{
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 4) == 0)
- REG32(EBX) = POP32();
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POP_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(pop_esp)() // Opcode 0x5c
-{
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 4) == 0)
- REG32(ESP) = POP32();
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POP_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(pop_ebp)() // Opcode 0x5d
-{
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 4) == 0)
- REG32(EBP) = POP32();
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POP_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(pop_esi)() // Opcode 0x5e
-{
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 4) == 0)
- REG32(ESI) = POP32();
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POP_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(pop_edi)() // Opcode 0x5f
-{
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 4) == 0)
- REG32(EDI) = POP32();
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POP_REG_SHORT);
-}
-
-bool I386_OPS_BASE::I386OP(pop_seg32)( int segment)
-{
- UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- UINT32 value;
- bool fault;
- if(i386_limit_check(SS,offset, 4) == 0)
- {
- ea = i386_translate( SS, offset, 0, 4);
- value = READ32( ea);
- i386_sreg_load(value, segment, &fault);
- if(fault) return false;
- if(STACK_32BIT)
- REG32(ESP) = offset + 4;
- else
- REG16(SP) = offset + 4;
- }
- else
- {
- cpustate->ext = 1;
- i386_trap_with_error(FAULT_SS,0,0,0);
- return false;
- }
- CYCLES(CYCLES_POP_SREG);
- return true;
-}
-
-void I386_OPS_BASE::I386OP(pop_ds32)() // Opcode 0x1f
-{
- I386OP(pop_seg32)( DS);
-}
-
-void I386_OPS_BASE::I386OP(pop_es32)() // Opcode 0x07
-{
- I386OP(pop_seg32)( ES);
-}
-
-void I386_OPS_BASE::I386OP(pop_fs32)() // Opcode 0x0f a1
-{
- I386OP(pop_seg32)( FS);
-}
-
-void I386_OPS_BASE::I386OP(pop_gs32)() // Opcode 0x0f a9
-{
- I386OP(pop_seg32)( GS);
-}
-
-void I386_OPS_BASE::I386OP(pop_ss32)() // Opcode 0x17
-{
- if(!I386OP(pop_seg32)( SS)) return;
- if(cpustate->IF != 0) // if external interrupts are enabled
- {
- cpustate->IF = 0; // reset IF for the next instruction
- cpustate->delayed_interrupt_enable = 1;
- }
-}
-
-void I386_OPS_BASE::I386OP(pop_rm32)() // Opcode 0x8f
-{
- UINT8 modrm = FETCH();
- UINT32 value;
- UINT32 ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 4) == 0)
- {
- // be careful here, if the write references the esp register
- // it expects the post-pop value but esp must be wound back
- // if the write faults
- UINT32 temp_sp = REG32(ESP);
- value = POP32();
-
- if( modrm >= 0xc0 ) {
- STORE_RM32(modrm, value);
- } else {
- ea = GetEA(modrm,1, 4);
- try
- {
- WRITE32(ea, value);
- }
- catch(UINT64 e)
- {
- REG32(ESP) = temp_sp;
- throw e;
- }
- }
- }
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POP_RM);
-}
-
-void I386_OPS_BASE::I386OP(popad)() // Opcode 0x61
-{
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
- if(i386_limit_check(SS,offset, 32) == 0)
- {
- REG32(EDI) = POP32();
- REG32(ESI) = POP32();
- REG32(EBP) = POP32();
- REG32(ESP) += 4;
- REG32(EBX) = POP32();
- REG32(EDX) = POP32();
- REG32(ECX) = POP32();
- REG32(EAX) = POP32();
- }
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POPA);
-}
-
-void I386_OPS_BASE::I386OP(popfd)() // Opcode 0x9d
-{
- UINT32 value;
- UINT32 current = get_flags();
- UINT8 IOPL = (current >> 12) & 0x03;
- UINT32 mask = 0x00257fd5; // VM, VIP and VIF cannot be set by POPF/POPFD
- UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
-
- // IOPL can only change if CPL is 0
- if(cpustate->CPL != 0)
- mask &= ~0x00003000;
-
- // IF can only change if CPL is at least as privileged as IOPL
- if(cpustate->CPL > IOPL)
- mask &= ~0x00000200;
-
- if(V8086_MODE)
- {
- if(IOPL < 3)
- {
- logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",cpustate->pc);
- FAULT(FAULT_GP,0) // #GP(0)
- }
- mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode
- }
-
- if(i386_limit_check(SS,offset, 4) == 0)
- {
- value = POP32();
- value &= ~0x00010000; // RF will always return zero
- set_flags((current & ~mask) | (value & mask)); // mask out reserved bits
- }
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_POPF);
-}
-
-void I386_OPS_BASE::I386OP(push_eax)() // Opcode 0x50
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( REG32(EAX) );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(push_ecx)() // Opcode 0x51
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( REG32(ECX) );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(push_edx)() // Opcode 0x52
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( REG32(EDX) );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(push_ebx)() // Opcode 0x53
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( REG32(EBX) );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(push_esp)() // Opcode 0x54
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( REG32(ESP) );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(push_ebp)() // Opcode 0x55
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( REG32(EBP) );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(push_esi)() // Opcode 0x56
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( REG32(ESI) );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(push_edi)() // Opcode 0x57
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( REG32(EDI) );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_REG_SHORT);
-}
-
-void I386_OPS_BASE::I386OP(push_cs32)() // Opcode 0x0e
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32SEG( cpustate->sreg[CS].selector );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_SREG);
-}
-
-void I386_OPS_BASE::I386OP(push_ds32)() // Opcode 0x1e
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32SEG( cpustate->sreg[DS].selector );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_SREG);
-}
-
-void I386_OPS_BASE::I386OP(push_es32)() // Opcode 0x06
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32SEG( cpustate->sreg[ES].selector );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_SREG);
-}
-
-void I386_OPS_BASE::I386OP(push_fs32)() // Opcode 0x0f a0
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32SEG( cpustate->sreg[FS].selector );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_SREG);
-}
-
-void I386_OPS_BASE::I386OP(push_gs32)() // Opcode 0x0f a8
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32SEG( cpustate->sreg[GS].selector );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_SREG);
-}
-
-void I386_OPS_BASE::I386OP(push_ss32)() // Opcode 0x16
-{
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( cpustate->sreg[SS].selector );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_SREG);
-}
-
-void I386_OPS_BASE::I386OP(push_i32)() // Opcode 0x68
-{
- UINT32 value = FETCH32();
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32(value);
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSH_IMM);
-}
-
-void I386_OPS_BASE::I386OP(pushad)() // Opcode 0x60
-{
- UINT32 temp = REG32(ESP);
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 32;
- else
- offset = (REG16(SP) - 32) & 0xffff;
- if(i386_limit_check(SS,offset, 32) == 0)
- {
- PUSH32( REG32(EAX) );
- PUSH32( REG32(ECX) );
- PUSH32( REG32(EDX) );
- PUSH32( REG32(EBX) );
- PUSH32( temp );
- PUSH32( REG32(EBP) );
- PUSH32( REG32(ESI) );
- PUSH32( REG32(EDI) );
- }
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSHA);
-}
-
-void I386_OPS_BASE::I386OP(pushfd)() // Opcode 0x9c
-{
- if(!cpustate->IOP1 && !cpustate->IOP2 && V8086_MODE)
- FAULT(FAULT_GP,0)
- UINT32 offset;
- if(STACK_32BIT)
- offset = REG32(ESP) - 4;
- else
- offset = (REG16(SP) - 4) & 0xffff;
- if(i386_limit_check(SS,offset, 4) == 0)
- PUSH32( get_flags() & 0x00fcffff );
- else
- FAULT(FAULT_SS,0)
- CYCLES(CYCLES_PUSHF);
-}
-
-void I386_OPS_BASE::I386OP(ret_near32_i16)() // Opcode 0xc2
-{
- INT16 disp = FETCH16();
- cpustate->eip = POP32();
- REG32(ESP) += disp;
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_RET_IMM); /* TODO: Timing = 10 + m */
-}
-
-void I386_OPS_BASE::I386OP(ret_near32)() // Opcode 0xc3
-{
- cpustate->eip = POP32();
- CHANGE_PC(cpustate->eip);
- CYCLES(CYCLES_RET); /* TODO: Timing = 10 + m */
-}
-
-void I386_OPS_BASE::I386OP(sbb_rm32_r32)() // Opcode 0x19
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- dst = LOAD_RM32(modrm);
- dst = SBB32( dst, src, cpustate->CF);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1, 4);
- src = LOAD_REG32(modrm);
- dst = READ32(ea);
- dst = SBB32( dst, src, cpustate->CF);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(sbb_r32_rm32)() // Opcode 0x1b
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- dst = LOAD_REG32(modrm);
- dst = SBB32( dst, src, cpustate->CF);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0, 4);
- src = READ32(ea);
- dst = LOAD_REG32(modrm);
- dst = SBB32( dst, src, cpustate->CF);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(sbb_eax_i32)() // Opcode 0x1d
-{
- UINT32 src, dst;
- src = FETCH32();
- dst = REG32(EAX);
- dst = SBB32( dst, src, cpustate->CF);
- REG32(EAX) = dst;
- CYCLES(CYCLES_ALU_IMM_ACC);
-}
-
-void I386_OPS_BASE::I386OP(scasd)() // Opcode 0xaf
-{
- UINT32 eas, src, dst;
- eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 0, 4 );
- src = READ32(eas);
- dst = REG32(EAX);
- SUB32(dst, src);
- BUMP_DI(4);
- CYCLES(CYCLES_SCAS);
-}
-
-void I386_OPS_BASE::I386OP(shld32_i8)() // Opcode 0x0f a4
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT32 upper = LOAD_REG32(modrm);
- UINT8 shift = FETCH();
- shift &= 31;
- if( shift == 0 ) {
- } else {
- cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
- dst = (dst << shift) | (upper >> (32-shift));
- cpustate->OF = cpustate->CF ^ (dst >> 31);
- SetSZPF32(dst);
- }
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_SHLD_REG);
- } else {
- UINT32 ea = GetEA(modrm,1, 4);
- UINT32 dst = READ32(ea);
- UINT32 upper = LOAD_REG32(modrm);
- UINT8 shift = FETCH();
- shift &= 31;
- if( shift == 0 ) {
- } else {
- cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
- dst = (dst << shift) | (upper >> (32-shift));
- cpustate->OF = cpustate->CF ^ (dst >> 31);
- SetSZPF32(dst);
- }
- WRITE32(ea, dst);
- CYCLES(CYCLES_SHLD_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(shld32_cl)() // Opcode 0x0f a5
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT32 upper = LOAD_REG32(modrm);
- UINT8 shift = REG8(CL);
- shift &= 31;
- if( shift == 0 ) {
- } else {
- cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
- dst = (dst << shift) | (upper >> (32-shift));
- cpustate->OF = cpustate->CF ^ (dst >> 31);
- SetSZPF32(dst);
- }
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_SHLD_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- UINT32 upper = LOAD_REG32(modrm);
- UINT8 shift = REG8(CL);
- shift &= 31;
- if( shift == 0 ) {
- } else {
- cpustate->CF = (dst & (1 << (32-shift))) ? 1 : 0;
- dst = (dst << shift) | (upper >> (32-shift));
- cpustate->OF = cpustate->CF ^ (dst >> 31);
- SetSZPF32(dst);
- }
- WRITE32(ea, dst);
- CYCLES(CYCLES_SHLD_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(shrd32_i8)() // Opcode 0x0f ac
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT32 upper = LOAD_REG32(modrm);
- UINT8 shift = FETCH();
- shift &= 31;
- if( shift == 0 ) {
- } else {
- cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
- dst = (dst >> shift) | (upper << (32-shift));
- cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
- SetSZPF32(dst);
- }
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_SHRD_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- UINT32 upper = LOAD_REG32(modrm);
- UINT8 shift = FETCH();
- shift &= 31;
- if( shift == 0 ) {
- } else {
- cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
- dst = (dst >> shift) | (upper << (32-shift));
- cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
- SetSZPF32(dst);
- }
- WRITE32(ea, dst);
- CYCLES(CYCLES_SHRD_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(shrd32_cl)() // Opcode 0x0f ad
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT32 upper = LOAD_REG32(modrm);
- UINT8 shift = REG8(CL);
- shift &= 31;
- if( shift == 0 ) {
- } else {
- cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
- dst = (dst >> shift) | (upper << (32-shift));
- cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
- SetSZPF32(dst);
- }
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_SHRD_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- UINT32 upper = LOAD_REG32(modrm);
- UINT8 shift = REG8(CL);
- shift &= 31;
- if( shift == 0 ) {
- } else {
- cpustate->CF = (dst & (1 << (shift-1))) ? 1 : 0;
- dst = (dst >> shift) | (upper << (32-shift));
- cpustate->OF = ((dst >> 31) ^ (dst >> 30)) & 1;
- SetSZPF32(dst);
- }
- WRITE32(ea, dst);
- CYCLES(CYCLES_SHRD_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(stosd)() // Opcode 0xab
-{
- UINT32 eas = i386_translate( ES, cpustate->address_size ? REG32(EDI) : REG16(DI), 1, 4 );
- WRITE32(eas, REG32(EAX));
- BUMP_DI(4);
- CYCLES(CYCLES_STOS);
-}
-
-void I386_OPS_BASE::I386OP(sub_rm32_r32)() // Opcode 0x29
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- dst = LOAD_RM32(modrm);
- dst = SUB32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- src = LOAD_REG32(modrm);
- dst = READ32(ea);
- dst = SUB32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(sub_r32_rm32)() // Opcode 0x2b
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- dst = LOAD_REG32(modrm);
- dst = SUB32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- src = READ32(ea);
- dst = LOAD_REG32(modrm);
- dst = SUB32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(sub_eax_i32)() // Opcode 0x2d
-{
- UINT32 src, dst;
- src = FETCH32();
- dst = REG32(EAX);
- dst = SUB32(dst, src);
- REG32(EAX) = dst;
- CYCLES(CYCLES_ALU_IMM_ACC);
-}
-
-void I386_OPS_BASE::I386OP(test_eax_i32)() // Opcode 0xa9
-{
- UINT32 src = FETCH32();
- UINT32 dst = REG32(EAX);
- dst = src & dst;
- SetSZPF32(dst);
- cpustate->CF = 0;
- cpustate->OF = 0;
- CYCLES(CYCLES_TEST_IMM_ACC);
-}
-
-void I386_OPS_BASE::I386OP(test_rm32_r32)() // Opcode 0x85
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- dst = LOAD_RM32(modrm);
- dst = src & dst;
- SetSZPF32(dst);
- cpustate->CF = 0;
- cpustate->OF = 0;
- CYCLES(CYCLES_TEST_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- src = LOAD_REG32(modrm);
- dst = READ32(ea);
- dst = src & dst;
- SetSZPF32(dst);
- cpustate->CF = 0;
- cpustate->OF = 0;
- CYCLES(CYCLES_TEST_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(xchg_eax_ecx)() // Opcode 0x91
-{
- UINT32 temp;
- temp = REG32(EAX);
- REG32(EAX) = REG32(ECX);
- REG32(ECX) = temp;
- CYCLES(CYCLES_XCHG_REG_REG);
-}
-
-void I386_OPS_BASE::I386OP(xchg_eax_edx)() // Opcode 0x92
-{
- UINT32 temp;
- temp = REG32(EAX);
- REG32(EAX) = REG32(EDX);
- REG32(EDX) = temp;
- CYCLES(CYCLES_XCHG_REG_REG);
-}
-
-void I386_OPS_BASE::I386OP(xchg_eax_ebx)() // Opcode 0x93
-{
- UINT32 temp;
- temp = REG32(EAX);
- REG32(EAX) = REG32(EBX);
- REG32(EBX) = temp;
- CYCLES(CYCLES_XCHG_REG_REG);
-}
-
-void I386_OPS_BASE::I386OP(xchg_eax_esp)() // Opcode 0x94
-{
- UINT32 temp;
- temp = REG32(EAX);
- REG32(EAX) = REG32(ESP);
- REG32(ESP) = temp;
- CYCLES(CYCLES_XCHG_REG_REG);
-}
-
-void I386_OPS_BASE::I386OP(xchg_eax_ebp)() // Opcode 0x95
-{
- UINT32 temp;
- temp = REG32(EAX);
- REG32(EAX) = REG32(EBP);
- REG32(EBP) = temp;
- CYCLES(CYCLES_XCHG_REG_REG);
-}
-
-void I386_OPS_BASE::I386OP(xchg_eax_esi)() // Opcode 0x96
-{
- UINT32 temp;
- temp = REG32(EAX);
- REG32(EAX) = REG32(ESI);
- REG32(ESI) = temp;
- CYCLES(CYCLES_XCHG_REG_REG);
-}
-
-void I386_OPS_BASE::I386OP(xchg_eax_edi)() // Opcode 0x97
-{
- UINT32 temp;
- temp = REG32(EAX);
- REG32(EAX) = REG32(EDI);
- REG32(EDI) = temp;
- CYCLES(CYCLES_XCHG_REG_REG);
-}
-
-void I386_OPS_BASE::I386OP(xchg_r32_rm32)() // Opcode 0x87
-{
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- UINT32 src = LOAD_RM32(modrm);
- UINT32 dst = LOAD_REG32(modrm);
- STORE_REG32(modrm, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_XCHG_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 src = READ32(ea);
- UINT32 dst = LOAD_REG32(modrm);
- WRITE32(ea, dst);
- STORE_REG32(modrm, src);
- CYCLES(CYCLES_XCHG_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(xor_rm32_r32)() // Opcode 0x31
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_REG32(modrm);
- dst = LOAD_RM32(modrm);
- dst = XOR32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- src = LOAD_REG32(modrm);
- dst = READ32(ea);
- dst = XOR32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
-}
-
-void I386_OPS_BASE::I386OP(xor_r32_rm32)() // Opcode 0x33
-{
- UINT32 src, dst;
- UINT8 modrm = FETCH();
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- dst = LOAD_REG32(modrm);
- dst = XOR32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- src = READ32(ea);
- dst = LOAD_REG32(modrm);
- dst = XOR32(dst, src);
- STORE_REG32(modrm, dst);
- CYCLES(CYCLES_ALU_MEM_REG);
- }
-}
-
-void I386_OPS_BASE::I386OP(xor_eax_i32)() // Opcode 0x35
-{
- UINT32 src, dst;
- src = FETCH32();
- dst = REG32(EAX);
- dst = XOR32(dst, src);
- REG32(EAX) = dst;
- CYCLES(CYCLES_ALU_IMM_ACC);
-}
-
-
-
-void I386_OPS_BASE::I386OP(group81_32)() // Opcode 0x81
-{
- UINT32 ea;
- UINT32 src, dst;
- UINT8 modrm = FETCH();
-
- switch( (modrm >> 3) & 0x7 )
- {
- case 0: // ADD Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = FETCH32();
- dst = ADD32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = FETCH32();
- dst = ADD32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 1: // OR Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = FETCH32();
- dst = OR32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = FETCH32();
- dst = OR32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 2: // ADC Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = FETCH32();
- dst = ADC32( dst, src, cpustate->CF);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = FETCH32();
- dst = ADC32( dst, src, cpustate->CF);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 3: // SBB Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = FETCH32();
- dst = SBB32( dst, src, cpustate->CF);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = FETCH32();
- dst = SBB32( dst, src, cpustate->CF);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 4: // AND Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = FETCH32();
- dst = AND32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = FETCH32();
- dst = AND32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 5: // SUB Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = FETCH32();
- dst = SUB32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = FETCH32();
- dst = SUB32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 6: // XOR Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = FETCH32();
- dst = XOR32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = FETCH32();
- dst = XOR32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 7: // CMP Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = FETCH32();
- SUB32(dst, src);
- CYCLES(CYCLES_CMP_REG_REG);
- } else {
- ea = GetEA(modrm,0,4);
- dst = READ32(ea);
- src = FETCH32();
- SUB32(dst, src);
- CYCLES(CYCLES_CMP_REG_MEM);
- }
- break;
- }
-}
-
-void I386_OPS_BASE::I386OP(group83_32)() // Opcode 0x83
-{
- UINT32 ea;
- UINT32 src, dst;
- UINT8 modrm = FETCH();
-
- switch( (modrm >> 3) & 0x7 )
- {
- case 0: // ADD Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = ADD32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = ADD32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 1: // OR Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = OR32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = OR32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 2: // ADC Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = ADC32( dst, src, cpustate->CF);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = ADC32( dst, src, cpustate->CF);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 3: // SBB Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = ((UINT32)(INT32)(INT8)FETCH());
- dst = SBB32( dst, src, cpustate->CF);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = ((UINT32)(INT32)(INT8)FETCH());
- dst = SBB32( dst, src, cpustate->CF);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 4: // AND Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = AND32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = AND32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 5: // SUB Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = SUB32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = SUB32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 6: // XOR Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = XOR32(dst, src);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_ALU_REG_REG);
- } else {
- ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- src = (UINT32)(INT32)(INT8)FETCH();
- dst = XOR32(dst, src);
- WRITE32(ea, dst);
- CYCLES(CYCLES_ALU_REG_MEM);
- }
- break;
- case 7: // CMP Rm32, i32
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- src = (UINT32)(INT32)(INT8)FETCH();
- SUB32(dst, src);
- CYCLES(CYCLES_CMP_REG_REG);
- } else {
- ea = GetEA(modrm,0,4);
- dst = READ32(ea);
- src = (UINT32)(INT32)(INT8)FETCH();
- SUB32(dst, src);
- CYCLES(CYCLES_CMP_REG_MEM);
- }
- break;
- }
-}
-
-void I386_OPS_BASE::I386OP(groupC1_32)() // Opcode 0xc1
-{
- UINT32 dst;
- UINT8 modrm = FETCH();
- UINT8 shift;
-
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- shift = FETCH() & 0x1f;
- dst = i386_shift_rotate32( modrm, dst, shift);
- STORE_RM32(modrm, dst);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- shift = FETCH() & 0x1f;
- dst = i386_shift_rotate32( modrm, dst, shift);
- WRITE32(ea, dst);
- }
-}
-
-void I386_OPS_BASE::I386OP(groupD1_32)() // Opcode 0xd1
-{
- UINT32 dst;
- UINT8 modrm = FETCH();
-
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- dst = i386_shift_rotate32( modrm, dst, 1);
- STORE_RM32(modrm, dst);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- dst = i386_shift_rotate32( modrm, dst, 1);
- WRITE32(ea, dst);
- }
-}
-
-void I386_OPS_BASE::I386OP(groupD3_32)() // Opcode 0xd3
-{
- UINT32 dst;
- UINT8 modrm = FETCH();
-
- if( modrm >= 0xc0 ) {
- dst = LOAD_RM32(modrm);
- dst = i386_shift_rotate32( modrm, dst, REG8(CL));
- STORE_RM32(modrm, dst);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- dst = READ32(ea);
- dst = i386_shift_rotate32( modrm, dst, REG8(CL));
- WRITE32(ea, dst);
- }
-}
-
-void I386_OPS_BASE::I386OP(groupF7_32)() // Opcode 0xf7
-{
- UINT8 modrm = FETCH();
-
- switch( (modrm >> 3) & 0x7 )
- {
- case 0: /* TEST Rm32, i32 */
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT32 src = FETCH32();
- dst &= src;
- cpustate->CF = cpustate->OF = cpustate->AF = 0;
- SetSZPF32(dst);
- CYCLES(CYCLES_TEST_IMM_REG);
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- UINT32 dst = READ32(ea);
- UINT32 src = FETCH32();
- dst &= src;
- cpustate->CF = cpustate->OF = cpustate->AF = 0;
- SetSZPF32(dst);
- CYCLES(CYCLES_TEST_IMM_MEM);
- }
- break;
- case 2: /* NOT Rm32 */
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- dst = ~dst;
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_NOT_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- dst = ~dst;
- WRITE32(ea, dst);
- CYCLES(CYCLES_NOT_MEM);
- }
- break;
- case 3: /* NEG Rm32 */
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- dst = SUB32( 0, dst );
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_NEG_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- dst = SUB32( 0, dst );
- WRITE32(ea, dst);
- CYCLES(CYCLES_NEG_MEM);
- }
- break;
- case 4: /* MUL EAX, Rm32 */
- {
- UINT64 result;
- UINT32 src, dst;
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- CYCLES(CYCLES_MUL32_ACC_REG); /* TODO: Correct multiply timing */
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- src = READ32(ea);
- CYCLES(CYCLES_MUL32_ACC_MEM); /* TODO: Correct multiply timing */
- }
-
- dst = REG32(EAX);
- result = (UINT64)src * (UINT64)dst;
- REG32(EDX) = (UINT32)(result >> 32);
- REG32(EAX) = (UINT32)result;
-
- cpustate->CF = cpustate->OF = (REG32(EDX) != 0);
- }
- break;
- case 5: /* IMUL EAX, Rm32 */
- {
- INT64 result;
- INT64 src, dst;
- if( modrm >= 0xc0 ) {
- src = (INT64)(INT32)LOAD_RM32(modrm);
- CYCLES(CYCLES_IMUL32_ACC_REG); /* TODO: Correct multiply timing */
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- src = (INT64)(INT32)READ32(ea);
- CYCLES(CYCLES_IMUL32_ACC_MEM); /* TODO: Correct multiply timing */
- }
-
- dst = (INT64)(INT32)REG32(EAX);
- result = src * dst;
-
- REG32(EDX) = (UINT32)(result >> 32);
- REG32(EAX) = (UINT32)result;
-
- cpustate->CF = cpustate->OF = !(result == (INT64)(INT32)result);
- }
- break;
- case 6: /* DIV EAX, Rm32 */
- {
- UINT64 quotient, remainder, result;
- UINT32 src;
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- CYCLES(CYCLES_DIV32_ACC_REG);
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- src = READ32(ea);
- CYCLES(CYCLES_DIV32_ACC_MEM);
- }
-
- quotient = ((UINT64)(REG32(EDX)) << 32) | (UINT64)(REG32(EAX));
- if( src ) {
- remainder = quotient % (UINT64)src;
- result = quotient / (UINT64)src;
- if( result > 0xffffffff ) {
- /* TODO: Divide error */
- } else {
- REG32(EDX) = (UINT32)remainder;
- REG32(EAX) = (UINT32)result;
- }
- } else {
- i386_trap( 0, 0, 0);
- }
- }
- break;
- case 7: /* IDIV EAX, Rm32 */
- {
- INT64 quotient, remainder, result;
- UINT32 src;
- if( modrm >= 0xc0 ) {
- src = LOAD_RM32(modrm);
- CYCLES(CYCLES_IDIV32_ACC_REG);
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- src = READ32(ea);
- CYCLES(CYCLES_IDIV32_ACC_MEM);
- }
-
- quotient = (((INT64)REG32(EDX)) << 32) | ((UINT64)REG32(EAX));
- if( src ) {
- remainder = quotient % (INT64)(INT32)src;
- result = quotient / (INT64)(INT32)src;
- if( result > 0xffffffff ) {
- /* TODO: Divide error */
- } else {
- REG32(EDX) = (UINT32)remainder;
- REG32(EAX) = (UINT32)result;
- }
- } else {
- i386_trap( 0, 0, 0);
- }
- }
- break;
- }
-}
-
-void I386_OPS_BASE::I386OP(groupFF_32)() // Opcode 0xff
-{
- UINT8 modrm = FETCH();
-
- switch( (modrm >> 3) & 0x7 )
- {
- case 0: /* INC Rm32 */
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- dst = INC32(dst);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_INC_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- dst = INC32(dst);
- WRITE32(ea, dst);
- CYCLES(CYCLES_INC_MEM);
- }
- break;
- case 1: /* DEC Rm32 */
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- dst = DEC32(dst);
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_DEC_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- dst = DEC32(dst);
- WRITE32(ea, dst);
- CYCLES(CYCLES_DEC_MEM);
- }
- break;
- case 2: /* CALL Rm32 */
- {
- UINT32 address;
- if( modrm >= 0xc0 ) {
- address = LOAD_RM32(modrm);
- CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- address = READ32(ea);
- CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */
- }
- PUSH32( cpustate->eip );
- cpustate->eip = address;
- CHANGE_PC(cpustate->eip);
- }
- break;
- case 3: /* CALL FAR Rm32 */
- {
- UINT16 selector;
- UINT32 address;
-
- if( modrm >= 0xc0 )
- {
- report_invalid_modrm( "groupFF_32", modrm);
- }
- else
- {
- UINT32 ea = GetEA(modrm,0,6);
- address = READ32(ea + 0);
- selector = READ16(ea + 4);
- CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */
- if(PROTECTED_MODE && !V8086_MODE)
- {
- i386_protected_mode_call(selector,address,1,1);
- }
- else
- {
- PUSH32SEG( cpustate->sreg[CS].selector );
- PUSH32( cpustate->eip );
- cpustate->sreg[CS].selector = selector;
- cpustate->performed_intersegment_jump = 1;
- i386_load_segment_descriptor( CS );
- cpustate->eip = address;
- CHANGE_PC(cpustate->eip);
- }
- }
- }
- break;
- case 4: /* JMP Rm32 */
- {
- UINT32 address;
- if( modrm >= 0xc0 ) {
- address = LOAD_RM32(modrm);
- CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- address = READ32(ea);
- CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */
- }
- cpustate->eip = address;
- CHANGE_PC(cpustate->eip);
- }
- break;
- case 5: /* JMP FAR Rm32 */
- {
- UINT16 selector;
- UINT32 address;
-
- if( modrm >= 0xc0 )
- {
- report_invalid_modrm( "groupFF_32", modrm);
- }
- else
- {
- UINT32 ea = GetEA(modrm,0,6);
- address = READ32(ea + 0);
- selector = READ16(ea + 4);
- CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */
- if(PROTECTED_MODE && !V8086_MODE)
- {
- i386_protected_mode_jump(selector,address,1,1);
- }
- else
- {
- cpustate->sreg[CS].selector = selector;
- cpustate->performed_intersegment_jump = 1;
- i386_load_segment_descriptor( CS );
- cpustate->eip = address;
- CHANGE_PC(cpustate->eip);
- }
- }
- }
- break;
- case 6: /* PUSH Rm32 */
- {
- UINT32 value;
- if( modrm >= 0xc0 ) {
- value = LOAD_RM32(modrm);
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- value = READ32(ea);
- }
- PUSH32(value);
- CYCLES(CYCLES_PUSH_RM);
- }
- break;
- default:
- report_invalid_modrm( "groupFF_32", modrm);
- break;
- }
-}
-
-void I386_OPS_BASE::I386OP(group0F00_32)() // Opcode 0x0f 00
-{
- UINT32 address, ea;
- UINT8 modrm = FETCH();
- I386_SREG seg;
- UINT8 result;
-
- switch( (modrm >> 3) & 0x7 )
- {
- case 0: /* SLDT */
- if ( PROTECTED_MODE && !V8086_MODE )
- {
- if( modrm >= 0xc0 ) {
- STORE_RM32(modrm, cpustate->ldtr.segment);
- CYCLES(CYCLES_SLDT_REG);
- } else {
- ea = GetEA(modrm,1,2);
- WRITE16( ea, cpustate->ldtr.segment);
- CYCLES(CYCLES_SLDT_MEM);
- }
- }
- else
- {
- i386_trap(6, 0, 0);
- }
- break;
- case 1: /* STR */
- if ( PROTECTED_MODE && !V8086_MODE )
- {
- if( modrm >= 0xc0 ) {
- STORE_RM32(modrm, cpustate->task.segment);
- CYCLES(CYCLES_STR_REG);
- } else {
- ea = GetEA(modrm,1,2);
- WRITE16( ea, cpustate->task.segment);
- CYCLES(CYCLES_STR_MEM);
- }
- }
- else
- {
- i386_trap(6, 0, 0);
- }
- break;
- case 2: /* LLDT */
- if ( PROTECTED_MODE && !V8086_MODE )
- {
- if(cpustate->CPL)
- FAULT(FAULT_GP,0)
- if( modrm >= 0xc0 ) {
- address = LOAD_RM32(modrm);
- cpustate->ldtr.segment = address;
- CYCLES(CYCLES_LLDT_REG);
- } else {
- ea = GetEA(modrm,0,4);
- cpustate->ldtr.segment = READ32(ea);
- CYCLES(CYCLES_LLDT_MEM);
- }
- memset(&seg, 0, sizeof(seg));
- seg.selector = cpustate->ldtr.segment;
- i386_load_protected_mode_segment(&seg,NULL);
- cpustate->ldtr.limit = seg.limit;
- cpustate->ldtr.base = seg.base;
- cpustate->ldtr.flags = seg.flags;
- }
- else
- {
- i386_trap(6, 0, 0);
- }
- break;
-
- case 3: /* LTR */
- if ( PROTECTED_MODE && !V8086_MODE )
- {
- if(cpustate->CPL)
- FAULT(FAULT_GP,0)
- if( modrm >= 0xc0 ) {
- address = LOAD_RM32(modrm);
- cpustate->task.segment = address;
- CYCLES(CYCLES_LTR_REG);
- } else {
- ea = GetEA(modrm,0,4);
- cpustate->task.segment = READ32(ea);
- CYCLES(CYCLES_LTR_MEM);
- }
- memset(&seg, 0, sizeof(seg));
- seg.selector = cpustate->task.segment;
- i386_load_protected_mode_segment(&seg,NULL);
-
- UINT32 addr = ((seg.selector & 4) ? cpustate->ldtr.base : cpustate->gdtr.base) + (seg.selector & ~7) + 5;
- i386_translate_address( TRANSLATE_READ, &addr, NULL);
- cpustate->program->write_data8(addr, (seg.flags & 0xff) | 2);
-
- cpustate->task.limit = seg.limit;
- cpustate->task.base = seg.base;
- cpustate->task.flags = seg.flags | 2;
- }
- else
- {
- i386_trap(6, 0, 0);
- }
- break;
-
- case 4: /* VERR */
- if ( PROTECTED_MODE && !V8086_MODE )
- {
- if( modrm >= 0xc0 ) {
- address = LOAD_RM32(modrm);
- CYCLES(CYCLES_VERR_REG);
- } else {
- ea = GetEA(modrm,0,4);
- address = READ32(ea);
- CYCLES(CYCLES_VERR_MEM);
- }
- memset(&seg, 0, sizeof(seg));
- seg.selector = address;
- result = i386_load_protected_mode_segment(&seg,NULL);
- // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
- if(!(seg.flags & 0x10))
- result = 0;
- // check that the segment is readable
- if(seg.flags & 0x10) // is code or data segment
- {
- if(seg.flags & 0x08) // is code segment, so check if it's readable
- {
- if(!(seg.flags & 0x02))
- {
- result = 0;
- }
- else
- { // check if conforming, these are always readable, regardless of privilege
- if(!(seg.flags & 0x04))
- {
- // if not conforming, then we must check privilege levels (TODO: current privilege level check)
- if(((seg.flags >> 5) & 0x03) < (address & 0x03))
- result = 0;
- }
- }
- }
- }
- // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
- SetZF(result);
- }
- else
- {
- i386_trap(6, 0, 0);
- logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n");
- }
- break;
-
- case 5: /* VERW */
- if ( PROTECTED_MODE && !V8086_MODE )
- {
- if( modrm >= 0xc0 ) {
- address = LOAD_RM16(modrm);
- CYCLES(CYCLES_VERW_REG);
- } else {
- ea = GetEA(modrm,0,2);
- address = READ16(ea);
- CYCLES(CYCLES_VERW_MEM);
- }
- memset(&seg, 0, sizeof(seg));
- seg.selector = address;
- result = i386_load_protected_mode_segment(&seg,NULL);
- // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
- if(!(seg.flags & 0x10))
- result = 0;
- // check that the segment is writable
- if(seg.flags & 0x10) // is code or data segment
- {
- if(seg.flags & 0x08) // is code segment (and thus, not writable)
- {
- result = 0;
- }
- else
- { // is data segment
- if(!(seg.flags & 0x02))
- result = 0;
- }
- }
- // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
- if(((seg.flags >> 5) & 0x03) < (address & 0x03))
- result = 0;
- SetZF(result);
- }
- else
- {
- i386_trap(6, 0, 0);
- logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n");
- }
- break;
-
- default:
- report_invalid_modrm( "group0F00_32", modrm);
- break;
- }
-}
-
-void I386_OPS_BASE::I386OP(group0F01_32)() // Opcode 0x0f 01
-{
- UINT8 modrm = FETCH();
- UINT32 address, ea;
-
- switch( (modrm >> 3) & 0x7 )
- {
- case 0: /* SGDT */
- {
- if( modrm >= 0xc0 ) {
- address = LOAD_RM32(modrm);
- ea = i386_translate( CS, address, 1, 6 );
- } else {
- ea = GetEA(modrm,1,6);
- }
- WRITE16(ea, cpustate->gdtr.limit);
- WRITE32(ea + 2, cpustate->gdtr.base);
- CYCLES(CYCLES_SGDT);
- break;
- }
- case 1: /* SIDT */
- {
- if (modrm >= 0xc0)
- {
- address = LOAD_RM32(modrm);
- ea = i386_translate( CS, address, 1, 6 );
- }
- else
- {
- ea = GetEA(modrm,1,6);
- }
- WRITE16(ea, cpustate->idtr.limit);
- WRITE32(ea + 2, cpustate->idtr.base);
- CYCLES(CYCLES_SIDT);
- break;
- }
- case 2: /* LGDT */
- {
- if(PROTECTED_MODE && cpustate->CPL)
- FAULT(FAULT_GP,0)
- if( modrm >= 0xc0 ) {
- address = LOAD_RM32(modrm);
- ea = i386_translate( CS, address, 0, 6 );
- } else {
- ea = GetEA(modrm,0,6);
- }
- cpustate->gdtr.limit = READ16(ea);
- cpustate->gdtr.base = READ32(ea + 2);
- CYCLES(CYCLES_LGDT);
- break;
- }
- case 3: /* LIDT */
- {
- if(PROTECTED_MODE && cpustate->CPL)
- FAULT(FAULT_GP,0)
- if( modrm >= 0xc0 ) {
- address = LOAD_RM32(modrm);
- ea = i386_translate( CS, address, 0, 6 );
- } else {
- ea = GetEA(modrm,0,6);
- }
- cpustate->idtr.limit = READ16(ea);
- cpustate->idtr.base = READ32(ea + 2);
- CYCLES(CYCLES_LIDT);
- break;
- }
- case 4: /* SMSW */
- {
- if( modrm >= 0xc0 ) {
- // smsw stores all of cr0 into register
- STORE_RM32(modrm, cpustate->cr[0]);
- CYCLES(CYCLES_SMSW_REG);
- } else {
- /* always 16-bit memory operand */
- ea = GetEA(modrm,1,2);
- WRITE16(ea, cpustate->cr[0]);
- CYCLES(CYCLES_SMSW_MEM);
- }
- break;
- }
- case 6: /* LMSW */
- {
- if(PROTECTED_MODE && cpustate->CPL)
- FAULT(FAULT_GP,0)
- UINT16 b;
- if( modrm >= 0xc0 ) {
- b = LOAD_RM16(modrm);
- CYCLES(CYCLES_LMSW_REG);
- } else {
- ea = GetEA(modrm,0,2);
- CYCLES(CYCLES_LMSW_MEM);
- b = READ16(ea);
- }
- if(PROTECTED_MODE)
- b |= 0x0001; // cannot return to real mode using this instruction.
- cpustate->cr[0] &= ~0x0000000f;
- cpustate->cr[0] |= b & 0x0000000f;
- break;
- }
- default:
- report_invalid_modrm( "group0F01_32", modrm);
- break;
- }
-}
-
-void I386_OPS_BASE::I386OP(group0FBA_32)() // Opcode 0x0f ba
-{
- UINT8 modrm = FETCH();
-
- switch( (modrm >> 3) & 0x7 )
- {
- case 4: /* BT Rm32, i8 */
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT8 bit = FETCH();
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
-
- CYCLES(CYCLES_BT_IMM_REG);
- } else {
- UINT32 ea = GetEA(modrm,0,4);
- UINT32 dst = READ32(ea);
- UINT8 bit = FETCH();
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
-
- CYCLES(CYCLES_BT_IMM_MEM);
- }
- break;
- case 5: /* BTS Rm32, i8 */
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT8 bit = FETCH();
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst |= (1 << bit);
-
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_BTS_IMM_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- UINT8 bit = FETCH();
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst |= (1 << bit);
-
- WRITE32(ea, dst);
- CYCLES(CYCLES_BTS_IMM_MEM);
- }
- break;
- case 6: /* BTR Rm32, i8 */
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT8 bit = FETCH();
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst &= ~(1 << bit);
-
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_BTR_IMM_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- UINT8 bit = FETCH();
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst &= ~(1 << bit);
-
- WRITE32(ea, dst);
- CYCLES(CYCLES_BTR_IMM_MEM);
- }
- break;
- case 7: /* BTC Rm32, i8 */
- if( modrm >= 0xc0 ) {
- UINT32 dst = LOAD_RM32(modrm);
- UINT8 bit = FETCH();
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst ^= (1 << bit);
-
- STORE_RM32(modrm, dst);
- CYCLES(CYCLES_BTC_IMM_REG);
- } else {
- UINT32 ea = GetEA(modrm,1,4);
- UINT32 dst = READ32(ea);
- UINT8 bit = FETCH();
-
- if( dst & (1 << bit) )
- cpustate->CF = 1;
- else
- cpustate->CF = 0;
- dst ^= (1 << bit);
-
- WRITE32(ea, dst);
- CYCLES(CYCLES_BTC_IMM_MEM);
- }
- break;
- default:
- report_invalid_modrm( "group0FBA_32", modrm);
- break;
- }
-}
-
-void I386_OPS_BASE::I386OP(lar_r32_rm32)() // Opcode 0x0f 0x02
-{
- UINT8 modrm = FETCH();
- I386_SREG seg;
- UINT8 type;
-
- if(PROTECTED_MODE && !V8086_MODE)
- {
- memset(&seg,0,sizeof(seg));
- if(modrm >= 0xc0)
- {
- seg.selector = LOAD_RM32(modrm);
- CYCLES(CYCLES_LAR_REG);
- }
- else
- {
- UINT32 ea = GetEA(modrm,0,4);
- seg.selector = READ32(ea);
- CYCLES(CYCLES_LAR_MEM);
- }
- if(seg.selector == 0)
- {
- SetZF(0); // not a valid segment
- }
- else
- {
- UINT64 desc;
- if(!i386_load_protected_mode_segment(&seg,&desc))
- {
- SetZF(0);
- return;
- }
- UINT8 DPL = (seg.flags >> 5) & 3;
- if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
- {
- SetZF(0);
- return;
- }
- if(!(seg.flags & 0x10)) // special segment
- {
- // check for invalid segment types
- type = seg.flags & 0x000f;
- if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d)
- {
- SetZF(0); // invalid segment type
- }
- else
- {
- STORE_REG32(modrm,(desc>>32) & 0x00ffff00);
- SetZF(1);
- }
- }
- else
- {
- STORE_REG32(modrm,(desc>>32) & 0x00ffff00);
- SetZF(1);
- }
- }
- }
- else
- {
- // illegal opcode
- i386_trap(6,0, 0);
- logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n");
- }
-}
-
-void I386_OPS_BASE::I386OP(lsl_r32_rm32)() // Opcode 0x0f 0x03
-{
- UINT8 modrm = FETCH();
- UINT32 limit;
- I386_SREG seg;
-
- if(PROTECTED_MODE && !V8086_MODE)
- {
- memset(&seg, 0, sizeof(seg));
- if(modrm >= 0xc0)
- {
- seg.selector = LOAD_RM32(modrm);
- }
- else
- {
- UINT32 ea = GetEA(modrm,0,4);
- seg.selector = READ32(ea);
- }
- if(seg.selector == 0)
- {
- SetZF(0); // not a valid segment
- }
- else
- {
- UINT8 type;
- if(!i386_load_protected_mode_segment(&seg,NULL))
- {
- SetZF(0);
- return;
- }
- UINT8 DPL = (seg.flags >> 5) & 3;
- if(((DPL < cpustate->CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
- {
- SetZF(0);
- return;
- }
- type = seg.flags & 0x1f;
- switch(type)
- {
- case 0:
- case 4:
- case 5:
- case 6:
- case 7:
- case 8:
- case 10:
- case 12:
- case 13:
- case 14:
- case 15:
- SetZF(0);
- return;
- default:
- limit = seg.limit;
- STORE_REG32(modrm,limit);
- SetZF(1);
- }
- }
- }
- else
- i386_trap(6, 0, 0);
-}
-
-void I386_OPS_BASE::I386OP(bound_r32_m32_m32)() // Opcode 0x62
-{
- UINT8 modrm;
- INT32 val, low, high;
-
- modrm = FETCH();
-
- if (modrm >= 0xc0)
- {
- low = high = LOAD_RM32(modrm);
- }
- else
- {
- UINT32 ea = GetEA(modrm,0,8);
- low = READ32(ea + 0);
- high = READ32(ea + 4);
- }
- val = LOAD_REG32(modrm);
-
- if ((val < low) || (val > high))
- {
- CYCLES(CYCLES_BOUND_OUT_RANGE);
- i386_trap(5, 0, 0);
- }
- else
- {
- CYCLES(CYCLES_BOUND_IN_RANGE);
- }
-}
-
-void I386_OPS_BASE::I386OP(retf32)() // Opcode 0xcb
-{
- if(PROTECTED_MODE && !V8086_MODE)
- {
- i386_protected_mode_retf(0,1);
- }
- else
- {
- cpustate->eip = POP32();
- cpustate->sreg[CS].selector = POP32();
- i386_load_segment_descriptor( CS );
- CHANGE_PC(cpustate->eip);
- }
-
- CYCLES(CYCLES_RET_INTERSEG);
-}
-
-void I386_OPS_BASE::I386OP(retf_i32)() // Opcode 0xca
-{
- UINT16 count = FETCH16();
-
- if(PROTECTED_MODE && !V8086_MODE)
- {
- i386_protected_mode_retf(count,1);
- }
- else
- {
- cpustate->eip = POP32();
- cpustate->sreg[CS].selector = POP32();
- i386_load_segment_descriptor( CS );
- CHANGE_PC(cpustate->eip);
- REG32(ESP) += count;
- }
-
- CYCLES(CYCLES_RET_IMM_INTERSEG);
-}
-
-void I386_OPS_BASE::I386OP(load_far_pointer32)( int s)
-{
- UINT8 modrm = FETCH();
- UINT16 selector;
-
- if( modrm >= 0xc0 ) {
- report_invalid_modrm( "load_far_pointer32", modrm);
- } else {
- UINT32 ea = GetEA(modrm,0,6);
- STORE_REG32(modrm, READ32(ea + 0));
- selector = READ16(ea + 4);
- i386_sreg_load(selector,s,NULL);
- }
-}
-
-void I386_OPS_BASE::I386OP(lds32)() // Opcode 0xc5
-{
- I386OP(load_far_pointer32)( DS);
- CYCLES(CYCLES_LDS);
-}
-
-void I386_OPS_BASE::I386OP(lss32)() // Opcode 0x0f 0xb2
-{
- I386OP(load_far_pointer32)( SS);
- CYCLES(CYCLES_LSS);
-}
-
-void I386_OPS_BASE::I386OP(les32)() // Opcode 0xc4
-{
- I386OP(load_far_pointer32)( ES);
- CYCLES(CYCLES_LES);
-}
-
-void I386_OPS_BASE::I386OP(lfs32)() // Opcode 0x0f 0xb4
-{
- I386OP(load_far_pointer32)( FS);
- CYCLES(CYCLES_LFS);
-}
-
-void I386_OPS_BASE::I386OP(lgs32)() // Opcode 0x0f 0xb5
-{
- I386OP(load_far_pointer32)( GS);
- CYCLES(CYCLES_LGS);
-}