Port fpu to C

This commit is contained in:
Fabian 2018-01-24 22:53:49 -06:00
parent fb1cb5e800
commit 9ad9693cdd
8 changed files with 1552 additions and 50 deletions

View file

@ -172,25 +172,6 @@ function V86Starter(options)
"_mmap_write16": function(addr, value) { return cpu.mmap_write16(addr, value); }, "_mmap_write16": function(addr, value) { return cpu.mmap_write16(addr, value); },
"_mmap_write32": function(addr, value) { return cpu.mmap_write32(addr, value); }, "_mmap_write32": function(addr, value) { return cpu.mmap_write32(addr, value); },
"_fpu_op_D8_reg": function() { return cpu.fpu.op_D8_reg.apply(cpu.fpu, arguments); },
"_fpu_op_D9_reg": function() { return cpu.fpu.op_D9_reg.apply(cpu.fpu, arguments); },
"_fpu_op_DA_reg": function() { return cpu.fpu.op_DA_reg.apply(cpu.fpu, arguments); },
"_fpu_op_DB_reg": function() { return cpu.fpu.op_DB_reg.apply(cpu.fpu, arguments); },
"_fpu_op_DC_reg": function() { return cpu.fpu.op_DC_reg.apply(cpu.fpu, arguments); },
"_fpu_op_DD_reg": function() { return cpu.fpu.op_DD_reg.apply(cpu.fpu, arguments); },
"_fpu_op_DE_reg": function() { return cpu.fpu.op_DE_reg.apply(cpu.fpu, arguments); },
"_fpu_op_DF_reg": function() { return cpu.fpu.op_DF_reg.apply(cpu.fpu, arguments); },
"_fpu_op_D8_mem": function() { return cpu.fpu.op_D8_mem.apply(cpu.fpu, arguments); },
"_fpu_op_D9_mem": function() { return cpu.fpu.op_D9_mem.apply(cpu.fpu, arguments); },
"_fpu_op_DA_mem": function() { return cpu.fpu.op_DA_mem.apply(cpu.fpu, arguments); },
"_fpu_op_DB_mem": function() { return cpu.fpu.op_DB_mem.apply(cpu.fpu, arguments); },
"_fpu_op_DC_mem": function() { return cpu.fpu.op_DC_mem.apply(cpu.fpu, arguments); },
"_fpu_op_DD_mem": function() { return cpu.fpu.op_DD_mem.apply(cpu.fpu, arguments); },
"_fpu_op_DE_mem": function() { return cpu.fpu.op_DE_mem.apply(cpu.fpu, arguments); },
"_fpu_op_DF_mem": function() { return cpu.fpu.op_DF_mem.apply(cpu.fpu, arguments); },
"_fwait": function() { return cpu.fpu.fwait(); },
"_int_log2": function(val) { return v86util.int_log2(val); }, "_int_log2": function(val) { return v86util.int_log2(val); },
"_math_pow": function(x, y) { return Math.pow(x, y); }, "_math_pow": function(x, y) { return Math.pow(x, y); },
@ -244,6 +225,21 @@ function V86Starter(options)
"_get_time": () => Date.now(), "_get_time": () => Date.now(),
"_codegen_finalize": (cache_index, virt_start, start, end) => cpu.codegen_finalize(cache_index, virt_start, start, end), "_codegen_finalize": (cache_index, virt_start, start, end) => cpu.codegen_finalize(cache_index, virt_start, start, end),
"_atan2": Math.atan2,
"_sin": Math.sin,
"_cos": Math.cos,
"_tan": Math.tan,
"_trunc": Math.trunc,
"_fmod": (x, y) => x % y,
"_llvm_exp2_f64": (x) => Math.pow(2, x),
"_log": Math.log,
"_round": Math.round,
};
const wasm_globals = {
"Infinity": Infinity,
"NaN": NaN,
}; };
let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm"; let wasm_file = DEBUG ? "v86-debug.wasm" : "v86.wasm";
@ -259,7 +255,7 @@ function V86Starter(options)
v86util.load_wasm( v86util.load_wasm(
wasm_file, wasm_file,
{ "env": wasm_shared_funcs }, { "env": wasm_shared_funcs, "global" : wasm_globals },
options["memory_size"] + INTERNAL_MEM_SIZE, options["memory_size"] + INTERNAL_MEM_SIZE,
WASM_TABLE_SIZE, WASM_TABLE_SIZE,
wm => { wm => {

View file

@ -192,6 +192,29 @@ function CPU(bus, wm, codegen)
this.reg8s = new Int8Array(this.reg32s.buffer, 4, 32); this.reg8s = new Int8Array(this.reg32s.buffer, 4, 32);
this.reg8 = new Uint8Array(this.reg32s.buffer, 4, 32); this.reg8 = new Uint8Array(this.reg32s.buffer, 4, 32);
// Why no Float80Array :-(
this.fpu_st = new Float64Array(wm.memory.buffer, 968, 8);
this.fpu_stack_empty = new Int32Array(wm.memory.buffer, 816, 1);
this.fpu_stack_empty[0] = 0xff;
this.fpu_stack_ptr = new Uint32Array(wm.memory.buffer, 1032, 1);
this.fpu_stack_ptr[0] = 0;
this.fpu_control_word = new Int32Array(wm.memory.buffer, 1036, 1);
this.fpu_control_word[0] = 0x37F;
this.fpu_status_word = new Int32Array(wm.memory.buffer, 1040, 1);
this.fpu_status_word[0] = 0;
this.fpu_ip = new Int32Array(wm.memory.buffer, 1048, 1);
this.fpu_ip[0] = 0;
this.fpu_ip_selector = new Int32Array(wm.memory.buffer, 1052, 1);
this.fpu_ip_selector[0] = 0;
this.fpu_opcode = new Int32Array(wm.memory.buffer, 1044, 1);
this.fpu_opcode[0] = 0;
this.fpu_dp = new Int32Array(wm.memory.buffer, 1056, 1);
this.fpu_dp[0] = 0;
this.fpu_dp_selector = new Int32Array(wm.memory.buffer, 1060, 1);
this.fpu_dp_selector[0] = 0;
// mm0-mm7 split up into 32 bit pairs // mm0-mm7 split up into 32 bit pairs
this.reg_mmxs = new Int32Array(wm.memory.buffer, 1064, 16); this.reg_mmxs = new Int32Array(wm.memory.buffer, 1064, 16);
this.reg_mmx = new Uint32Array(this.reg_mmxs.buffer, 1064, 16); this.reg_mmx = new Uint32Array(this.reg_mmxs.buffer, 1064, 16);
@ -211,7 +234,6 @@ function CPU(bus, wm, codegen)
this.fw_value = new Int32Array(wm.memory.buffer, 720, 1); this.fw_value = new Int32Array(wm.memory.buffer, 720, 1);
this.io = undefined; this.io = undefined;
this.fpu = undefined;
this.bus = bus; this.bus = bus;
@ -452,7 +474,6 @@ CPU.prototype.get_state = function()
state[40] = this.sreg; state[40] = this.sreg;
state[41] = this.dreg; state[41] = this.dreg;
state[42] = this.mem8; state[42] = this.mem8;
state[43] = this.fpu;
state[45] = this.devices.virtio; state[45] = this.devices.virtio;
state[46] = this.devices.apic; state[46] = this.devices.apic;
@ -481,6 +502,16 @@ CPU.prototype.get_state = function()
state[65] = this.reg_mmxs; state[65] = this.reg_mmxs;
state[66] = this.reg_xmm32s; state[66] = this.reg_xmm32s;
state[67] = this.fpu_st;
state[68] = this.fpu_stack_empty[0];
state[69] = this.fpu_stack_ptr[0];
state[70] = this.fpu_control_word[0];
state[71] = this.fpu_ip[0];
state[72] = this.fpu_ip_selector[0];
state[73] = this.fpu_dp[0];
state[74] = this.fpu_dp_selector[0];
state[75] = this.fpu_opcode[0];
return state; return state;
}; };
@ -527,7 +558,6 @@ CPU.prototype.set_state = function(state)
this.sreg.set(state[40]); this.sreg.set(state[40]);
this.dreg.set(state[41]); this.dreg.set(state[41]);
this.mem8.set(state[42]); this.mem8.set(state[42]);
this.fpu = state[43];
this.devices.virtio = state[45]; this.devices.virtio = state[45];
this.devices.apic = state[46]; this.devices.apic = state[46];
@ -556,6 +586,16 @@ CPU.prototype.set_state = function(state)
this.reg_mmxs.set(state[65]); this.reg_mmxs.set(state[65]);
this.reg_xmm32s.set(state[66]); this.reg_xmm32s.set(state[66]);
this.fpu_st.set(state[67]);
this.fpu_stack_empty[0] = state[68];
this.fpu_stack_ptr[0] = state[69];
this.fpu_control_word[0] = state[70];
this.fpu_ip[0] = state[71];
this.fpu_ip_selector[0] = state[72];
this.fpu_dp[0] = state[73];
this.fpu_dp_selector[0] = state[74];
this.fpu_opcode[0] = state[75];
this.full_clear_tlb(); this.full_clear_tlb();
// tsc_offset? // tsc_offset?
@ -849,8 +889,6 @@ CPU.prototype.init = function(settings, device_bus)
this.devices.vga = new VGAScreen(this, device_bus, this.devices.vga = new VGAScreen(this, device_bus,
settings.vga_memory_size || 8 * 1024 * 1024); settings.vga_memory_size || 8 * 1024 * 1024);
this.fpu = new FPU(this);
this.devices.ps2 = new PS2(this, device_bus); this.devices.ps2 = new PS2(this, device_bus);
this.devices.uart = new UART(this, 0x3F8, device_bus); this.devices.uart = new UART(this, 0x3F8, device_bus);
@ -1500,7 +1538,7 @@ CPU.prototype.set_cr0 = function(cr0)
this.cr[0] = cr0; this.cr[0] = cr0;
if(!this.fpu) if(false)
{ {
// if there's no FPU, keep emulation set // if there's no FPU, keep emulation set
this.cr[0] |= CR0_EM; this.cr[0] |= CR0_EM;
@ -3703,7 +3741,7 @@ CPU.prototype.cpuid = function()
ecx = 1 << 23 | 1 << 30; // popcnt, rdrand ecx = 1 << 23 | 1 << 30; // popcnt, rdrand
var vme = 0 << 1; var vme = 0 << 1;
if(VMWARE_HYPERVISOR_PORT) ecx |= 1 << 31; // hypervisor if(VMWARE_HYPERVISOR_PORT) ecx |= 1 << 31; // hypervisor
edx = (this.fpu ? 1 : 0) | // fpu edx = (true /* have fpu */ ? 1 : 0) | // fpu
vme | 1 << 3 | 1 << 4 | 1 << 5 | // vme, pse, tsc, msr vme | 1 << 3 | 1 << 4 | 1 << 5 | // vme, pse, tsc, msr
1 << 8 | 1 << 11 | 1 << 13 | 1 << 15 | // cx8, sep, pge, cmov 1 << 8 | 1 << 11 | 1 << 13 | 1 << 15 | // cx8, sep, pge, cmov
1 << 23 | 1 << 24 | 1 << 25 | 1 << 26; // mmx, fxsr, sse1, sse2 1 << 23 | 1 << 24 | 1 << 25 | 1 << 26; // mmx, fxsr, sse1, sse2

View file

@ -827,6 +827,14 @@ void clear_tlb()
memcpy_large(tlb_info, tlb_info_global, 0x100000); memcpy_large(tlb_info, tlb_info_global, 0x100000);
} }
void task_switch_test()
{
if(cr[0] & (CR0_EM | CR0_TS))
{
trigger_nm();
}
}
void task_switch_test_mmx() void task_switch_test_mmx()
{ {
if(*cr & (CR0_EM | CR0_TS)) if(*cr & (CR0_EM | CR0_TS))

View file

@ -70,6 +70,7 @@ void write_xmm64(int32_t r, union reg64 data);
void write_xmm128(int32_t r, int32_t i0, int32_t i1, int32_t i2, int32_t i3); void write_xmm128(int32_t r, int32_t i0, int32_t i1, int32_t i2, int32_t i3);
void write_xmm_reg128(int32_t r, union reg128 data); void write_xmm_reg128(int32_t r, union reg128 data);
void clear_tlb(void); void clear_tlb(void);
void task_switch_test(void);
void task_switch_test_mmx(void); void task_switch_test_mmx(void);
int32_t read_moffs(void); int32_t read_moffs(void);
int32_t get_real_eip(void); int32_t get_real_eip(void);

File diff suppressed because it is too large Load diff

View file

@ -9,3 +9,21 @@ int32_t fpu_load_status_word(void);
void fpu_set_status_word(int32_t sw); void fpu_set_status_word(int32_t sw);
void fpu_store_m80(uint32_t addr, double_t n); void fpu_store_m80(uint32_t addr, double_t n);
double_t fpu_load_m80(uint32_t addr); double_t fpu_load_m80(uint32_t addr);
void fwait();
void fpu_op_D8_mem(int32_t, int32_t);
void fpu_op_D8_reg(int32_t);
void fpu_op_D9_mem(int32_t, int32_t);
void fpu_op_D9_reg(int32_t);
void fpu_op_DA_mem(int32_t, int32_t);
void fpu_op_DA_reg(int32_t);
void fpu_op_DB_mem(int32_t, int32_t);
void fpu_op_DB_reg(int32_t);
void fpu_op_DC_mem(int32_t, int32_t);
void fpu_op_DC_reg(int32_t);
void fpu_op_DD_mem(int32_t, int32_t);
void fpu_op_DD_reg(int32_t);
void fpu_op_DE_mem(int32_t, int32_t);
void fpu_op_DE_reg(int32_t);
void fpu_op_DF_mem(int32_t, int32_t);
void fpu_op_DF_reg(int32_t);

View file

@ -8,6 +8,7 @@
#include "log.h" #include "log.h"
#include "arith.h" #include "arith.h"
#include "cpu.h" #include "cpu.h"
#include "fpu.h"
#include "shared.h" #include "shared.h"
#include "misc_instr.h" #include "misc_instr.h"
#include "string.h" #include "string.h"

View file

@ -33,24 +33,7 @@ extern void enter16(int32_t, int32_t);
extern void enter32(int32_t, int32_t); extern void enter32(int32_t, int32_t);
extern void far_jump(int32_t, int32_t, int32_t); extern void far_jump(int32_t, int32_t, int32_t);
extern void far_return(int32_t, int32_t, int32_t); extern void far_return(int32_t, int32_t, int32_t);
extern void fpu_op_D8_mem(int32_t, int32_t);
extern void fpu_op_D8_reg(int32_t);
extern void fpu_op_D9_mem(int32_t, int32_t);
extern void fpu_op_D9_reg(int32_t);
extern void fpu_op_DA_mem(int32_t, int32_t);
extern void fpu_op_DA_reg(int32_t);
extern void fpu_op_DB_mem(int32_t, int32_t);
extern void fpu_op_DB_reg(int32_t);
extern void fpu_op_DC_mem(int32_t, int32_t);
extern void fpu_op_DC_reg(int32_t);
extern void fpu_op_DD_mem(int32_t, int32_t);
extern void fpu_op_DD_reg(int32_t);
extern void fpu_op_DE_mem(int32_t, int32_t);
extern void fpu_op_DE_reg(int32_t);
extern void fpu_op_DF_mem(int32_t, int32_t);
extern void fpu_op_DF_reg(int32_t);
extern void full_clear_tlb(void); extern void full_clear_tlb(void);
extern void fwait(void);
extern void handle_irqs(void); extern void handle_irqs(void);
extern void hlt_op(void); extern void hlt_op(void);
extern void invlpg(int32_t); extern void invlpg(int32_t);
@ -64,7 +47,6 @@ extern void mmap_write32(uint32_t, int32_t);
extern void mmap_write8(uint32_t, int32_t); extern void mmap_write8(uint32_t, int32_t);
extern void popa16(void); extern void popa16(void);
extern void popa32(void); extern void popa32(void);
extern void task_switch_test(void);
extern void todo(void); extern void todo(void);
extern void undefined_instruction(void); extern void undefined_instruction(void);
extern void unimplemented_sse(void); extern void unimplemented_sse(void);