BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FUCOMI_ST0_STj(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); BX_CPU_THIS_PTR FPU_update_last_instruction(i); int pop_stack = i->b1() & 4; clear_C1(); if (IS_TAG_EMPTY(0) || IS_TAG_EMPTY(i->rm())) { FPU_exception(FPU_EX_Stack_Underflow); setEFlagsOSZAPC(EFlagsZFMask | EFlagsPFMask | EFlagsCFMask); if(BX_CPU_THIS_PTR the_i387.is_IA_masked()) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } BX_NEXT_INSTR(i); } float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); int rc = floatx80_compare_quiet(BX_READ_FPU_REG(0), BX_READ_FPU_REG(i->rm()), status); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); if (! FPU_exception(status.float_exception_flags)) { if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); } BX_NEXT_INSTR(i); }
/* 66 0F 3A 62 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPISTRM_VdqWdqIb(bxInstruction_c *i) { #if (BX_SUPPORT_SSE >= 5) || (BX_SUPPORT_SSE >= 4 && BX_SUPPORT_SSE_EXTENSION > 0) BX_CPU_THIS_PTR prepareSSE(); BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2, result; Bit8u imm8 = i->Ib(); /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_XMM_REG(i->rm()); } else { BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op2); } // compare all pairs of Ai, Bj bx_bool BoolRes[16][16]; compare_strings(BoolRes, op1, op2, imm8); unsigned num_elements = (imm8 & 0x1) ? 8 : 16; unsigned len1 = find_eos(op1, imm8); unsigned len2 = find_eos(op2, imm8); Bit16u result2 = aggregate(BoolRes, len1, len2, imm8); // As defined by imm8[6], result2 is then either stored to the least // significant bits of XMM0 (zero extended to 128 bits) or expanded // into a byte/word-mask and then stored to XMM0 if (imm8 & 0x40) { if (num_elements == 8) { for (int index = 0; index < 8; index++) result.xmm16u(index) = (result2 & (1<<index)) ? 0xffff : 0; } else { // num_elements = 16 for (int index = 0; index < 16; index++) result.xmmubyte(index) = (result2 & (1<<index)) ? 0xff : 0; } } else { result.xmm64u(1) = 0; result.xmm64u(0) = (Bit64u) result2; } Bit32u flags = 0; if (result2 != 0) flags |= EFlagsCFMask; if (len1 < num_elements) flags |= EFlagsSFMask; if (len2 < num_elements) flags |= EFlagsZFMask; if (result2 & 0x1) flags |= EFlagsOFMask; setEFlagsOSZAPC(flags); BX_WRITE_XMM_REG(0, result); /* store result XMM0 */ #else BX_INFO(("PCMPISTRM_VdqWdqIb: required SSE4.2, use --enable-sse and --enable-sse-extension options")); UndefinedOpcode(i); #endif }
/* 66 0F 3A 63 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPISTRI_VdqWdqIb(bxInstruction_c *i) { #if (BX_SUPPORT_SSE >= 5) || (BX_SUPPORT_SSE >= 4 && BX_SUPPORT_SSE_EXTENSION > 0) BX_CPU_THIS_PTR prepareSSE(); BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2; Bit8u imm8 = i->Ib(); /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_XMM_REG(i->rm()); } else { BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ readVirtualDQwordAligned(i->seg(), RMAddr(i), (Bit8u *) &op2); } // compare all pairs of Ai, Bj bx_bool BoolRes[16][16]; compare_strings(BoolRes, op1, op2, imm8); unsigned num_elements = (imm8 & 0x1) ? 8 : 16; int index; unsigned len1 = find_eos(op1, imm8); unsigned len2 = find_eos(op2, imm8); Bit16u result2 = aggregate(BoolRes, len1, len2, imm8); // The index of the first (or last, according to imm8[6]) set bit of result2 // is returned to ECX. If no bits are set in IntRes2, ECX is set to 16 (8) if (imm8 & 0x40) { // The index returned to ECX is of the MSB in result2 for (index=num_elements-1; index>=0; index--) if (result2 & (1<<index)) break; if (index < 0) index = num_elements; } else { // The index returned to ECX is of the LSB in result2 for (index=0; index<(int)num_elements; index++) if (result2 & (1<<index)) break; } RCX = index; Bit32u flags = 0; if (result2 != 0) flags |= EFlagsCFMask; if (len1 < num_elements) flags |= EFlagsSFMask; if (len2 < num_elements) flags |= EFlagsZFMask; if (result2 & 0x1) flags |= EFlagsOFMask; setEFlagsOSZAPC(flags); #else BX_INFO(("PCMPISTRI_VdqWdqIb: required SSE4.2, use --enable-sse and --enable-sse-extension options")); UndefinedOpcode(i); #endif }
/* 66 0F 3A 60 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPESTRM_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->rm()), result; Bit8u imm8 = i->Ib(); // compare all pairs of Ai, Bj Bit8u BoolRes[16][16]; compare_strings(BoolRes, op1, op2, imm8); unsigned len1, len2, num_elements = (imm8 & 0x1) ? 8 : 16; #if BX_SUPPORT_X86_64 if (i->os64L()) { len1 = find_eos64(RAX, imm8); len2 = find_eos64(RDX, imm8); } else #endif { len1 = find_eos32(EAX, imm8); len2 = find_eos32(EDX, imm8); } Bit16u result2 = aggregate(BoolRes, len1, len2, imm8); // As defined by imm8[6], result2 is then either stored to the least // significant bits of XMM0 (zero extended to 128 bits) or expanded // into a byte/word-mask and then stored to XMM0 if (imm8 & 0x40) { if (num_elements == 8) { for (int index = 0; index < 8; index++) result.xmm16u(index) = (result2 & (1<<index)) ? 0xffff : 0; } else { // num_elements = 16 for (int index = 0; index < 16; index++) result.xmmubyte(index) = (result2 & (1<<index)) ? 0xff : 0; } } else { result.xmm64u(1) = 0; result.xmm64u(0) = (Bit64u) result2; } Bit32u flags = 0; if (result2 != 0) flags |= EFlagsCFMask; if (len1 < num_elements) flags |= EFlagsSFMask; if (len2 < num_elements) flags |= EFlagsZFMask; if (result2 & 0x1) flags |= EFlagsOFMask; setEFlagsOSZAPC(flags); BX_WRITE_XMM_REGZ(0, result, i->getVL()); /* store result XMM0 */ BX_NEXT_INSTR(i); }
void BX_CPU_C::write_eflags_fpu_compare(int float_relation) { switch(float_relation) { case float_relation_unordered: setEFlagsOSZAPC(EFlagsZFMask | EFlagsPFMask | EFlagsCFMask); break; case float_relation_greater: setEFlagsOSZAPC(0); break; case float_relation_less: setEFlagsOSZAPC(EFlagsCFMask); break; case float_relation_equal: setEFlagsOSZAPC(EFlagsZFMask); break; default: BX_PANIC(("write_eflags: unknown floating point compare relation")); } }
void BX_CPU_C::AND_EdId(bxInstruction_c *i) { Bit32u op2_32, op1_32, result_32; op2_32 = i->Id(); if (i->modC0()) { op1_32 = BX_READ_32BIT_REG(i->rm()); #if defined(BX_HostAsm_And32) Bit32u flags32; asmAnd32(result_32, op1_32, op2_32, flags32); setEFlagsOSZAPC(flags32); #else result_32 = op1_32 & op2_32; #endif BX_WRITE_32BIT_REGZ(i->rm(), result_32); } else { read_RMW_virtual_dword(i->seg(), RMAddr(i), &op1_32); #if defined(BX_HostAsm_And32) Bit32u flags32; asmAnd32(result_32, op1_32, op2_32, flags32); setEFlagsOSZAPC(flags32); #else result_32 = op1_32 & op2_32; #endif write_RMW_virtual_dword(result_32); } #if !defined(BX_HostAsm_And32) SET_FLAGS_OSZAPC_RESULT_32(result_32, BX_INSTR_LOGIC32); #endif }
/* 66 0F 3A 61 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPESTRI_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->nnn()), op2 = BX_READ_XMM_REG(i->rm()); Bit8u imm8 = i->Ib(); // compare all pairs of Ai, Bj Bit8u BoolRes[16][16]; compare_strings(BoolRes, op1, op2, imm8); unsigned len1, len2, num_elements = (imm8 & 0x1) ? 8 : 16; int index; #if BX_SUPPORT_X86_64 if (i->os64L()) { len1 = find_eos64(RAX, imm8); len2 = find_eos64(RDX, imm8); } else #endif { len1 = find_eos32(EAX, imm8); len2 = find_eos32(EDX, imm8); } Bit16u result2 = aggregate(BoolRes, len1, len2, imm8); // The index of the first (or last, according to imm8[6]) set bit of result2 // is returned to ECX. If no bits are set in IntRes2, ECX is set to 16 (8) if (imm8 & 0x40) { // The index returned to ECX is of the MSB in result2 for (index=num_elements-1; index>=0; index--) if (result2 & (1<<index)) break; if (index < 0) index = num_elements; } else { // The index returned to ECX is of the LSB in result2 for (index=0; index<(int)num_elements; index++) if (result2 & (1<<index)) break; } RCX = index; Bit32u flags = 0; if (result2 != 0) flags |= EFlagsCFMask; if (len1 < num_elements) flags |= EFlagsSFMask; if (len2 < num_elements) flags |= EFlagsZFMask; if (result2 & 0x1) flags |= EFlagsOFMask; setEFlagsOSZAPC(flags); BX_NEXT_INSTR(i); }
void BX_CPU_C::TEST_EAXId(bxInstruction_c *i) { Bit32u op2_32, op1_32; op1_32 = EAX; op2_32 = i->Id(); #if defined(BX_HostAsm_Test32) Bit32u flags32; asmTest32(op1_32, op2_32, flags32); setEFlagsOSZAPC(flags32); #else Bit32u result_32 = op1_32 & op2_32; SET_FLAGS_OSZAPC_RESULT_32(result_32, BX_INSTR_LOGIC32); #endif }
/* Opcode: VEX.66.0F.38.17 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPTEST_VdqWdqR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->nnn()), op2 = BX_READ_AVX_REG(i->rm()); unsigned len = i->getVL(); unsigned result = EFlagsZFMask | EFlagsCFMask; for (unsigned n=0; n < (2*len); n++) { if ((op2.avx64u(n) & op1.avx64u(n)) != 0) result &= ~EFlagsZFMask; if ((op2.avx64u(n) & ~op1.avx64u(n)) != 0) result &= ~EFlagsCFMask; } setEFlagsOSZAPC(result); BX_NEXT_INSTR(i); }
void BX_CPU_C::TEST_EdId(bxInstruction_c *i) { Bit32u op2_32, op1_32; op2_32 = i->Id(); if (i->modC0()) { op1_32 = BX_READ_32BIT_REG(i->rm()); } else { read_virtual_dword(i->seg(), RMAddr(i), &op1_32); } #if defined(BX_HostAsm_Test32) Bit32u flags32; asmTest32(op1_32, op2_32, flags32); setEFlagsOSZAPC(flags32); #else Bit32u result_32 = op1_32 & op2_32; SET_FLAGS_OSZAPC_RESULT_32(result_32, BX_INSTR_LOGIC32); #endif }
void BX_CPU_C::OR_GdEd(bxInstruction_c *i) { Bit32u op1_32, op2_32, result_32; op1_32 = BX_READ_32BIT_REG(i->nnn()); if (i->modC0()) { op2_32 = BX_READ_32BIT_REG(i->rm()); } else { read_virtual_dword(i->seg(), RMAddr(i), &op2_32); } #if defined(BX_HostAsm_Or32) Bit32u flags32; asmOr32(result_32, op1_32, op2_32, flags32); setEFlagsOSZAPC(flags32); #else result_32 = op1_32 | op2_32; SET_FLAGS_OSZAPC_RESULT_32(result_32, BX_INSTR_LOGIC32); #endif BX_WRITE_32BIT_REGZ(i->nnn(), result_32); }