mirror of
https://github.com/copy/v86.git
synced 2025-12-31 04:23:15 +00:00
Implement SSE3 support in V86 (#906)
Co-authored-by: Fabian <copy@copy.sh>
This commit is contained in:
parent
5da61d617e
commit
c634ae290c
7 changed files with 217 additions and 61 deletions
|
|
@ -5,7 +5,7 @@ WebAssembly modules at runtime in order to achieve decent performance. Here's a
|
|||
list of emulated hardware:
|
||||
|
||||
- An x86-compatible CPU. The instruction set is around Pentium 4 level,
|
||||
including full SSE2 support. Some features are missing, in particular:
|
||||
including full SSE3 support. Some features are missing, in particular:
|
||||
- Task gates, far calls in protected mode
|
||||
- Some 16 bit protected mode features
|
||||
- Single stepping (trap flag, debug registers)
|
||||
|
|
@ -25,7 +25,7 @@ list of emulated hardware:
|
|||
- A generic VGA card with SVGA support and Bochs VBE Extensions.
|
||||
- A PCI bus. This one is partly incomplete and not used by every device.
|
||||
- An IDE disk controller.
|
||||
- An NE2000 (8390) PCI network card.
|
||||
- An NE2000 (RTL8390) PCI network card.
|
||||
- A virtio filesystem.
|
||||
- A SoundBlaster 16 sound card.
|
||||
|
||||
|
|
@ -81,8 +81,7 @@ Here's an overview of the operating systems supported in v86:
|
|||
- FreeDOS, Windows 1.01 and MS-DOS run very well.
|
||||
- KolibriOS works.
|
||||
- Haiku works.
|
||||
- Android x86 1.6-r2 works if one selects VESA mode at the boot prompt. Newer
|
||||
versions may work if compiled without SSE3. See [#224](https://github.com/copy/v86/issues/224).
|
||||
- Android-x86 works up to 4.4-r2, if you select VESA mode at the boot prompt.
|
||||
- Windows 1, 3.x, 95, 98, ME, NT and 2000 work reasonably well.
|
||||
- In Windows 2000 and higher the PC type has to be changed from ACPI PC to Standard PC
|
||||
- There are some known boot issues ([#250](https://github.com/copy/v86/issues/250), [#433](https://github.com/copy/v86/issues/433), [#507](https://github.com/copy/v86/issues/507), [#555](https://github.com/copy/v86/issues/555), [#620](https://github.com/copy/v86/issues/620), [#645](https://github.com/copy/v86/issues/645))
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ const encodings = [
|
|||
{ opcode: 0xDA, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, skip_mem: 1, }, // unimplemented: fisttp (sse3)
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, }, // fisttp (sse3)
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, },
|
||||
{ opcode: 0xDB, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, },
|
||||
|
|
@ -324,7 +324,7 @@ const encodings = [
|
|||
{ opcode: 0xDC, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 0, custom: 1, is_fpu: 1, task_switch_test: 1, os: 1, },
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, os: 1, skip_mem: 1, }, // unimplemented: fisttp (sse3)
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, os: 1, }, // fisttp (sse3)
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1, os: 1, },
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1, os: 1, },
|
||||
{ opcode: 0xDD, e: 1, fixed_g: 4, custom: 0, is_fpu: 1, task_switch_test: 1, os: 1, skip_mem: 1 }, // frstor
|
||||
|
|
@ -342,7 +342,7 @@ const encodings = [
|
|||
{ opcode: 0xDE, e: 1, fixed_g: 7, custom: 1, is_fpu: 1, task_switch_test: 1, },
|
||||
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 0, custom: 0, is_fpu: 1, task_switch_test: 1 },
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1, skip_mem: 1 }, // unimplemented: fisttp (sse3)
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 1, custom: 0, is_fpu: 1, task_switch_test: 1 }, // fisttp (sse3)
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 2, custom: 1, is_fpu: 1, task_switch_test: 1 },
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 3, custom: 1, is_fpu: 1, task_switch_test: 1 },
|
||||
{ opcode: 0xDF, e: 1, fixed_g: 4, custom: 1, is_fpu: 1, task_switch_test: 1, skip_mem: 1 }, // unimplemented: Binary Coded Decimals
|
||||
|
|
@ -477,7 +477,7 @@ const encodings = [
|
|||
{ opcode: 0x0F36, skip: 1, block_boundary: 1, }, // ud
|
||||
{ opcode: 0x0F37, skip: 1, block_boundary: 1, }, // getsec
|
||||
|
||||
// sse3+
|
||||
// ssse3+
|
||||
{ opcode: 0x0F38, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F39, skip: 1, block_boundary: 1, },
|
||||
{ opcode: 0x0F3A, skip: 1, block_boundary: 1, },
|
||||
|
|
@ -616,7 +616,7 @@ const encodings = [
|
|||
|
||||
|
||||
// mmx, sse
|
||||
// - skipped or missing are sse3+
|
||||
// - skipped or missing are ssse3+
|
||||
|
||||
{ sse: 1, opcode: 0x0F10, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0xF30F10, e: 1, custom: 1 },
|
||||
|
|
@ -628,8 +628,8 @@ const encodings = [
|
|||
{ sse: 1, opcode: 0xF20F11, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0x0F12, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0x660F12, reg_ud: 1, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0xF20F12, e: 1, skip: 1, block_boundary: 1, }, // sse3
|
||||
{ sse: 1, opcode: 0xF30F12, e: 1, skip: 1, block_boundary: 1, }, // sse3
|
||||
{ sse: 1, opcode: 0xF20F12, e: 1, custom: 1 }, // sse3
|
||||
{ sse: 1, opcode: 0xF30F12, e: 1, custom: 1 }, // sse3
|
||||
{ sse: 1, opcode: 0x0F13, reg_ud: 1, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0x660F13, reg_ud: 1, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0x0F14, e: 1, custom: 1 },
|
||||
|
|
@ -638,7 +638,7 @@ const encodings = [
|
|||
{ sse: 1, opcode: 0x660F15, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0x0F16, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0x660F16, reg_ud: 1, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0xF30F16, skip: 1, e: 1, block_boundary: 1, }, // sse3
|
||||
{ sse: 1, opcode: 0xF30F16, e: 1, custom: 1 }, // sse3
|
||||
{ sse: 1, opcode: 0x0F17, reg_ud: 1, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0x660F17, reg_ud: 1, e: 1, custom: 1 },
|
||||
|
||||
|
|
@ -699,7 +699,10 @@ const encodings = [
|
|||
{ sse: 1, opcode: 0x660F59, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0xF20F59, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0xF30F59, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0xF20F7C, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0x660F7C, e: 1, custom: 1 }, // sse3
|
||||
{ sse: 1, opcode: 0xF20F7C, e: 1, custom: 1 }, // sse3
|
||||
{ sse: 1, opcode: 0x660F7D, e: 1, custom: 1 }, // sse3
|
||||
{ sse: 1, opcode: 0xF20F7D, e: 1, custom: 1 }, // sse3
|
||||
|
||||
{ sse: 1, opcode: 0x0F5A, e: 1, custom: 1 },
|
||||
{ sse: 1, opcode: 0x660F5A, e: 1, custom: 1 },
|
||||
|
|
|
|||
|
|
@ -332,6 +332,23 @@ pub unsafe fn fpu_fistm16p(addr: i32) {
|
|||
safe_write16(addr, v as i32).unwrap();
|
||||
fpu_pop();
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe fn fpu_truncate_to_i16(f: F80) -> i16 {
|
||||
let st0 = fpu_truncate_to_i32(f);
|
||||
if st0 < -0x8000 || st0 > 0x7FFF {
|
||||
fpu_invalid_arithmetic();
|
||||
-0x8000
|
||||
}
|
||||
else {
|
||||
st0 as i16
|
||||
}
|
||||
}
|
||||
pub unsafe fn fpu_fisttpm16(addr: i32) {
|
||||
return_on_pagefault!(writable_or_pagefault(addr, 2));
|
||||
let v = fpu_truncate_to_i16(fpu_get_st0());
|
||||
safe_write16(addr, v as i32).unwrap();
|
||||
fpu_pop();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn fpu_convert_to_i32(f: F80) -> i32 {
|
||||
|
|
@ -353,6 +370,19 @@ pub unsafe fn fpu_fistm32p(addr: i32) {
|
|||
safe_write32(addr, v).unwrap();
|
||||
fpu_pop();
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe fn fpu_truncate_to_i32(f: F80) -> i32 {
|
||||
F80::clear_exception_flags();
|
||||
let x = f.truncate_to_i32();
|
||||
*fpu_status_word |= F80::get_exception_flags() as u16;
|
||||
x
|
||||
}
|
||||
pub unsafe fn fpu_fisttpm32(addr: i32) {
|
||||
return_on_pagefault!(writable_or_pagefault(addr, 4));
|
||||
let v = fpu_truncate_to_i32(fpu_get_st0());
|
||||
safe_write32(addr, v).unwrap();
|
||||
fpu_pop();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn fpu_convert_to_i64(f: F80) -> i64 {
|
||||
|
|
@ -368,6 +398,19 @@ pub unsafe fn fpu_fistm64p(addr: i32) {
|
|||
safe_write64(addr, v as u64).unwrap();
|
||||
fpu_pop();
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe fn fpu_truncate_to_i64(f: F80) -> i64 {
|
||||
F80::clear_exception_flags();
|
||||
let x = f.truncate_to_i64();
|
||||
*fpu_status_word |= F80::get_exception_flags() as u16;
|
||||
x
|
||||
}
|
||||
pub unsafe fn fpu_fisttpm64(addr: i32) {
|
||||
return_on_pagefault!(writable_or_pagefault(addr, 8));
|
||||
let v = fpu_truncate_to_i64(fpu_get_st0());
|
||||
safe_write64(addr, v as u64).unwrap();
|
||||
fpu_pop();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn fpu_fldcw(addr: i32) {
|
||||
|
|
|
|||
|
|
@ -1821,10 +1821,7 @@ pub unsafe fn instr_DA_7_reg(_r: i32) { trigger_ud(); }
|
|||
|
||||
pub unsafe fn instr_DB_0_mem(addr: i32) { fpu_fildm32(addr); }
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_DB_1_mem(_addr: i32) {
|
||||
dbg_log!("fisttp");
|
||||
fpu_unimpl();
|
||||
}
|
||||
pub unsafe fn instr_DB_1_mem(addr: i32) { fpu_fisttpm32(addr); }
|
||||
pub unsafe fn instr_DB_2_mem(addr: i32) { fpu_fistm32(addr); }
|
||||
pub unsafe fn instr_DB_3_mem(addr: i32) { fpu_fistm32p(addr); }
|
||||
#[no_mangle]
|
||||
|
|
@ -1880,10 +1877,7 @@ pub unsafe fn instr_DC_7_reg(r: i32) { fpu_fdivr(r, fpu_get_sti(r)); }
|
|||
|
||||
pub unsafe fn instr16_DD_0_mem(addr: i32) { fpu_fldm64(addr); }
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr16_DD_1_mem(_addr: i32) {
|
||||
dbg_log!("fisttp");
|
||||
fpu_unimpl();
|
||||
}
|
||||
pub unsafe fn instr16_DD_1_mem(addr: i32) { fpu_fisttpm64(addr); }
|
||||
pub unsafe fn instr16_DD_2_mem(addr: i32) { fpu_fstm64(addr); }
|
||||
pub unsafe fn instr16_DD_3_mem(addr: i32) { fpu_fstm64p(addr); }
|
||||
#[no_mangle]
|
||||
|
|
@ -1994,10 +1988,7 @@ pub unsafe fn instr_DE_7_reg(r: i32) {
|
|||
#[no_mangle]
|
||||
pub unsafe fn instr_DF_0_mem(addr: i32) { fpu_fildm16(addr) }
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_DF_1_mem(_addr: i32) {
|
||||
dbg_log!("fisttp");
|
||||
fpu_unimpl();
|
||||
}
|
||||
pub unsafe fn instr_DF_1_mem(addr: i32) { fpu_fisttpm16(addr); }
|
||||
pub unsafe fn instr_DF_2_mem(addr: i32) { fpu_fistm16(addr); }
|
||||
pub unsafe fn instr_DF_3_mem(addr: i32) { fpu_fistm16p(addr); }
|
||||
pub unsafe fn instr_DF_4_mem(_addr: i32) {
|
||||
|
|
|
|||
|
|
@ -554,14 +554,30 @@ pub unsafe fn instr_660F12_mem(addr: i32, r: i32) {
|
|||
write_xmm64(r, data);
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_F20F12_mem(_addr: i32, _r: i32) { unimplemented_sse(); }
|
||||
pub unsafe fn instr_F20F12(source: u64, r: i32) {
|
||||
// movddup xmm1, xmm2/m64
|
||||
write_xmm_reg128(r, reg128 { u64: [source, source] });
|
||||
}
|
||||
pub unsafe fn instr_F20F12_reg(r1: i32, r2: i32) { instr_F20F12(read_xmm64s(r1), r2); }
|
||||
pub unsafe fn instr_F20F12_mem(addr: i32, r: i32) {
|
||||
instr_F20F12(return_on_pagefault!(safe_read64s(addr)), r);
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_F20F12_reg(_r1: i32, _r2: i32) { unimplemented_sse(); }
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_F30F12_mem(_addr: i32, _r: i32) { unimplemented_sse(); }
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_F30F12_reg(_r1: i32, _r2: i32) { unimplemented_sse(); }
|
||||
|
||||
pub unsafe fn instr_F30F12(source: reg128, r: i32) {
|
||||
// movsldup xmm1, xmm2/m128
|
||||
write_xmm_reg128(r, reg128 {
|
||||
u32: [
|
||||
source.u32[0],
|
||||
source.u32[0],
|
||||
source.u32[2],
|
||||
source.u32[2],
|
||||
],
|
||||
});
|
||||
}
|
||||
pub unsafe fn instr_F30F12_reg(r1: i32, r2: i32) { instr_F30F12(read_xmm128s(r1), r2); }
|
||||
pub unsafe fn instr_F30F12_mem(addr: i32, r: i32) {
|
||||
instr_F30F12(return_on_pagefault!(safe_read128s(addr)), r);
|
||||
}
|
||||
pub unsafe fn instr_0F13_mem(addr: i32, r: i32) {
|
||||
// movlps m64, xmm
|
||||
movl_r128_m64(addr, r);
|
||||
|
|
@ -658,10 +674,21 @@ pub unsafe fn instr_660F16_mem(addr: i32, r: i32) {
|
|||
}
|
||||
pub unsafe fn instr_660F16_reg(_r1: i32, _r2: i32) { trigger_ud(); }
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_F30F16_reg(_r1: i32, _r2: i32) { unimplemented_sse(); }
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_F30F16_mem(_addr: i32, _r: i32) { unimplemented_sse(); }
|
||||
|
||||
pub unsafe fn instr_F30F16(source: reg128, r: i32) {
|
||||
// movshdup xmm1, xmm2/m128
|
||||
write_xmm_reg128(r, reg128 {
|
||||
u32: [
|
||||
source.u32[1],
|
||||
source.u32[1],
|
||||
source.u32[3],
|
||||
source.u32[3],
|
||||
]
|
||||
});
|
||||
}
|
||||
pub unsafe fn instr_F30F16_reg(r1: i32, r2: i32) { instr_F30F16(read_xmm128s(r1), r2); }
|
||||
pub unsafe fn instr_F30F16_mem(addr: i32, r: i32) {
|
||||
instr_F30F16(return_on_pagefault!(safe_read128s(addr)), r);
|
||||
}
|
||||
pub unsafe fn instr_0F17_mem(addr: i32, r: i32) {
|
||||
// movhps m64, xmm
|
||||
movh_r128_m64(addr, r);
|
||||
|
|
@ -1821,24 +1848,6 @@ pub unsafe fn instr_F30F59_reg(r1: i32, r2: i32) { instr_F30F59(read_xmm_f32(r1)
|
|||
pub unsafe fn instr_F30F59_mem(addr: i32, r: i32) {
|
||||
instr_F30F59(return_on_pagefault!(safe_read_f32(addr)), r);
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_F20F7C(source: reg128, r: i32) {
|
||||
// haddps xmm, xmm/mem128
|
||||
let destination = read_xmm128s(r);
|
||||
let result = reg128 {
|
||||
f32: [
|
||||
destination.f32[0] + destination.f32[1],
|
||||
destination.f32[2] + destination.f32[3],
|
||||
source.f32[0] + source.f32[1],
|
||||
source.f32[2] + source.f32[3],
|
||||
],
|
||||
};
|
||||
write_xmm_reg128(r, result);
|
||||
}
|
||||
pub unsafe fn instr_F20F7C_reg(r1: i32, r2: i32) { instr_F20F7C(read_xmm128s(r1), r2); }
|
||||
pub unsafe fn instr_F20F7C_mem(addr: i32, r: i32) {
|
||||
instr_F20F7C(return_on_pagefault!(safe_read128s(addr)), r);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_0F5A(source: u64, r: i32) {
|
||||
|
|
@ -2946,6 +2955,7 @@ pub unsafe fn instr_0F77() {
|
|||
// emms
|
||||
fpu_set_tag_word(0xFFFF);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_0F78() { unimplemented_sse(); }
|
||||
#[no_mangle]
|
||||
|
|
@ -2954,11 +2964,79 @@ pub unsafe fn instr_0F79() { unimplemented_sse(); }
|
|||
pub unsafe fn instr_0F7A() { unimplemented_sse(); }
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_0F7B() { unimplemented_sse(); }
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_0F7C() { unimplemented_sse(); }
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_0F7D() { unimplemented_sse(); }
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_660F7C(source: reg128, r: i32) {
|
||||
// haddpd xmm1, xmm2/m128
|
||||
let destination = read_xmm128s(r);
|
||||
write_xmm_reg128(r, reg128 {
|
||||
f64: [
|
||||
destination.f64[0] + destination.f64[1],
|
||||
source.f64[0] + source.f64[1],
|
||||
],
|
||||
});
|
||||
}
|
||||
pub unsafe fn instr_660F7C_reg(r1: i32, r2: i32) { instr_660F7C(read_xmm128s(r1), r2); }
|
||||
pub unsafe fn instr_660F7C_mem(addr: i32, r: i32) {
|
||||
instr_660F7C(return_on_pagefault!(safe_read128s(addr)), r);
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_F20F7C(source: reg128, r: i32) {
|
||||
// haddps xmm, xmm/mem128
|
||||
let destination = read_xmm128s(r);
|
||||
write_xmm_reg128(r, reg128 {
|
||||
f32: [
|
||||
destination.f32[0] + destination.f32[1],
|
||||
destination.f32[2] + destination.f32[3],
|
||||
source.f32[0] + source.f32[1],
|
||||
source.f32[2] + source.f32[3],
|
||||
],
|
||||
});
|
||||
}
|
||||
pub unsafe fn instr_F20F7C_reg(r1: i32, r2: i32) { instr_F20F7C(read_xmm128s(r1), r2); }
|
||||
pub unsafe fn instr_F20F7C_mem(addr: i32, r: i32) {
|
||||
instr_F20F7C(return_on_pagefault!(safe_read128s(addr)), r);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_660F7D(source: reg128, r: i32) {
|
||||
// hsubpd xmm1, xmm2/m128
|
||||
let destination = read_xmm128s(r);
|
||||
write_xmm_reg128(r, reg128 {
|
||||
f64: [
|
||||
destination.f64[0] - destination.f64[1],
|
||||
source.f64[0] - source.f64[1],
|
||||
],
|
||||
});
|
||||
}
|
||||
pub unsafe fn instr_660F7D_reg(r1: i32, r2: i32) { instr_660F7D(read_xmm128s(r1), r2); }
|
||||
pub unsafe fn instr_660F7D_mem(addr: i32, r: i32) {
|
||||
instr_660F7D(return_on_pagefault!(safe_read128s(addr)), r);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_F20F7D(source: reg128, r: i32) {
|
||||
// hsubps xmm1, xmm2/m128
|
||||
let destination = read_xmm128s(r);
|
||||
write_xmm_reg128(r, reg128 {
|
||||
f32: [
|
||||
destination.f32[0] - destination.f32[1],
|
||||
destination.f32[2] - destination.f32[3],
|
||||
source.f32[0] - source.f32[1],
|
||||
source.f32[2] - source.f32[3],
|
||||
],
|
||||
});
|
||||
}
|
||||
pub unsafe fn instr_F20F7D_reg(r1: i32, r2: i32) { instr_F20F7D(read_xmm128s(r1), r2); }
|
||||
pub unsafe fn instr_F20F7D_mem(addr: i32, r: i32) {
|
||||
instr_F20F7D(return_on_pagefault!(safe_read128s(addr)), r);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe fn instr_0F7E(r: i32) -> i32 {
|
||||
// movd r/m32, mm
|
||||
|
|
@ -3145,7 +3223,7 @@ pub unsafe fn instr_0FA2() {
|
|||
// pentium
|
||||
eax = 3 | 6 << 4 | 15 << 8;
|
||||
ebx = 1 << 16 | 8 << 8; // cpu count, clflush size
|
||||
ecx = 1 << 23 | 1 << 30; // popcnt, rdrand
|
||||
ecx = 1 << 0 | 1 << 23 | 1 << 30; // sse3, popcnt, rdrand
|
||||
let vme = 0 << 1;
|
||||
if ::config::VMWARE_HYPERVISOR_PORT {
|
||||
ecx |= 1 << 31
|
||||
|
|
|
|||
|
|
@ -5738,6 +5738,19 @@ pub fn instr_660F12_reg_jit(ctx: &mut JitContext, _r1: u32, _r2: u32) {
|
|||
codegen::gen_trigger_ud(ctx);
|
||||
}
|
||||
|
||||
pub fn instr_F20F12_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
sse_read64_xmm_mem(ctx, "instr_F20F12", modrm_byte, r);
|
||||
}
|
||||
pub fn instr_F20F12_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
sse_read64_xmm_xmm(ctx, "instr_F20F12", r1, r2);
|
||||
}
|
||||
pub fn instr_F30F12_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
sse_read128_xmm_mem(ctx, "instr_F30F12", modrm_byte, r);
|
||||
}
|
||||
pub fn instr_F30F12_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
sse_read128_xmm_xmm(ctx, "instr_F30F12", r1, r2);
|
||||
}
|
||||
|
||||
pub fn instr_0F13_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
instr_660FD6_mem_jit(ctx, modrm_byte, r)
|
||||
}
|
||||
|
|
@ -5790,6 +5803,13 @@ pub fn instr_660F16_reg_jit(ctx: &mut JitContext, _r1: u32, _r2: u32) {
|
|||
codegen::gen_trigger_ud(ctx);
|
||||
}
|
||||
|
||||
pub fn instr_F30F16_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
sse_read128_xmm_mem(ctx, "instr_F30F16", modrm_byte, r);
|
||||
}
|
||||
pub fn instr_F30F16_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
sse_read128_xmm_xmm(ctx, "instr_F30F16", r1, r2);
|
||||
}
|
||||
|
||||
pub fn instr_0F17_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
||||
let address_local = ctx.builder.set_new_local();
|
||||
|
|
@ -6128,12 +6148,6 @@ pub fn instr_F30F59_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32)
|
|||
pub fn instr_F30F59_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
sse_read_f32_xmm_xmm(ctx, "instr_F30F59", r1, r2);
|
||||
}
|
||||
pub fn instr_F20F7C_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
sse_read128_xmm_mem(ctx, "instr_F20F7C", modrm_byte, r);
|
||||
}
|
||||
pub fn instr_F20F7C_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
sse_read128_xmm_xmm(ctx, "instr_F20F7C", r1, r2);
|
||||
}
|
||||
|
||||
pub fn instr_0F5A_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
sse_read64_xmm_mem(ctx, "instr_0F5A", modrm_byte, r);
|
||||
|
|
@ -6766,6 +6780,31 @@ pub fn instr_660F76_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
|||
sse_read128_xmm_xmm(ctx, "instr_660F76", r1, r2);
|
||||
}
|
||||
|
||||
pub fn instr_660F7C_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
sse_read128_xmm_mem(ctx, "instr_660F7C", modrm_byte, r);
|
||||
}
|
||||
pub fn instr_660F7C_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
sse_read128_xmm_xmm(ctx, "instr_660F7C", r1, r2);
|
||||
}
|
||||
pub fn instr_F20F7C_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
sse_read128_xmm_mem(ctx, "instr_F20F7C", modrm_byte, r);
|
||||
}
|
||||
pub fn instr_F20F7C_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
sse_read128_xmm_xmm(ctx, "instr_F20F7C", r1, r2);
|
||||
}
|
||||
pub fn instr_660F7D_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
sse_read128_xmm_mem(ctx, "instr_660F7D", modrm_byte, r);
|
||||
}
|
||||
pub fn instr_660F7D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
sse_read128_xmm_xmm(ctx, "instr_660F7D", r1, r2);
|
||||
}
|
||||
pub fn instr_F20F7D_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
sse_read128_xmm_mem(ctx, "instr_F20F7D", modrm_byte, r);
|
||||
}
|
||||
pub fn instr_F20F7D_reg_jit(ctx: &mut JitContext, r1: u32, r2: u32) {
|
||||
sse_read128_xmm_xmm(ctx, "instr_F20F7D", r1, r2);
|
||||
}
|
||||
|
||||
pub fn instr_0F7E_mem_jit(ctx: &mut JitContext, modrm_byte: ModrmByte, r: u32) {
|
||||
codegen::gen_modrm_resolve(ctx, modrm_byte);
|
||||
let address_local = ctx.builder.set_new_local();
|
||||
|
|
|
|||
|
|
@ -129,6 +129,9 @@ impl F80 {
|
|||
pub fn to_i32(&self) -> i32 { unsafe { extF80M_to_i32(self, softfloat_roundingMode, false) } }
|
||||
pub fn to_i64(&self) -> i64 { unsafe { extF80M_to_i64(self, softfloat_roundingMode, false) } }
|
||||
|
||||
pub fn truncate_to_i32(&self) -> i32 { unsafe { extF80M_to_i32(self, 1, false) } }
|
||||
pub fn truncate_to_i64(&self) -> i64 { unsafe { extF80M_to_i64(self, 1, false) } }
|
||||
|
||||
pub fn cos(self) -> F80 { F80::of_f64x(self.to_f64x().cos()) }
|
||||
pub fn sin(self) -> F80 { F80::of_f64x(self.to_f64x().sin()) }
|
||||
pub fn tan(self) -> F80 { F80::of_f64x(self.to_f64x().tan()) }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue