BX_CPU_C::read_virtual_dqword(unsigned s, bx_address offset, Bit8u *data) { // Read Double Quadword. Bit64u *qwords = (Bit64u*) data; read_virtual_qword(s, offset+Host1stDWordOffset, &qwords[0]); read_virtual_qword(s, offset+Host2ndDWordOffset, &qwords[1]); }
/* 0F 0F /r 0D */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::PI2FD_PqQq(bxInstruction_c *i) { BxPackedMmxRegister result, op; BX_CPU_THIS_PTR prepareMMX(); /* op is a register or memory reference */ if (i->modC0()) { op = BX_READ_MMX_REG(i->rm()); } else { BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), RMAddr(i)); } float_status_t status_word; prepare_softfloat_status_word(status_word, float_round_to_zero); MMXUD0(result) = int32_to_float32(MMXSD0(op), status_word); MMXUD1(result) = int32_to_float32(MMXSD1(op), status_word); /* now write result back to destination */ BX_WRITE_MMX_REG(i->nnn(), result); }
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_DOUBLE_REAL(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i)); FPU_update_last_instruction(i); clear_C1(); if (! IS_TAG_EMPTY(-1)) { FPU_stack_overflow(); BX_NEXT_INSTR(i); } float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); // convert to floatx80 format floatx80 result = float64_to_floatx80(load_reg, status); unsigned unmasked = FPU_exception(status.float_exception_flags); if (! (unmasked & FPU_CW_Invalid)) { BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); } BX_NEXT_INSTR(i); }
/* 0F 0F /r B7 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHRW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->nnn()), op2, result; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->rm()); } else { BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), RMAddr(i)); } Bit32s product1 = Bit32s(MMXSW0(op1)) * Bit32s(MMXSW0(op2)) + 0x8000; Bit32s product2 = Bit32s(MMXSW1(op1)) * Bit32s(MMXSW1(op2)) + 0x8000; Bit32s product3 = Bit32s(MMXSW2(op1)) * Bit32s(MMXSW2(op2)) + 0x8000; Bit32s product4 = Bit32s(MMXSW3(op1)) * Bit32s(MMXSW3(op2)) + 0x8000; MMXUW0(result) = Bit16u(product1 >> 16); MMXUW1(result) = Bit16u(product2 >> 16); MMXUW2(result) = Bit16u(product3 >> 16); MMXUW3(result) = Bit16u(product4 >> 16); /* now write result back to destination */ BX_WRITE_MMX_REG(i->nnn(), result); }
void BX_CPU_C::BSR_GqEq(bxInstruction_c *i) { /* for 64 bit operand size mode */ Bit64u op1_64, op2_64; /* op2_64 is a register or memory reference */ if (i->modC0()) { op2_64 = BX_READ_64BIT_REG(i->rm()); } else { /* pointer, segment address pair */ read_virtual_qword(i->seg(), RMAddr(i), &op2_64); } if (op2_64 == 0) { assert_ZF(); /* op1_64 undefined */ return; } op1_64 = 63; while ( (op2_64 & BX_CONST64(0x8000000000000000)) == 0 ) { op1_64--; op2_64 <<= 1; } SET_FLAGS_OSZAPC_RESULT_64(op1_64, BX_INSTR_BITSCAN64); /* now write result back to destination */ BX_WRITE_64BIT_REG(i->nnn(), op1_64); }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_DOUBLE_REAL(bxInstruction_c *i) { #if BX_SUPPORT_FPU BX_CPU_THIS_PTR prepareFPU(i); float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i)); clear_C1(); if (! IS_TAG_EMPTY(-1)) { BX_CPU_THIS_PTR FPU_stack_overflow(); return; } float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); // convert to floatx80 format floatx80 result = float64_to_floatx80(load_reg, status); if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags)) return; BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); #else BX_INFO(("FLD_DOUBLE_REAL: required FPU, configure --enable-fpu")); #endif }
/* Opcode: VEX.66.0F.38 2D (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMASKMOVPD_VpdHpdMpd(bxInstruction_c *i) { BxPackedAvxRegister mask = BX_READ_AVX_REG(i->vvv()), result; unsigned len = i->getVL(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_X86_64 if (i->as64L()) { for (unsigned n=0; n < (2*len); n++) { if (mask.avx32u(n*2+1) & 0x80000000) { if (! IsCanonical(get_laddr64(i->seg(), eaddr + 8*n))) exception(int_number(i->seg()), 0); } } } #endif for (int n=2*len-1; n >= 0; n--) { if (mask.avx32u(n*2+1) & 0x80000000) result.avx64u(n) = read_virtual_qword(i->seg(), (eaddr + 8*n) & i->asize_mask()); else result.avx64u(n) = 0; } BX_WRITE_AVX_REGZ(i->nnn(), result, len); BX_NEXT_INSTR(i); }
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_GqMq(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u val64 = read_virtual_qword(i->seg(), eaddr); BX_WRITE_64BIT_REG(i->nnn(), bx_bswap64(val64)); BX_NEXT_INSTR(i); }
/* VEX.66.0F 16 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVHPD_VpdHpdMq(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); BxPackedXmmRegister op; op.xmm64u(0) = BX_READ_XMM_REG_LO_QWORD(i->vvv()); op.xmm64u(1) = read_virtual_qword(i->seg(), eaddr); BX_WRITE_XMM_REG_CLEAR_HIGH(i->nnn(), op); BX_NEXT_INSTR(i); }
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FCOM_DOUBLE_REAL(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); int pop_stack = i->nnn() & 1, rc; RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); float64 load_reg = read_virtual_qword(i->seg(), RMAddr(i)); BX_CPU_THIS_PTR FPU_update_last_instruction(i); clear_C1(); if (IS_TAG_EMPTY(0)) { FPU_exception(FPU_EX_Stack_Underflow); setcc(FPU_SW_C0|FPU_SW_C2|FPU_SW_C3); 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()); floatx80 a = BX_READ_FPU_REG(0); if (floatx80_is_nan(a) || floatx80_is_unsupported(a) || float64_is_nan(load_reg)) { rc = float_relation_unordered; float_raise(status, float_flag_invalid); } else { rc = floatx80_compare(a, float64_to_floatx80(load_reg, status), status); } setcc(status_word_flags_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); }
void BX_CPU_C::LSS_GqMp(bxInstruction_c *i) { if (i->modC0()) { BX_DEBUG(("LSS_GqMp: invalid use of LSS, must be memory reference!")); UndefinedOpcode(i); } Bit64u reg_64; Bit16u ss; read_virtual_qword(i->seg(), RMAddr(i), ®_64); read_virtual_word(i->seg(), RMAddr(i) + 8, &ss); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], ss); BX_WRITE_64BIT_REG(i->nnn(), reg_64); }
/* DF /4 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FBLD_PACKED_BCD(bxInstruction_c *i) { #if BX_SUPPORT_FPU BX_CPU_THIS_PTR prepareFPU(i); // read packed bcd from memory Bit16u hi2 = read_virtual_word (i->seg(), RMAddr(i) + 8); Bit64u lo8 = read_virtual_qword(i->seg(), RMAddr(i)); clear_C1(); if (! IS_TAG_EMPTY(-1)) { BX_CPU_THIS_PTR FPU_stack_overflow(); return; } // convert packed BCD to 64-bit integer Bit64s scale = 1; Bit64s val64 = 0; for (int n = 0; n < 16; n++) { val64 += (lo8 & 0x0f) * scale; lo8 >>= 4; scale *= 10; } val64 += (hi2 & 0x0f) * scale; val64 += ((hi2>>4) & 0x0f) * scale * 10; floatx80 result = int64_to_floatx80(val64); if (hi2 & 0x8000) // set negative floatx80_chs(result); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); #else BX_INFO(("FBLD_PACKED_BCD: required FPU, configure --enable-fpu")); #endif }
/* DF /4 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FBLD_PACKED_BCD(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u hi2 = read_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask()); Bit64u lo8 = read_virtual_qword(i->seg(), RMAddr(i)); FPU_update_last_instruction(i); clear_C1(); if (! IS_TAG_EMPTY(-1)) { FPU_stack_overflow(); BX_NEXT_INSTR(i); } // convert packed BCD to 64-bit integer Bit64s scale = 1; Bit64s val64 = 0; for (int n = 0; n < 16; n++) { val64 += (lo8 & 0x0f) * scale; lo8 >>= 4; scale *= 10; } val64 += (hi2 & 0x0f) * scale; val64 += ((hi2>>4) & 0x0f) * scale * 10; floatx80 result = int64_to_floatx80(val64); if (hi2 & 0x8000) // set negative floatx80_chs(result); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); BX_NEXT_INSTR(i); }
/* DF /5 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FILD_QWORD_INTEGER(bxInstruction_c *i) { #if BX_SUPPORT_FPU BX_CPU_THIS_PTR prepareFPU(i); Bit64s load_reg = (Bit64s) read_virtual_qword(i->seg(), RMAddr(i)); clear_C1(); if (! IS_TAG_EMPTY(-1)) { BX_CPU_THIS_PTR FPU_stack_overflow(); return; } floatx80 result = int64_to_floatx80(load_reg); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); #else BX_INFO(("FILD_QWORD_INTEGER: required FPU, configure --enable-fpu")); #endif }
/* 0F 0F /r BB */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::PSWAPD_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister result, op; /* op is a register or memory reference */ if (i->modC0()) { op = BX_READ_MMX_REG(i->rm()); } else { BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), RMAddr(i)); } MMXUD0(result) = MMXUD1(op); MMXUD1(result) = MMXUD0(op); /* now write result back to destination */ BX_WRITE_MMX_REG(i->nnn(), result); }
/* DF /5 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FILD_QWORD_INTEGER(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64s load_reg = (Bit64s) read_virtual_qword(i->seg(), RMAddr(i)); FPU_update_last_instruction(i); clear_C1(); if (! IS_TAG_EMPTY(-1)) { FPU_stack_overflow(); } else { floatx80 result = int64_to_floatx80(load_reg); BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); } BX_NEXT_INSTR(i); }
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FLD_EXTENDED_REAL(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); floatx80 result; RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); result.fraction = read_virtual_qword(i->seg(), RMAddr(i)); result.exp = read_virtual_word(i->seg(), (RMAddr(i)+8) & i->asize_mask()); FPU_update_last_instruction(i); clear_C1(); if (! IS_TAG_EMPTY(-1)) { FPU_stack_overflow(); } else { BX_CPU_THIS_PTR the_i387.FPU_push(); BX_WRITE_FPU_REG(result, 0); } BX_NEXT_INSTR(i); }
BX_CPU_C::read_virtual_tword(unsigned s, bx_address offset, floatx80 *data) { // read floating point register read_virtual_qword(s, offset+0, &data->fraction); read_virtual_word (s, offset+8, &data->exp); }