Browse Source

fpu: Have opcode 0xDB use fixed_g instruction functions

Amaan Cheval 6 years ago
parent
commit
c3a856e944
4 changed files with 53 additions and 141 deletions
  1. 1 1
      gen/x86_table.js
  2. 0 136
      src/native/fpu.c
  3. 36 2
      src/native/instructions.c
  4. 16 2
      src/native/instructions.h

+ 1 - 1
gen/x86_table.js

@@ -163,7 +163,6 @@ const encodings = [
     { opcode: 0xD6, nonfaulting: 1, },
     { opcode: 0xD7, skip: 1, },
 
-    { opcode: 0xDB, e: 1, skip: 1, },
     { opcode: 0xDC, e: 1, skip: 1, },
     { opcode: 0xDD, e: 1, skip: 1, },
     { opcode: 0xDE, e: 1, skip: 1, },
@@ -665,6 +664,7 @@ for(let i = 0; i < 8; i++)
         { opcode: 0xD8, e: 1, fixed_g: i, skip: 1, },
         { opcode: 0xD9, e: 1, fixed_g: i, skip: 1, },
         { opcode: 0xDA, e: 1, fixed_g: i, skip: 1, },
+        { opcode: 0xDB, e: 1, fixed_g: i, skip: 1, },
     ]);
 }
 

+ 0 - 136
src/native/fpu.c

@@ -846,142 +846,6 @@ void fpu_fst80p(int32_t addr)
     fpu_pop();
 }
 
