FPU: Implement zero divide fault

This commit is contained in:
Fabian 2018-12-26 17:05:57 +01:00
parent 0269e9cecf
commit 158bb75fec
5 changed files with 84 additions and 15 deletions

View file

@ -3,6 +3,7 @@ use std::mem::transmute;
use cpu2::cpu::*;
use cpu2::global_pointers::*;
use paging::OrPageFault;
use std::f64;
pub fn round(x: f64) -> f64 { x.round() }
pub fn floor(x: f64) -> f64 { x.floor() }
@ -23,6 +24,7 @@ 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_SF: i32 = 1 << 6;
const TWO_POW_63: f64 = 0x8000000000000000u64 as f64;
@ -89,6 +91,12 @@ pub unsafe fn fpu_stack_fault() {
*fpu_status_word |= FPU_EX_SF | FPU_EX_I;
}
#[no_mangle]
pub unsafe fn fpu_zero_fault() {
// TODO: Interrupt
*fpu_status_word |= FPU_EX_Z;
}
#[no_mangle]
pub unsafe fn fpu_sti_empty(mut i: i32) -> bool {
dbg_assert!(i >= 0 && i < 8);
@ -305,11 +313,17 @@ pub unsafe fn fpu_fcomp(val: f64) {
#[no_mangle]
pub unsafe fn fpu_fdiv(target_index: i32, val: f64) {
let st0: f64 = fpu_get_st0();
if val == 0.0 {
fpu_zero_fault();
}
fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, st0 / val);
}
#[no_mangle]
pub unsafe fn fpu_fdivr(target_index: i32, val: f64) {
let st0: f64 = fpu_get_st0();
if st0 == 0.0 {
fpu_zero_fault();
}
fpu_write_st(*fpu_stack_ptr as i32 + target_index & 7, val / st0);
}
#[no_mangle]
@ -762,15 +776,37 @@ pub unsafe fn fpu_fxch(i: i32) {
fpu_write_st(*fpu_stack_ptr as i32 + i & 7, fpu_get_st0());
fpu_write_st(*fpu_stack_ptr as i32, sti);
}
pub unsafe fn fpu_fyl2x() {
let st0 = fpu_get_st0();
if st0 < 0.0 {
fpu_invalid_arithmetic();
}
else if st0 == 0.0 {
fpu_zero_fault();
}
fpu_write_st(
*fpu_stack_ptr as i32 + 1 & 7,
fpu_get_sti(1) * st0.ln() / M_LN2,
);
fpu_pop();
}
#[no_mangle]
pub unsafe fn fpu_fxtract() {
let mut f = FloatParts::of_f64(fpu_get_st0());
fpu_write_st(
*fpu_stack_ptr as i32,
f.exponent as f64 - F64_EXPONENT_BIAS as f64,
);
f.exponent = 0x3FF;
fpu_push(f.to_f64());
let st0 = fpu_get_st0();
if st0 == 0.0 {
fpu_zero_fault();
fpu_write_st(*fpu_stack_ptr as i32, f64::NEG_INFINITY);
fpu_push(st0);
}
else {
let mut f = FloatParts::of_f64(st0);
fpu_write_st(
*fpu_stack_ptr as i32,
f.exponent as f64 - F64_EXPONENT_BIAS as f64,
);
f.exponent = 0x3FF;
fpu_push(f.to_f64());
}
}
#[no_mangle]
pub unsafe fn fwait() {

View file

@ -3698,14 +3698,7 @@ pub unsafe fn instr_D9_6_reg(r: i32) {
},
1 => {
// fyl2x
if st0 < 0.0 {
fpu_invalid_arithmetic();
}
fpu_write_st(
*fpu_stack_ptr as i32 + 1 & 7,
fpu_get_sti(1) * st0.ln() / M_LN2,
);
fpu_pop();
fpu_fyl2x();
},
2 => {
// fptan

14
tests/nasm/fdiv-zero.asm Normal file
View file

@ -0,0 +1,14 @@
global _start
section .data
align 16
%include "header.inc"
push 1234
fild dword [esp]
push 0
fild dword [esp]
fdiv
%include "footer.inc"

View file

@ -0,0 +1,12 @@
global _start
section .data
align 16
%include "header.inc"
push 0
fild dword [esp]
fxtract
%include "footer.inc"

14
tests/nasm/fyl2x-zero.asm Normal file
View file

@ -0,0 +1,14 @@
global _start
section .data
align 16
%include "header.inc"
push 1234
fild dword [esp]
push 0
fild dword [esp]
fyl2x
%include "footer.inc"