implement fbstp (close #708)

This commit is contained in:
Fabian 2022-08-01 21:24:35 +09:00
parent cf31709ec5
commit f1ebdb1c72
5 changed files with 61 additions and 14 deletions

View file

@ -346,9 +346,9 @@ const encodings = [
{ opcode: 0xDF, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1 },
{ opcode: 0xDF, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1 },
{ opcode: 0xDF, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, skip_mem: 1 }, // unimplemented: Binary Coded Decimals
{ opcode: 0xDF, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, },
{ opcode: 0xDF, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, skip_mem: 1 }, // unimplemented: Binary Coded Decimals
{ opcode: 0xDF, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, },
{ opcode: 0xDF, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1 },
{ opcode: 0xDF, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1 },
{ opcode: 0xDF, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1 },
// loop, jcxz, etc.
{ opcode: 0xE0, os: 1, imm8s: 1, no_block_boundary_in_interpreted: 1, skip: 1, block_boundary: 1, jump_offset_imm: 1, custom: 1, conditional_jump: 1, },

View file

@ -625,6 +625,35 @@ pub unsafe fn fpu_fstp(r: i32) {
fpu_pop();
}
#[no_mangle]
pub unsafe fn fpu_fbstp(addr: i32) {
match writable_or_pagefault(addr, 26) {
Ok(()) => *page_fault = false,
Err(()) => {
*page_fault = true;
return;
},
}
let st0 = fpu_get_st0();
let mut x = st0.to_i64().unsigned_abs();
if x <= 99_9999_9999_9999_9999 {
for i in 0..=8 {
let low = x % 10;
x /= 10;
let high = x % 10;
x /= 10;
safe_write8(addr + i, (high as i32) << 4 | low as i32).unwrap();
}
safe_write8(addr + 9, if st0.sign() { 0x80 } else { 0 }).unwrap();
}
else {
fpu_invalid_arithmetic();
safe_write64(addr + 0, 0xC000_0000_0000_0000).unwrap();
safe_write16(addr + 8, 0xFFFF).unwrap();
}
fpu_pop();
}
#[no_mangle]
pub unsafe fn fpu_fsub(target_index: i32, val: F80) {
let st0 = fpu_get_st0();

View file

@ -1989,11 +1989,7 @@ pub unsafe fn instr_DF_4_mem(_addr: i32) {
fpu_unimpl();
}
pub unsafe fn instr_DF_5_mem(addr: i32) { fpu_fildm64(addr); }
#[no_mangle]
pub unsafe fn instr_DF_6_mem(_addr: i32) {
dbg_log!("fbstp");
fpu_unimpl();
}
pub unsafe fn instr_DF_6_mem(addr: i32) { fpu_fbstp(addr); }
pub unsafe fn instr_DF_7_mem(addr: i32) { fpu_fistm64p(addr); }
#[no_mangle]
@ -2014,7 +2010,6 @@ pub unsafe fn instr_DF_4_reg(r: i32) {
};
}
pub unsafe fn instr_DF_5_reg(r: i32) { fpu_fucomip(r); }
#[no_mangle]
pub unsafe fn instr_DF_6_reg(r: i32) { fpu_fcomip(r); }
pub unsafe fn instr_DF_7_reg(_r: i32) { trigger_ud(); }

View file

@ -3776,9 +3776,22 @@ pub fn instr_DF_5_reg_jit(ctx: &mut JitContext, r: u32) {
}
pub fn instr_DF_6_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte) {
dbg_log!("fbstp");
codegen::gen_modrm_resolve(ctx, modrm_byte);
codegen::gen_trigger_ud(ctx);
codegen::gen_set_previous_eip_offset_from_eip_with_low_bits(
ctx.builder,
ctx.start_of_current_instruction as i32 & 0xFFF,
);
codegen::gen_move_registers_from_locals_to_memory(ctx);
ctx.builder.call_fn1("fpu_fbstp");
codegen::gen_move_registers_from_memory_to_locals(ctx);
codegen::gen_get_page_fault(ctx.builder);
ctx.builder.if_void();
codegen::gen_debug_track_jit_exit(ctx.builder, ctx.start_of_current_instruction);
ctx.builder.br(ctx.exit_label);
ctx.builder.block_end();
}
pub fn instr_DF_6_reg_jit(ctx: &mut JitContext, r: u32) {
ctx.builder.const_i32(r as i32);

View file

@ -1050,7 +1050,7 @@ void test_fbcd(double a)
double b;
asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
//asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
}
@ -1180,8 +1180,18 @@ void test_floats(void)
test_fcvt(1.0/0.0);
test_fcvt(q_nan.d);
test_fconst();
//test_fbcd(1234567890123456.0);
//test_fbcd(-123451234567890.0);
test_fbcd(0.0);
test_fbcd(-0.0);
test_fbcd(1.0);
test_fbcd(-1.0);
test_fbcd(1234567890123456.0);
test_fbcd(-123451234567890.0);
test_fbcd(341234567890123456.0);
test_fbcd(-345123451234567890.0);
test_fbcd(999999999999999900.0);
test_fbcd(-999999999999999900.0);
test_fbcd(1000000000000000000.0);
test_fbcd(-1000000000000000000.0);
test_fenv();
if (TEST_CMOV) {
test_fcmov();