sse: Implement 0F2C/0F2D/CVTT[PS][SD]2[SP]I (#57)

This commit is contained in:
Fabian 2018-08-28 12:43:06 -05:00
parent 9665dbf994
commit 3ea0089878
3 changed files with 81 additions and 18 deletions

View file

@ -548,14 +548,14 @@ const encodings = [
{ sse: 1, opcode: 0x0F2B, reg_ud: 1, e: 1 },
{ sse: 1, opcode: 0x660F2B, reg_ud: 1, e: 1 },
{ sse: 1, opcode: 0x0F2C, e: 1, skip: 1, },
{ sse: 1, opcode: 0x660F2C, e: 1, skip: 1, },
{ sse: 1, opcode: 0x0F2C, e: 1, },
{ sse: 1, opcode: 0x660F2C, e: 1, },
{ sse: 1, opcode: 0xF20F2C, e: 1, },
{ sse: 1, opcode: 0xF30F2C, e: 1, skip: 1, },
{ sse: 1, opcode: 0x0F2D, e: 1, skip: 1, },
{ sse: 1, opcode: 0x660F2D, e: 1, skip: 1, },
{ sse: 1, opcode: 0xF30F2C, e: 1, },
{ sse: 1, opcode: 0x0F2D, e: 1, },
{ sse: 1, opcode: 0x660F2D, e: 1, },
{ sse: 1, opcode: 0xF20F2D, e: 1, },
{ sse: 1, opcode: 0xF30F2D, e: 1, skip: 1, },
{ sse: 1, opcode: 0xF30F2D, e: 1, },
{ sse: 1, opcode: 0x0F2E, e: 1 },
{ sse: 1, opcode: 0x660F2E, e: 1 },

View file

@ -984,24 +984,46 @@ pub unsafe fn instr_660F2B_mem(mut addr: i32, mut r: i32) -> () {
c_comment!(("XXX: Aligned write or #gp"));
mov_r_m128(addr, r);
}
#[no_mangle]
pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) -> () {
// cvttps2pi mm, xmm/m64
let result = reg64 {
i32_0: [
sse_convert_f32_to_i32(source.f32_0[0].trunc()),
sse_convert_f32_to_i32(source.f32_0[1].trunc()),
],
};
write_mmx_reg64(r, result);
}
#[no_mangle]
pub unsafe fn instr_0F2C_mem(mut addr: i32, mut r: i32) -> () {
instr_0F2C(return_on_pagefault!(safe_read64s(addr)), r);
}
#[no_mangle]
pub unsafe fn instr_0F2C(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); }
pub unsafe fn instr_0F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2C(read_xmm64s(r1), r2); }
#[no_mangle]
pub unsafe fn instr_0F2C_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2C(read_mmx64s(r1), r2); }
pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) -> () {
// cvttpd2pi mm, xmm/m128
let result = reg64 {
// XXX: Check conversion
i32_0: [
sse_convert_f64_to_i32(source.f64_0[0]),
sse_convert_f64_to_i32(source.f64_0[1]),
],
};
write_mmx_reg64(r, result);
}
#[no_mangle]
pub unsafe fn instr_660F2C_mem(mut addr: i32, mut r: i32) -> () {
instr_660F2C(return_on_pagefault!(safe_read128s(addr)), r);
}
#[no_mangle]
pub unsafe fn instr_660F2C(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); }
#[no_mangle]
pub unsafe fn instr_660F2C_reg(mut r1: i32, mut r2: i32) -> () {
instr_660F2C(read_xmm128s(r1), r2);
}
#[no_mangle]
pub unsafe fn instr_F20F2C(mut source: reg64, mut r: i32) -> () {
let mut si: i32 = 0;
@ -1032,13 +1054,17 @@ pub unsafe fn instr_F20F2C_reg(mut r1: i32, mut r2: i32) -> () {
pub unsafe fn instr_F20F2C_mem(mut addr: i32, mut r: i32) -> () {
instr_F20F2C(return_on_pagefault!(safe_read64s(addr)), r);
}
#[no_mangle]
pub unsafe fn instr_F30F2C(source: f32, mut r: i32) -> () {
let result = source.trunc();
write_reg32(r, sse_convert_f32_to_i32(source));
}
#[no_mangle]
pub unsafe fn instr_F30F2C_mem(mut addr: i32, mut r: i32) -> () {
instr_F30F2C(return_on_pagefault!(fpu_load_m32(addr)) as f32, r);
}
#[no_mangle]
pub unsafe fn instr_F30F2C(mut source: f32, mut r: i32) -> () { unimplemented_sse(); }
#[no_mangle]
pub unsafe fn instr_F30F2C_reg(mut r1: i32, mut r2: i32) -> () {
instr_F30F2C(read_xmm_f32(r1), r2);
}
@ -5874,16 +5900,36 @@ pub unsafe fn instr_F30F2A_reg(mut r1: i32, mut r2: i32) -> () { instr_F30F2A(re
pub unsafe fn instr_F30F2A_mem(mut addr: i32, mut r: i32) -> () {
instr_F30F2A(return_on_pagefault!(safe_read32s(addr)), r);
}
#[no_mangle]
pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) -> () { unimplemented_sse(); }
pub unsafe fn instr_0F2D(mut source: reg64, mut r: i32) -> () {
// cvtps2pi mm, xmm/m64
let result = reg64 {
i32_0: [
sse_convert_f32_to_i32(source.f32_0[0].round()),
sse_convert_f32_to_i32(source.f32_0[1].round()),
],
};
write_mmx_reg64(r, result);
}
#[no_mangle]
pub unsafe fn instr_0F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2D(read_mmx64s(r1), r2); }
pub unsafe fn instr_0F2D_reg(mut r1: i32, mut r2: i32) -> () { instr_0F2D(read_xmm64s(r1), r2); }
#[no_mangle]
pub unsafe fn instr_0F2D_mem(mut addr: i32, mut r: i32) -> () {
instr_0F2D(return_on_pagefault!(safe_read64s(addr)), r);
}
#[no_mangle]
pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) -> () { unimplemented_sse(); }
pub unsafe fn instr_660F2D(mut source: reg128, mut r: i32) -> () {
// cvtpd2pi mm, xmm/m128
let result = reg64 {
i32_0: [
sse_convert_f64_to_i32(source.f64_0[0].round()),
sse_convert_f64_to_i32(source.f64_0[1].round()),
],
};
write_mmx_reg64(r, result);
}
#[no_mangle]
pub unsafe fn instr_660F2D_reg(mut r1: i32, mut r2: i32) -> () {
instr_660F2D(read_xmm128s(r1), r2);
@ -5906,7 +5952,10 @@ pub unsafe fn instr_F20F2D_mem(mut addr: i32, mut r: i32) -> () {
instr_F20F2D(return_on_pagefault!(safe_read64s(addr)), r);
}
#[no_mangle]
pub unsafe fn instr_F30F2D(mut source: f32, mut r: i32) -> () { unimplemented_sse(); }
pub unsafe fn instr_F30F2D(mut source: f32, mut r: i32) -> () {
// cvtss2si r32, xmm1/m32
write_reg32(r, sse_convert_f32_to_i32(source.round()));
}
#[no_mangle]
pub unsafe fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) -> () {
instr_F30F2D(read_xmm_f32(r1), r2);
@ -5915,6 +5964,7 @@ pub unsafe fn instr_F30F2D_reg(mut r1: i32, mut r2: i32) -> () {
pub unsafe fn instr_F30F2D_mem(mut addr: i32, mut r: i32) -> () {
instr_F30F2D(return_on_pagefault!(fpu_load_m32(addr)) as f32, r);
}
#[no_mangle]
pub unsafe fn instr_0F51(mut source: reg128, mut r: i32) -> () {
c_comment!(("sqrtps xmm, xmm/mem128"));

View file

@ -397,10 +397,23 @@ pub unsafe fn sse_max(mut x: f64, mut y: f64) -> f64 {
c_comment!(("if both x and y are 0 or x is nan, y is returned"));
return if x > y { x } else { y };
}
#[no_mangle]
pub unsafe fn sse_convert_f64_to_i32(mut x: f64) -> i32 {
pub unsafe fn sse_convert_f32_to_i32(mut x: f32) -> i32 {
c_comment!(("TODO: Rounding modes"));
if x >= 2147483648u32.wrapping_neg() as f64 && x < 2147483648u32 as f64 {
if x >= -2147483648.0 && x < 2147483648.0 {
return x as i64 as i32;
}
else {
c_comment!(("TODO: Signal"));
return 2147483648u32.wrapping_neg() as i32;
};
}
#[no_mangle]
pub unsafe fn sse_convert_f64_to_i32(mut x: f64) -> i32 {
c_comment!(("TODO: Rounding modes"));
if x >= -2147483648.0 as f64 && x < 2147483648.0 as f64 {
return x as i64 as i32;
}
else {