Browse Source

Fix some minor fpu bugs and add more nasm tests

Fabian 3 years ago
parent
commit
4e49468b7b

+ 1 - 1
gen/x86_table.js

@@ -287,7 +287,7 @@ const encodings = [
     { opcode: 0xD9, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, os: 1, skip_mem: 1, }, // fldenv (mem)
     { opcode: 0xD9, e: 1, fixed_g: 5, custom: 1, is_fpu: 1, task_switch_test: 1, os: 1, },
     { opcode: 0xD9, e: 1, fixed_g: 6, custom: 1, is_fpu: 1, task_switch_test: 1, os: 1, skip: 1, }, // fstenv (mem), fprem (reg)
-    { opcode: 0xD9, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, os: 1, skip_reg: 1, }, // fprem, fyl2xp1
+    { opcode: 0xD9, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, os: 1, skip_reg: 1, }, // fprem, fyl2xp1 (precision issues)
 
     { opcode: 0xDA, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1, },
     { opcode: 0xDA, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, },

+ 12 - 0
src/rust/cpu2/fpu.rs

@@ -516,6 +516,18 @@ pub unsafe fn fpu_fprem(ieee: bool) {
 
     let st0 = fpu_get_st0();
     let st1 = fpu_get_sti(1);
+
+    if st1 == 0.0 {
+        if st0 == 0.0 {
+            fpu_invalid_arithmetic();
+        }
+        else {
+            fpu_zero_fault();
+        }
+        fpu_write_st(*fpu_stack_ptr as i32, INDEFINITE_NAN);
+        return;
+    }
+
     let exp0 = st0.log2();
     let exp1 = st1.log2();
     let d = (exp0 - exp1).abs();

+ 3 - 1
src/rust/cpu2/instructions.rs

@@ -3348,10 +3348,10 @@ pub unsafe fn instr16_D9_6_mem(addr: i32) { fpu_fstenv16(addr); }
 pub unsafe fn instr32_D9_6_mem(addr: i32) { fpu_fstenv32(addr); }
 #[no_mangle]
 pub unsafe fn instr16_D9_6_reg(r: i32) {
-    let st0 = fpu_get_st0();
     match r {
         0 => {
             // f2xm1
+            let st0 = fpu_get_st0();
             let mut r = pow(2.0, st0) - 1.0;
             if r == -1.0 {
                 // Intel ...
@@ -3365,6 +3365,7 @@ pub unsafe fn instr16_D9_6_reg(r: i32) {
         },
         2 => {
             // fptan
+            let st0 = fpu_get_st0();
             if pow(-2.0, 63.0) < st0 && st0 < pow(2.0, 63.0) {
                 fpu_write_st(*fpu_stack_ptr as i32, st0.tan());
                 // no bug: push constant 1
@@ -3377,6 +3378,7 @@ pub unsafe fn instr16_D9_6_reg(r: i32) {
         },
         3 => {
             // fpatan
+            let st0 = fpu_get_st0();
             fpu_write_st(*fpu_stack_ptr as i32 + 1 & 7, fpu_get_sti(1).atan2(st0));
             fpu_pop();
         },

+ 19 - 0
tests/nasm/f2xm1.asm

@@ -0,0 +1,19 @@
+global _start
+
+%include "header.inc"
+
+    fldz
+    f2xm1
+
+    fld1
+    f2xm1
+
+    fld1
+    fchs
+    f2xm1
+
+    fldln2
+    f2xm1
+
+%include "footer.inc"
+

+ 8 - 0
tests/nasm/fdecstp.asm

@@ -0,0 +1,8 @@
+global _start
+
+%include "header.inc"
+
+    fdecstp
+
+%include "footer.inc"
+

+ 8 - 0
tests/nasm/fincstp.asm

@@ -0,0 +1,8 @@
+global _start
+
+%include "header.inc"
+
+    fincstp
+
+%include "footer.inc"
+

+ 21 - 0
tests/nasm/fprem.asm

@@ -0,0 +1,21 @@
+global _start
+
+%include "header.inc"
+
+    fld1
+    fldz
+    fprem
+
+    fld1
+    fldpi
+    fprem
+
+    fld1
+    fldl2t
+    fprem
+
+    fldz
+    fldz
+    fprem
+
+%include "footer.inc"

+ 21 - 0
tests/nasm/fprem1.asm

@@ -0,0 +1,21 @@
+global _start
+
+%include "header.inc"
+
+    fld1
+    fldz
+    fprem1
+
+    fld1
+    fldpi
+    fprem1
+
+    fld1
+    fldl2t
+    fprem1
+
+    fldz
+    fldz
+    fprem1
+
+%include "footer.inc"

+ 13 - 0
tests/nasm/fptan.asm

@@ -0,0 +1,13 @@
+global _start
+
+%include "header.inc"
+
+    fldpi
+    fptan
+
+    fldpi
+    fldpi
+    fpatan
+
+%include "footer.inc"
+

+ 18 - 0
tests/nasm/frndint.asm

@@ -0,0 +1,18 @@
+global _start
+
+%include "header.inc"
+
+    fldz
+    frndint
+
+    fldpi
+    frndint
+
+    fldl2t
+    frndint
+
+    fldln2
+    frndint
+
+%include "footer.inc"
+

+ 10 - 0
tests/nasm/fscale.asm

@@ -0,0 +1,10 @@
+global _start
+
+%include "header.inc"
+
+    fldpi
+    fldpi
+    fscale
+
+%include "footer.inc"
+

+ 20 - 0
tests/nasm/fsincos.asm

@@ -0,0 +1,20 @@
+global _start
+
+%include "header.inc"
+
+    fldpi
+    fsincos
+    fldz
+    fsincos
+
+    fldpi
+    fsin
+    fldz
+    fsin
+
+    fldpi
+    fcos
+    fldz
+    fcos
+
+%include "footer.inc"

+ 9 - 0
tests/nasm/fsqrt.asm

@@ -0,0 +1,9 @@
+global _start
+
+%include "header.inc"
+
+    fldpi
+    fsqrt
+
+%include "footer.inc"
+

+ 10 - 0
tests/nasm/fyl2x.asm

@@ -0,0 +1,10 @@
+global _start
+
+%include "header.inc"
+
+    fld1
+    fldpi
+    fyl2x
+
+%include "footer.inc"
+

+ 9 - 0
tests/nasm/fyl2xp1.asm

@@ -0,0 +1,9 @@
+global _start
+
+%include "header.inc"
+
+    fld1
+    fldpi
+    fyl2xp1
+
+%include "footer.inc"

+ 14 - 0
tests/nasm/indirect-call.asm

@@ -0,0 +1,14 @@
+global _start
+
+section .data
+
+%include "header.inc"
+
+    mov eax, foo
+    call eax
+foo:
+    xor eax, eax
+    ; clear stack (pushed eip is not the same between vm and gdb execution)
+    mov dword [esp], 0
+
+%include "footer.inc"

+ 12 - 0
tests/nasm/indirect-jump.asm

@@ -0,0 +1,12 @@
+global _start
+
+section .data
+
+%include "header.inc"
+
+    mov eax, foo
+    jmp eax
+foo:
+    xor eax, eax
+
+%include "footer.inc"

+ 12 - 0
tests/nasm/pop_esp2.asm

@@ -0,0 +1,12 @@
+global _start
+
+section .data
+	align 16
+
+%include "header.inc"
+
+    ; pop esp encoded using 8F
+    mov esp, stack_top-16
+    db 8Fh, 0C4h
+
+%include "footer.inc"