void bx_cpu_c::push_16(Bit16u value16) { Bit32u temp_ESP; #if BX_CPU_LEVEL >= 2 if (protected_mode()) { #if BX_CPU_LEVEL >= 3 if (bx_cpu. sregs[BX_SEG_REG_SS].cache.u.segment.d_b) temp_ESP = ESP; else #endif temp_ESP = SP; if (!can_push(&bx_cpu. sregs[BX_SEG_REG_SS].cache, temp_ESP, 2)) { BX_PANIC(("push_16(): can't push on stack")); exception(BX_SS_EXCEPTION, 0, 0); return; } /* access within limits */ write_virtual_word(BX_SEG_REG_SS, temp_ESP - 2, &value16); if (bx_cpu. sregs[BX_SEG_REG_SS].cache.u.segment.d_b) ESP -= 2; else SP -= 2; return; } else #endif { /* real mode */ if (bx_cpu. sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { if (ESP == 1) BX_PANIC(("CPU shutting down due to lack of stack space, ESP==1")); ESP -= 2; temp_ESP = ESP; } else { if (SP == 1) BX_PANIC(("CPU shutting down due to lack of stack space, SP==1")); SP -= 2; temp_ESP = SP; } write_virtual_word(BX_SEG_REG_SS, temp_ESP, &value16); return; } }
/* DB /7 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FSTP_EXTENDED_REAL(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); FPU_update_last_instruction(i); clear_C1(); floatx80 save_reg = floatx80_default_nan; /* The masked response */ if (IS_TAG_EMPTY(0)) { FPU_exception(FPU_EX_Stack_Underflow); if (! BX_CPU_THIS_PTR the_i387.is_IA_masked()) BX_NEXT_INSTR(i); } else { save_reg = BX_READ_FPU_REG(0); } write_virtual_qword(i->seg(), RMAddr(i), save_reg.fraction); write_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask(), save_reg.exp); BX_CPU_THIS_PTR the_i387.FPU_pop(); BX_NEXT_INSTR(i); }
/* DF /1 */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FISTTP16(bxInstruction_c *i) { #if BX_SUPPORT_SSE >= 3 BX_CPU_THIS_PTR prepareFPU(i); Bit16s save_reg = int16_indefinite; /* The masked response */ clear_C1(); if (IS_TAG_EMPTY(0)) { BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow); if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked())) return; } else { float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = floatx80_to_int16_round_to_zero(BX_READ_FPU_REG(0), status); if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags)) return; } write_virtual_word(i->seg(), RMAddr(i), (Bit16u)(save_reg)); BX_CPU_THIS_PTR the_i387.FPU_pop(); #else BX_INFO(("FISTTP16: required SSE3, use --enable-sse option")); UndefinedOpcode(i); #endif }
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_MwGw(bxInstruction_c *i) { Bit16u val16 = BX_READ_16BIT_REG(i->nnn()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word(i->seg(), eaddr, bx_bswap16(val16)); BX_NEXT_INSTR(i); }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwSwM(bxInstruction_c *i) { /* Illegal to use nonexisting segments */ if (i->nnn() >= 6) { BX_INFO(("MOV_EwSw: using of nonexisting segment register %d", i->nnn())); UndefinedOpcode(i); } BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u seg_reg = BX_CPU_THIS_PTR sregs[i->nnn()].selector.value; write_virtual_word(i->seg(), RMAddr(i), seg_reg); }
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FIST_WORD_INTEGER(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); FPU_update_last_instruction(i); Bit16u x87_sw = FPU_PARTIAL_STATUS; Bit16s save_reg = int16_indefinite; int pop_stack = i->nnn() & 1; clear_C1(); if (IS_TAG_EMPTY(0)) { FPU_exception(FPU_EX_Stack_Underflow); if (! BX_CPU_THIS_PTR the_i387.is_IA_masked()) BX_NEXT_INSTR(i); } else { float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = floatx80_to_int16(BX_READ_FPU_REG(0), status); if (FPU_exception(status.float_exception_flags, 1)) BX_NEXT_INSTR(i); } // store to the memory might generate an exception, in this case origial FPU_SW must be kept swap_values16u(x87_sw, FPU_PARTIAL_STATUS); write_virtual_word(i->seg(), RMAddr(i), (Bit16u)(save_reg)); FPU_PARTIAL_STATUS = x87_sw; if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); BX_NEXT_INSTR(i); }
void bx_cpu_c::POP_Ew(BxInstruction_t *i) { Bit16u val16; pop_16(&val16); if (i->mod == 0xc0) { BX_WRITE_16BIT_REG(i->rm, val16); } else { // Note: there is one little weirdism here. When 32bit addressing // is used, it is possible to use ESP in the modrm addressing. // If used, the value of ESP after the pop is used to calculate // the address. if (i->as_32 && (i->mod!=0xc0) && (i->rm==4) && (i->base==4)) { i->ResolveModrm(i); } write_virtual_word(i->seg, i->rm_addr, &val16); } }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::FIST_WORD_INTEGER(bxInstruction_c *i) { #if BX_SUPPORT_FPU BX_CPU_THIS_PTR prepareFPU(i); Bit16s save_reg = int16_indefinite; int pop_stack = i->nnn() & 1; clear_C1(); if (IS_TAG_EMPTY(0)) { BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow); if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked())) return; } else { float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); save_reg = floatx80_to_int16(BX_READ_FPU_REG(0), status); if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags)) return; } write_virtual_word(i->seg(), RMAddr(i), (Bit16u)(save_reg)); if (pop_stack) BX_CPU_THIS_PTR the_i387.FPU_pop(); #else BX_INFO(("FIST(P)_WORD_INTEGER: required FPU, configure --enable-fpu")); #endif }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwGwM(bxInstruction_c *i) { BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word(i->seg(), RMAddr(i), BX_READ_16BIT_REG(i->nnn())); }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwIwM(bxInstruction_c *i) { BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word(i->seg(), RMAddr(i), i->Iw()); }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_OdAX(bxInstruction_c *i) { write_virtual_word(i->seg(), i->Id(), AX); }
void BX_CPP_AttrRegparmN(1) BX_CPU_C::FBSTP_PACKED_BCD(bxInstruction_c *i) { #if BX_SUPPORT_FPU BX_CPU_THIS_PTR prepareFPU(i); /* * The packed BCD integer indefinite encoding (FFFFC000000000000000H) * is stored in response to a masked floating-point invalid-operation * exception. */ Bit16u save_reg_hi = 0xFFFF; Bit64u save_reg_lo = BX_CONST64(0xC000000000000000); clear_C1(); if (IS_TAG_EMPTY(0)) { BX_CPU_THIS_PTR FPU_exception(FPU_EX_Stack_Underflow); if (! (BX_CPU_THIS_PTR the_i387.is_IA_masked())) return; } else { float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 reg = BX_READ_FPU_REG(0); Bit64s save_val = floatx80_to_int64(reg, status); int sign = (reg.exp & 0x8000) != 0; if (sign) save_val = -save_val; if (save_val > BX_CONST64(999999999999999999)) { float_raise(status, float_flag_invalid); } if (! (status.float_exception_flags & float_flag_invalid)) { save_reg_hi = (sign) ? 0x8000 : 0; save_reg_lo = 0; for (int i=0; i<16; i++) { save_reg_lo += ((Bit64u)(save_val % 10)) << (4*i); save_val /= 10; } save_reg_hi += (Bit16u)(save_val % 10); save_val /= 10; save_reg_hi += (Bit16u)(save_val % 10) << 4; } /* check for fpu arithmetic exceptions */ if (BX_CPU_THIS_PTR FPU_exception(status.float_exception_flags)) return; } // write packed bcd to memory write_virtual_qword(i->seg(), RMAddr(i), save_reg_lo); write_virtual_word (i->seg(), RMAddr(i) + 8, save_reg_hi); BX_CPU_THIS_PTR the_i387.FPU_pop(); #else BX_INFO(("FBSTP_PACKED_BCD: required FPU, configure --enable-fpu")); #endif }
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FBSTP_PACKED_BCD(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareFPU(i); RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); FPU_update_last_instruction(i); Bit16u x87_sw = FPU_PARTIAL_STATUS; /* * The packed BCD integer indefinite encoding (FFFFC000000000000000H) * is stored in response to a masked floating-point invalid-operation * exception. */ Bit16u save_reg_hi = 0xFFFF; Bit64u save_reg_lo = BX_CONST64(0xC000000000000000); clear_C1(); if (IS_TAG_EMPTY(0)) { FPU_exception(FPU_EX_Stack_Underflow); if (! BX_CPU_THIS_PTR the_i387.is_IA_masked()) BX_NEXT_INSTR(i); } else { float_status_t status = FPU_pre_exception_handling(BX_CPU_THIS_PTR the_i387.get_control_word()); floatx80 reg = BX_READ_FPU_REG(0); Bit64s save_val = floatx80_to_int64(reg, status); int sign = (reg.exp & 0x8000) != 0; if (sign) save_val = -save_val; if (save_val > BX_CONST64(999999999999999999)) { status.float_exception_flags = float_flag_invalid; // throw away other flags } if (! (status.float_exception_flags & float_flag_invalid)) { save_reg_hi = (sign) ? 0x8000 : 0; save_reg_lo = 0; for (int i=0; i<16; i++) { save_reg_lo += ((Bit64u)(save_val % 10)) << (4*i); save_val /= 10; } save_reg_hi += (Bit16u)(save_val % 10); save_val /= 10; save_reg_hi += (Bit16u)(save_val % 10) << 4; } /* check for fpu arithmetic exceptions */ if (FPU_exception(status.float_exception_flags, 1)) BX_NEXT_INSTR(i); } // store to the memory might generate an exception, in this case origial FPU_SW must be kept swap_values16u(x87_sw, FPU_PARTIAL_STATUS); // write packed bcd to memory write_virtual_qword(i->seg(), RMAddr(i), save_reg_lo); write_virtual_word(i->seg(), (RMAddr(i) + 8) & i->asize_mask(), save_reg_hi); FPU_PARTIAL_STATUS = x87_sw; BX_CPU_THIS_PTR the_i387.FPU_pop(); BX_NEXT_INSTR(i); }
BX_CPU_C::write_virtual_tword(unsigned s, bx_address offset, floatx80 *data) { // store floating point register write_virtual_qword(s, offset+0, &data->fraction); write_virtual_word (s, offset+8, &data->exp); }