Browse Source

Minor improvements to some fpu instructions

Fabian 3 years ago
parent
commit
c3cf08bb35
2 changed files with 50 additions and 12 deletions
  1. 46 7
      src/rust/cpu2/fpu.rs
  2. 4 5
      src/rust/cpu2/instructions.rs

+ 46 - 7
src/rust/cpu2/fpu.rs

@@ -17,15 +17,27 @@ pub const M_LOG2E: f64 = 1.4426950408889634f64;
 pub const M_LN2: f64 = 0.6931471805599453f64;
 pub const M_LN10: f64 = 2.302585092994046f64;
 pub const M_PI: f64 = 3.141592653589793f64;
+
 const FPU_C0: i32 = 0x100;
 pub const FPU_C1: i32 = 0x200;
 pub const FPU_C2: i32 = 0x400;
 const FPU_C3: i32 = 0x4000;
 const FPU_RESULT_FLAGS: i32 = FPU_C0 | FPU_C1 | FPU_C2 | FPU_C3;
+
 const INDEFINITE_NAN: f64 = ::std::f64::NAN;
-const FPU_EX_I: i32 = 1 << 0;
-const FPU_EX_Z: i32 = 1 << 2;
+
+const FPU_EX_I: i32 = 1 << 0; // invalid operation
+#[allow(dead_code)]
+const FPU_EX_D: i32 = 1 << 1; // denormal operand
+const FPU_EX_Z: i32 = 1 << 2; // zero divide
+#[allow(dead_code)]
+const FPU_EX_O: i32 = 1 << 3; // overflow
+#[allow(dead_code)]
+const FPU_EX_U: i32 = 1 << 4; // underflow
+#[allow(dead_code)]
+const FPU_EX_P: i32 = 1 << 5; // precision
 const FPU_EX_SF: i32 = 1 << 6;
+
 const TWO_POW_63: f64 = 0x8000000000000000u64 as f64;
 
 const F64_MANTISSA_MASK: u64 = (1 << 52) - 1;
@@ -138,6 +150,7 @@ pub unsafe fn fpu_integer_round(f: f64) -> f64 {
         return ceil(f);
     };
 }