-void fpu_op_DB_reg(int32_t imm8)
-{
-    dbg_log_fpu_op(0xDB, imm8);
-
-    int32_t mod = imm8 >> 3 & 7;
-    int32_t low = imm8 & 7;
-
-    switch(mod)
-    {
-        case 0:
-            // fcmovnb
-            if(!test_b())
-            {
-                fpu_st[*fpu_stack_ptr] = fpu_get_sti(low);
-                *fpu_stack_empty &= ~(1 << *fpu_stack_ptr);
-            }
-            break;
-        case 1:
-            // fcmovne
-            if(!test_z())
-            {
-                fpu_st[*fpu_stack_ptr] = fpu_get_sti(low);
-                *fpu_stack_empty &= ~(1 << *fpu_stack_ptr);
-            }
-            break;
-        case 2:
-            // fcmovnbe
-            if(!test_be())
-            {
-                fpu_st[*fpu_stack_ptr] = fpu_get_sti(low);
-                *fpu_stack_empty &= ~(1 << *fpu_stack_ptr);
-            }
-            break;
-        case 3:
-            // fcmovnu
-            if(!test_p())
-            {
-                fpu_st[*fpu_stack_ptr] = fpu_get_sti(low);
-                *fpu_stack_empty &= ~(1 << *fpu_stack_ptr);
-            }
-            break;
-        case 4:
-            if(imm8 == 0xE3)
-            {
-                fpu_finit();
-            }
-            else if(imm8 == 0xE4)
-            {
-                // fsetpm
-                // treat as nop
-            }
-            else if(imm8 == 0xE1)
-            {
-                // fdisi
-                // also treat as nop
-            }
-            else if(imm8 == 0xE2)
-            {
-                // fclex
-                *fpu_status_word = 0;
-            }
-            else
-            {
-                dbg_log("%x", imm8);
-                fpu_unimpl();
-            }
-            break;
-        case 5:
-            fpu_fucomi(low);
-            break;
-        case 6:
-            fpu_fcomi(low);
-            break;
-        default:
-            dbg_log("%x", mod);
-            fpu_unimpl();
-    }
-}
-
-void fpu_op_DB_mem(int32_t mod, int32_t addr)
-{
-    dbg_log_fpu_op(0xDB, mod);
-
-    switch(mod)
-    {
-        case 0:
-            // fild
-            {
-                int32_t data = safe_read32s(addr);
-                fpu_push(data);
-            }
-            break;
-        case 2:
-            // fist
-            {
-                double_t st0 = fpu_integer_round(fpu_get_st0());
-                int32_t i = convert_f64_to_i32(st0);
-                if(i == (int32_t)0x80000000)
-                {
-                    // XXX: Probably not correct if st0 == 0x80000000
-                    fpu_invalid_arithmetic();
-                }
-                safe_write32(addr, i);
-            }
-            break;
-        case 3:
-            // fistp
-            {
-                double_t st0 = fpu_integer_round(fpu_get_st0());
-                int32_t i = convert_f64_to_i32(st0);
-                if(i == (int32_t)0x80000000)
-                {
-                    // XXX: Probably not correct if st0 == 0x80000000
-                    //      (input fits, but same value as error value)
-                    fpu_invalid_arithmetic();
-                }
-                safe_write32(addr, i);
-                fpu_pop();
-            }
-            break;
-        case 5:
-            // fld
-            fpu_push(fpu_load_m80(addr));
-            break;
-        case 7:
-            // fstp
-            writable_or_pagefault(addr, 10);
-            fpu_store_m80(addr, fpu_get_st0());
-            fpu_pop();
-            break;
-        default:
-            dbg_log("%x", mod);
-            fpu_unimpl();
-    }
-}
-
 void fpu_op_DC_reg(int32_t imm8)
 {
     dbg_log_fpu_op(0xDC, imm8);

+ 36 - 2
src/native/instructions.c

@@ -1180,8 +1180,42 @@ void instr_DA_5_reg(int32_t r) {
 void instr_DA_6_reg(int32_t r) { trigger_ud(); }
 void instr_DA_7_reg(int32_t r) { trigger_ud(); }
 
-void instr_DB_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DB_mem(r, addr); }
-void instr_DB_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_DB_reg(0xC0 | r2 | r << 3); }
+void instr_DB_0_mem(int32_t addr) { task_switch_test(); fpu_push(safe_read32s(addr)); }
+void instr_DB_1_mem(int32_t addr) { trigger_ud(); }
+void instr_DB_2_mem(int32_t addr) { task_switch_test(); fpu_fistm32(addr); }
+void instr_DB_3_mem(int32_t addr) { task_switch_test(); fpu_fistm32p(addr); }
+void instr_DB_4_mem(int32_t addr) { trigger_ud(); }
+void instr_DB_5_mem(int32_t addr) { task_switch_test(); fpu_push(fpu_load_m80(addr)); }
+void instr_DB_6_mem(int32_t addr) { trigger_ud(); }
+void instr_DB_7_mem(int32_t addr) { task_switch_test(); fpu_fst80p(addr); }
+
+void instr_DB_0_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(!test_b(), r); }
+void instr_DB_1_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(!test_z(), r); }
+void instr_DB_2_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(!test_be(), r); }
+void instr_DB_3_reg(int32_t r) { task_switch_test(); fpu_fcmovcc(!test_p(), r); }
+void instr_DB_4_reg(int32_t r) {
+    task_switch_test();
+    if(r == 3)
+    {
+        fpu_finit();
+    }
+    else if(r == 4 || r == 1)
+    {
+        // fsetpm and fdisi; treated as nop
+    }
+    else if(r == 2)
+    {
+        fpu_fclex();
+    }
+    else
+    {
+        trigger_ud();
+    }
+}
+void instr_DB_5_reg(int32_t r) { task_switch_test(); fpu_fucomi(r); }
+void instr_DB_6_reg(int32_t r) { task_switch_test(); fpu_fcomi(r); }
+void instr_DB_7_reg(int32_t r) { trigger_ud(); }
+
 void instr_DC_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DC_mem(r, addr); }
 void instr_DC_reg(int32_t r2, int32_t r) { task_switch_test(); fpu_op_DC_reg(0xC0 | r2 | r << 3); }
 void instr_DD_mem(int32_t addr, int32_t r) { task_switch_test(); fpu_op_DD_mem(r, addr); }

+ 16 - 2
src/native/instructions.h

@@ -834,8 +834,22 @@ void instr_DA_6_mem(int32_t addr);
 void instr_DA_6_reg(int32_t r);
 void instr_DA_7_mem(int32_t addr);
 void instr_DA_7_reg(int32_t r);
-void instr_DB_mem(int32_t addr, int32_t r);
-void instr_DB_reg(int32_t r2, int32_t r);
+void instr_DB_0_mem(int32_t addr);
+void instr_DB_0_reg(int32_t r);
+void instr_DB_1_mem(int32_t addr);
+void instr_DB_1_reg(int32_t r);
+void instr_DB_2_mem(int32_t addr);
+void instr_DB_2_reg(int32_t r);
+void instr_DB_3_mem(int32_t addr);
+void instr_DB_3_reg(int32_t r);
+void instr_DB_4_mem(int32_t addr);
+void instr_DB_4_reg(int32_t r);
+void instr_DB_5_mem(int32_t addr);
+void instr_DB_5_reg(int32_t r);
+void instr_DB_6_mem(int32_t addr);
+void instr_DB_6_reg(int32_t r);
+void instr_DB_7_mem(int32_t addr);
+void instr_DB_7_reg(int32_t r);
 void instr_DC_mem(int32_t addr, int32_t r);
 void instr_DC_reg(int32_t r2, int32_t r);
 void instr_DD_mem(int32_t addr, int32_t r);