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_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); },
"_math_pow": function(x, y) { return Math.pow(x, y); },
@ -244,6 +225,21 @@ function V86Starter(options)
"_get_time": () => Date.now(),
"_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";
@ -259,7 +255,7 @@ function V86Starter(options)
v86util.load_wasm(
wasm_file,
{ "env": wasm_shared_funcs },
{ "env": wasm_shared_funcs, "global" : wasm_globals },
options["memory_size"] + INTERNAL_MEM_SIZE,
WASM_TABLE_SIZE,
wm => {

View file

@ -192,6 +192,29 @@ function CPU(bus, wm, codegen)
this.reg8s = new Int8Array(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
this.reg_mmxs = new Int32Array(wm.memory.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.io = undefined;
this.fpu = undefined;
this.bus = bus;
@ -452,7 +474,6 @@ CPU.prototype.get_state = function()
state[40] = this.sreg;
state[41] = this.dreg;
state[42] = this.mem8;
state[43] = this.fpu;
state[45] = this.devices.virtio;
state[46] = this.devices.apic;
@ -481,6 +502,16 @@ CPU.prototype.get_state = function()
state[65] = this.reg_mmxs;
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;
};
@ -527,7 +558,6 @@ CPU.prototype.set_state = function(state)
this.sreg.set(state[40]);
this.dreg.set(state[41]);
this.mem8.set(state[42]);
this.fpu = state[43];
this.devices.virtio = state[45];
this.devices.apic = state[46];
@ -556,6 +586,16 @@ CPU.prototype.set_state = function(state)
this.reg_mmxs.set(state[65]);
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();
// tsc_offset?
@ -849,8 +889,6 @@ CPU.prototype.init = function(settings, device_bus)
this.devices.vga = new VGAScreen(this, device_bus,
settings.vga_memory_size || 8 * 1024 * 1024);
this.fpu = new FPU(this);
this.devices.ps2 = new PS2(this, 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;
if(!this.fpu)
if(false)
{
// if there's no FPU, keep emulation set
this.cr[0] |= CR0_EM;
@ -3703,7 +3741,7 @@ CPU.prototype.cpuid = function()
ecx = 1 << 23 | 1 << 30; // popcnt, rdrand
var vme = 0 << 1;
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
1 << 8 | 1 << 11 | 1 << 13 | 1 << 15 | // cx8, sep, pge, cmov
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);
}
void task_switch_test()
{
if(cr[0] & (CR0_EM | CR0_TS))
{
trigger_nm();
}
}
void task_switch_test_mmx()
{
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_xmm_reg128(int32_t r, union reg128 data);
void clear_tlb(void);
void task_switch_test(void);
void task_switch_test_mmx(void);
int32_t read_moffs(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_store_m80(uint32_t addr, double_t n);
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 "arith.h"
#include "cpu.h"
#include "fpu.h"
#include "shared.h"
#include "misc_instr.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 far_jump(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 fwait(void);
extern void handle_irqs(void);
extern void hlt_op(void);
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 popa16(void);
extern void popa32(void);
extern void task_switch_test(void);
extern void todo(void);
extern void undefined_instruction(void);
extern void unimplemented_sse(void);