+
 #[no_mangle]
 pub unsafe fn fpu_load_m32(addr: i32) -> OrPageFault<f64> {
     let v: f32 = transmute(safe_read32s(addr)?);
@@ -149,7 +162,6 @@ pub unsafe fn fpu_load_m64(addr: i32) -> OrPageFault<f64> {
     let f = transmute(value);
     Ok(f)
 }
-
 #[no_mangle]
 pub unsafe fn fpu_load_m80(addr: i32) -> OrPageFault<f64> {
     let value = safe_read64s(addr as i32)?;
@@ -261,6 +273,7 @@ pub unsafe fn fpu_fcmovcc(condition: bool, r: i32) {
         };
     }
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fcom(y: f64) {
     let x = fpu_get_st0();
@@ -277,6 +290,7 @@ pub unsafe fn fpu_fcom(y: f64) {
         }
     };
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fcomi(r: i32) {
     let y = fpu_get_sti(r);
@@ -295,21 +309,25 @@ pub unsafe fn fpu_fcomi(r: i32) {
         }
     };
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fcomip(r: i32) {
     fpu_fcomi(r);
     fpu_pop();
 }
+
 #[no_mangle]
 pub unsafe fn fpu_pop() {
     *fpu_stack_empty |= 1 << *fpu_stack_ptr;
     *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_add(1) & 7;
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fcomp(val: f64) {
     fpu_fcom(val);
     fpu_pop();
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fdiv(target_index: i32, val: f64) {
     let st0 = fpu_get_st0();
@@ -330,12 +348,20 @@ pub unsafe fn fpu_fdivr(target_index: i32, val: f64) {
 pub unsafe fn fpu_ffree(r: i32) {
     *fpu_stack_empty |= 1 << (*fpu_stack_ptr).wrapping_add(r as u32);
 }
+
+#[no_mangle]
+pub unsafe fn fpu_fildm16(addr: i32) {
+    fpu_push(return_on_pagefault!(safe_read16(addr)) as i16 as f64);
+}
+#[no_mangle]
+pub unsafe fn fpu_fildm32(addr: i32) {
+    fpu_push(return_on_pagefault!(safe_read32s(addr)) as i32 as f64);
+}
 #[no_mangle]
 pub unsafe fn fpu_fildm64(addr: i32) {
-    let value = return_on_pagefault!(safe_read64s(addr)) as i64;
-    let m64 = value as f64;
-    fpu_push(m64);
+    fpu_push(return_on_pagefault!(safe_read64s(addr)) as i64 as f64);
 }
+
 #[no_mangle]
 pub unsafe fn fpu_push(x: f64) {
     *fpu_stack_ptr = (*fpu_stack_ptr).wrapping_sub(1) & 7;
@@ -377,6 +403,7 @@ pub unsafe fn fpu_convert_to_i16(f: f64) -> i16 {
 }
 #[no_mangle]
 pub unsafe fn fpu_fistm16(addr: i32) {
+    return_on_pagefault!(writable_or_pagefault(addr, 2));
     let v = fpu_convert_to_i16(fpu_get_st0());
     return_on_pagefault!(safe_write16(addr, v as i32));
 }
@@ -400,6 +427,7 @@ pub unsafe fn fpu_convert_to_i32(f: f64) -> i32 {
 }
 #[no_mangle]
 pub unsafe fn fpu_fistm32(addr: i32) {
+    return_on_pagefault!(writable_or_pagefault(addr, 4));
     let v = fpu_convert_to_i32(fpu_get_st0());
     return_on_pagefault!(safe_write32(addr, v));
 }
@@ -422,6 +450,7 @@ pub unsafe fn fpu_convert_to_i64(f: f64) -> i64 {
 }
 #[no_mangle]
 pub unsafe fn fpu_fistm64p(addr: i32) {
+    return_on_pagefault!(writable_or_pagefault(addr, 8));
     let v = fpu_convert_to_i64(fpu_get_st0());
     return_on_pagefault!(safe_write64(addr, v as u64));
     fpu_pop();
@@ -477,8 +506,9 @@ pub unsafe fn fpu_set_status_word(sw: i32) {
     *fpu_status_word = sw & !(7 << 11);
     *fpu_stack_ptr = (sw >> 11 & 7) as u32;
 }
+
 #[no_mangle]
-pub unsafe fn fpu_fldm32(addr: i32) { fpu_push(return_on_pagefault!(safe_read32s(addr)) as f64); }
+pub unsafe fn fpu_fldm32(addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m32(addr))); }
 #[no_mangle]
 pub unsafe fn fpu_fldm64(addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m64(addr))); }
 #[no_mangle]
@@ -493,6 +523,7 @@ pub unsafe fn fpu_fldm80(addr: i32) {
         },
     }
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fmul(target_index: i32, val: f64) {
     let st0 = fpu_get_st0();
@@ -735,6 +766,7 @@ pub unsafe fn fpu_fsubr(target_index: i32, val: f64) {
     let st0 = fpu_get_st0();
     fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, val - st0)
 }
+
 #[no_mangle]
 pub unsafe fn fpu_ftst(x: f64) {
     *fpu_status_word &= !FPU_RESULT_FLAGS;
@@ -749,32 +781,38 @@ pub unsafe fn fpu_ftst(x: f64) {
     }
     // TODO: unordered (x is nan, etc)
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fucom(r: i32) {
     // TODO
     fpu_fcom(fpu_get_sti(r));
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fucomi(r: i32) {
     // TODO
     fpu_fcomi(r);
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fucomip(r: i32) {
     fpu_fucomi(r);
     fpu_pop();
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fucomp(r: i32) {
     fpu_fucom(r);
     fpu_pop();
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fucompp() {
     fpu_fucom(1);
     fpu_pop();
     fpu_pop();
 }
+
 #[no_mangle]
 pub unsafe fn fpu_fxam(x: f64) {
     *fpu_status_word &= !FPU_RESULT_FLAGS;
@@ -797,6 +835,7 @@ pub unsafe fn fpu_fxam(x: f64) {
     // TODO:
     // Unsupported, Denormal
 }
+
 #[no_mangle]
 pub unsafe fn fpu_sign(i: i32) -> i32 {
     // sign of a number on the stack

+ 4 - 5
src/rust/cpu2/instructions.rs

@@ -2620,8 +2620,9 @@ pub unsafe fn instr_D8_6_reg(r: i32) { fpu_fdiv(0, fpu_get_sti(r)); }
 pub unsafe fn instr_D8_7_mem(addr: i32) { fpu_fdivr(0, return_on_pagefault!(fpu_load_m32(addr))); }
 #[no_mangle]
 pub unsafe fn instr_D8_7_reg(r: i32) { fpu_fdivr(0, fpu_get_sti(r)); }
+
 #[no_mangle]
-pub unsafe fn instr16_D9_0_mem(addr: i32) { fpu_push(return_on_pagefault!(fpu_load_m32(addr))); }
+pub unsafe fn instr16_D9_0_mem(addr: i32) { fpu_fldm32(addr); }
 #[no_mangle]
 pub unsafe fn instr16_D9_0_reg(r: i32) { fpu_push(fpu_get_sti(r)); }
 #[no_mangle]
@@ -2919,7 +2920,7 @@ pub unsafe fn instr_DA_6_reg(r: i32) { trigger_ud(); }
 #[no_mangle]
 pub unsafe fn instr_DA_7_reg(r: i32) { trigger_ud(); }
 #[no_mangle]
-pub unsafe fn instr_DB_0_mem(addr: i32) { fpu_fldm32(addr); }
+pub unsafe fn instr_DB_0_mem(addr: i32) { fpu_fildm32(addr); }
 #[no_mangle]
 pub unsafe fn instr_DB_1_mem(addr: i32) {
     dbg_log!("fisttp");
@@ -3149,9 +3150,7 @@ pub unsafe fn instr_DE_7_reg(r: i32) {
     fpu_pop();
 }
 #[no_mangle]
-pub unsafe fn instr_DF_0_mem(addr: i32) {
-    fpu_push(return_on_pagefault!(safe_read16(addr)) as i16 as f64);
-}
+pub unsafe fn instr_DF_0_mem(addr: i32) { fpu_fildm16(addr) }
 #[no_mangle]
 pub unsafe fn instr_DF_1_mem(addr: i32) {
     dbg_log!("fisttp");