Fix conversions trapping and fix some weirdness around conditional jumps

This commit is contained in:
Jef
2019-03-21 11:47:50 +01:00
parent 14bff9229e
commit 4eb546c6a5
2 changed files with 184 additions and 115 deletions

View File

@@ -180,71 +180,71 @@ test spec_testsuite::comments ... ok
test spec_testsuite::const_ ... ok test spec_testsuite::const_ ... ok
test spec_testsuite::call ... ok test spec_testsuite::call ... ok
test spec_testsuite::custom ... ok test spec_testsuite::custom ... ok
test spec_testsuite::conversions ... FAILED
test spec_testsuite::custom_section ... ok test spec_testsuite::custom_section ... ok
test spec_testsuite::data ... ok test spec_testsuite::data ... ok
test spec_testsuite::br_table ... FAILED
test spec_testsuite::elem ... ok test spec_testsuite::elem ... ok
test spec_testsuite::br_table ... FAILED
test spec_testsuite::conversions ... ok
test spec_testsuite::call_indirect ... ok test spec_testsuite::call_indirect ... ok
test spec_testsuite::exports ... ok test spec_testsuite::exports ... ok
test spec_testsuite::endianness ... ok test spec_testsuite::endianness ... ok
test spec_testsuite::f32_bitwise ... ok test spec_testsuite::f32_bitwise ... ok
test spec_testsuite::f64_bitwise ... ok test spec_testsuite::f64_bitwise ... ok
test spec_testsuite::f32 ... ok
test spec_testsuite::f32_cmp ... ok test spec_testsuite::f32_cmp ... ok
test spec_testsuite::fac ... ok test spec_testsuite::fac ... ok
test spec_testsuite::f64 ... ok test spec_testsuite::f64 ... ok
test spec_testsuite::f32 ... ok
test spec_testsuite::float_memory ... ok
test spec_testsuite::f64_cmp ... ok test spec_testsuite::f64_cmp ... ok
test spec_testsuite::float_memory ... ok
test spec_testsuite::forward ... ok test spec_testsuite::forward ... ok
test spec_testsuite::float_literals ... ok
test spec_testsuite::float_misc ... ok test spec_testsuite::float_misc ... ok
test spec_testsuite::func_ptrs ... ok test spec_testsuite::func_ptrs ... ok
test spec_testsuite::float_literals ... ok test spec_testsuite::get_local ... ok
test spec_testsuite::get_local ... FAILED
test spec_testsuite::func ... ok test spec_testsuite::func ... ok
test spec_testsuite::float_exprs ... FAILED
test spec_testsuite::globals ... ok test spec_testsuite::globals ... ok
test spec_testsuite::i32 ... ok test spec_testsuite::i32 ... ok
test spec_testsuite::inline_module ... ok
test spec_testsuite::if_ ... ok
test spec_testsuite::i64 ... ok test spec_testsuite::i64 ... ok
test spec_testsuite::inline_module ... ok
test spec_testsuite::imports ... ok test spec_testsuite::imports ... ok
test spec_testsuite::labels ... ok test spec_testsuite::if_ ... ok
test spec_testsuite::int_literals ... ok test spec_testsuite::int_literals ... ok
test spec_testsuite::labels ... ok
test spec_testsuite::linking ... ok test spec_testsuite::linking ... ok
test spec_testsuite::int_exprs ... ok test spec_testsuite::int_exprs ... ok
test spec_testsuite::loop_ ... ok test spec_testsuite::loop_ ... ok
test spec_testsuite::memory_redundancy ... ok
test spec_testsuite::left_to_right ... ok test spec_testsuite::left_to_right ... ok
test spec_testsuite::memory_redundancy ... ok
test spec_testsuite::memory ... ok test spec_testsuite::memory ... ok
test spec_testsuite::memory_grow ... ok
test spec_testsuite::memory_trap ... ok test spec_testsuite::memory_trap ... ok
test spec_testsuite::resizing ... ok test spec_testsuite::resizing ... ok
test spec_testsuite::memory_grow ... ok test spec_testsuite::float_exprs ... ok
test spec_testsuite::return_minimal ... ok test spec_testsuite::return_minimal ... ok
test spec_testsuite::select ... ok
test spec_testsuite::return_ ... ok test spec_testsuite::return_ ... ok
test spec_testsuite::set_local ... FAILED test spec_testsuite::select ... ok
test spec_testsuite::skip_stack_guard_page ... FAILED test spec_testsuite::set_local ... ok
test spec_testsuite::nop ... ok test spec_testsuite::nop ... ok
test spec_testsuite::start ... ok test spec_testsuite::skip_stack_guard_page ... FAILED
test spec_testsuite::store_retval ... ok test spec_testsuite::store_retval ... ok
test spec_testsuite::stack ... ok test spec_testsuite::stack ... ok
test spec_testsuite::start ... ok
test spec_testsuite::token ... ok test spec_testsuite::token ... ok
test spec_testsuite::switch ... ok test spec_testsuite::switch ... ok
test spec_testsuite::type_ ... ok test spec_testsuite::type_ ... ok
test spec_testsuite::traps ... FAILED
test spec_testsuite::typecheck ... ok test spec_testsuite::typecheck ... ok
test spec_testsuite::traps ... ok
test spec_testsuite::unreached_invalid ... ok test spec_testsuite::unreached_invalid ... ok
test spec_testsuite::unwind ... FAILED test spec_testsuite::unwind ... FAILED
test spec_testsuite::utf8_custom_section_id ... ok test spec_testsuite::utf8_custom_section_id ... ok
test spec_testsuite::utf8_import_field ... ok test spec_testsuite::utf8_import_field ... ok
test spec_testsuite::utf8_import_module ... ok test spec_testsuite::utf8_import_module ... ok
test spec_testsuite::tee_local ... ok
test spec_testsuite::utf8_invalid_encoding ... ok test spec_testsuite::utf8_invalid_encoding ... ok
test spec_testsuite::tee_local ... FAILED
test spec_testsuite::unreachable ... ok test spec_testsuite::unreachable ... ok
test spec_testsuite::names ... ok test spec_testsuite::names ... ok
test result: FAILED. 65 passed; 9 failed; 0 ignored; 0 measured; 0 filtered out test result: FAILED. 71 passed; 3 failed; 0 ignored; 0 measured; 3 filtered out
``` ```
## Getting involved ## Getting involved

View File

@@ -2162,12 +2162,15 @@ impl<'this, M: ModuleContext> Context<'this, M> {
.map(|c| *c) .map(|c| *c)
.unwrap_or_else(|| self.ret_label()); .unwrap_or_else(|| self.ret_label());
pass_args(self);
let predicate = self.into_reg(I32, val); let predicate = self.into_reg(I32, val);
dynasm!(self.asm dynasm!(self.asm
; test Rd(predicate.rq().unwrap()), Rd(predicate.rq().unwrap()) ; test Rd(predicate.rq().unwrap()), Rd(predicate.rq().unwrap())
);
pass_args(self);
dynasm!(self.asm
; jz =>label.0 ; jz =>label.0
); );
@@ -2188,12 +2191,15 @@ impl<'this, M: ModuleContext> Context<'this, M> {
.map(|c| *c) .map(|c| *c)
.unwrap_or_else(|| self.ret_label()); .unwrap_or_else(|| self.ret_label());
pass_args(self);
let predicate = self.into_reg(I32, val); let predicate = self.into_reg(I32, val);
dynasm!(self.asm dynasm!(self.asm
; test Rd(predicate.rq().unwrap()), Rd(predicate.rq().unwrap()) ; test Rd(predicate.rq().unwrap()), Rd(predicate.rq().unwrap())
);
pass_args(self);
dynasm!(self.asm
; jnz =>label.0 ; jnz =>label.0
); );
@@ -2344,7 +2350,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
self.pop_into(dst.into()); self.pop_into(dst.into());
} }
self.set_stack_depth(cc.stack_depth); self.set_stack_depth_preserve_flags(cc.stack_depth);
} }
/// Puts all stack values into "real" locations so that they can i.e. be set to different /// Puts all stack values into "real" locations so that they can i.e. be set to different
@@ -2452,31 +2458,27 @@ impl<'this, M: ModuleContext> Context<'this, M> {
} }
fn immediate_to_reg(&mut self, reg: GPR, val: Value) { fn immediate_to_reg(&mut self, reg: GPR, val: Value) {
if val.as_bytes() == 0 { match reg {
self.zero_reg(reg); GPR::Rq(r) => {
} else { let val = val.as_bytes();
match reg { if (val as u64) <= u32::max_value() as u64 {
GPR::Rq(r) => {
let val = val.as_bytes();
if (val as u64) <= u32::max_value() as u64 {
dynasm!(self.asm
; mov Rd(r), val as i32
);
} else {
dynasm!(self.asm
; mov Rq(r), QWORD val
);
}
}
GPR::Rx(r) => {
let temp = self.block_state.regs.take(I64);
self.immediate_to_reg(temp, val);
dynasm!(self.asm dynasm!(self.asm
; movq Rx(r), Rq(temp.rq().unwrap()) ; mov Rd(r), val as i32
);
} else {
dynasm!(self.asm
; mov Rq(r), QWORD val
); );
self.block_state.regs.release(temp);
} }
} }
GPR::Rx(r) => {
let temp = self.block_state.regs.take(I64);
self.immediate_to_reg(temp, val);
dynasm!(self.asm
; movq Rx(r), Rq(temp.rq().unwrap())
);
self.block_state.regs.release(temp);
}
} }
} }
@@ -3068,18 +3070,18 @@ impl<'this, M: ModuleContext> Context<'this, M> {
let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32)); let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32));
let float_cmp_mask = self.aligned_label(16, LabelValue::I32(0xcf000000u32 as i32)); let float_cmp_mask = self.aligned_label(16, LabelValue::I32(0xcf000000u32 as i32));
let zero = self.aligned_label(16, LabelValue::I32(0)); let zero = self.aligned_label(16, LabelValue::I32(0));
let trap_mask = self.trap_label(); let trap_label = self.trap_label();
dynasm!(self.asm dynasm!(self.asm
; cvttss2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttss2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; cmp Rd(temp.rq().unwrap()), [=>sign_mask.0] ; cmp Rd(temp.rq().unwrap()), [=>sign_mask.0]
; jne >ret ; jne >ret
; ucomiss Rx(reg.rx().unwrap()), Rx(reg.rx().unwrap()) ; ucomiss Rx(reg.rx().unwrap()), Rx(reg.rx().unwrap())
; jp =>trap_mask.0 ; jp =>trap_label.0
; ucomiss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0] ; ucomiss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
; jnae =>trap_mask.0 ; jnae =>trap_label.0
; ucomiss Rx(reg.rx().unwrap()), [=>zero.0] ; ucomiss Rx(reg.rx().unwrap()), [=>zero.0]
; jnb =>trap_mask.0 ; jnb =>trap_label.0
; ret: ; ret:
); );
@@ -3106,21 +3108,21 @@ impl<'this, M: ModuleContext> Context<'this, M> {
let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32)); let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32));
let float_cmp_mask = self.aligned_label(16, LabelValue::I32(0x4f000000u32 as i32)); let float_cmp_mask = self.aligned_label(16, LabelValue::I32(0x4f000000u32 as i32));
let zero = self.aligned_label(16, LabelValue::I32(0)); let zero = self.aligned_label(16, LabelValue::I32(0));
let trap_mask = self.trap_label(); let trap_label = self.trap_label();
dynasm!(self.asm dynasm!(self.asm
; ucomiss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0] ; ucomiss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
; jae >else_ ; jae >else_
; jp =>trap_mask.0 ; jp =>trap_label.0
; cvttss2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttss2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; cmp Rd(temp.rq().unwrap()), 0 ; test Rd(temp.rq().unwrap()), Rd(temp.rq().unwrap())
; jnge =>trap_mask.0 ; js =>trap_label.0
; jmp >ret ; jmp >ret
; else_: ; else_:
; subss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0] ; subss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
; cvttss2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttss2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; cmp Rd(temp.rq().unwrap()), 0 ; test Rd(temp.rq().unwrap()), Rd(temp.rq().unwrap())
; jnge =>trap_mask.0 ; js =>trap_label.0
; add Rq(temp.rq().unwrap()), [=>sign_mask.0] ; add Rq(temp.rq().unwrap()), [=>sign_mask.0]
; ret: ; ret:
); );
@@ -3147,20 +3149,21 @@ impl<'this, M: ModuleContext> Context<'this, M> {
val = ValueLocation::Reg(reg); val = ValueLocation::Reg(reg);
let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32)); let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32));
let float_cmp_mask = self.aligned_label(16, LabelValue::I64(0xc1e0000000200000u64 as i64)); let float_cmp_mask =
self.aligned_label(16, LabelValue::I64(0xc1e0000000200000u64 as i64));
let zero = self.aligned_label(16, LabelValue::I64(0)); let zero = self.aligned_label(16, LabelValue::I64(0));
let trap_mask = self.trap_label(); let trap_label = self.trap_label();
dynasm!(self.asm dynasm!(self.asm
; cvttsd2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttsd2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; cmp Rd(temp.rq().unwrap()), [=>sign_mask.0] ; cmp Rd(temp.rq().unwrap()), [=>sign_mask.0]
; jne >ret ; jne >ret
; ucomisd Rx(reg.rx().unwrap()), Rx(reg.rx().unwrap()) ; ucomisd Rx(reg.rx().unwrap()), Rx(reg.rx().unwrap())
; jp =>trap_mask.0 ; jp =>trap_label.0
; ucomisd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0] ; ucomisd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
; jna =>trap_mask.0 ; jna =>trap_label.0
; ucomisd Rx(reg.rx().unwrap()), [=>zero.0] ; ucomisd Rx(reg.rx().unwrap()), [=>zero.0]
; jnb =>trap_mask.0 ; jnb =>trap_label.0
; ret: ; ret:
); );
@@ -3186,23 +3189,24 @@ impl<'this, M: ModuleContext> Context<'this, M> {
let temp = self.block_state.regs.take(I32); let temp = self.block_state.regs.take(I32);
let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32)); let sign_mask = self.aligned_label(4, LabelValue::I32(SIGN_MASK_F32 as i32));
let float_cmp_mask = self.aligned_label(16, LabelValue::I64(0x41e0000000000000u64 as i64)); let float_cmp_mask =
self.aligned_label(16, LabelValue::I64(0x41e0000000000000u64 as i64));
let zero = self.aligned_label(16, LabelValue::I64(0)); let zero = self.aligned_label(16, LabelValue::I64(0));
let trap_mask = self.trap_label(); let trap_label = self.trap_label();
dynasm!(self.asm dynasm!(self.asm
; ucomisd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0] ; ucomisd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
; jae >else_ ; jae >else_
; jp =>trap_mask.0 ; jp =>trap_label.0
; cvttsd2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttsd2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; cmp Rd(temp.rq().unwrap()), 0 ; test Rd(temp.rq().unwrap()), Rd(temp.rq().unwrap())
; jnge =>trap_mask.0 ; js =>trap_label.0
; jmp >ret ; jmp >ret
; else_: ; else_:
; subsd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0] ; subsd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
; cvttsd2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttsd2si Rd(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; cmp Rd(temp.rq().unwrap()), 0 ; test Rd(temp.rq().unwrap()), Rd(temp.rq().unwrap())
; jnge =>trap_mask.0 ; js =>trap_label.0
; add Rq(temp.rq().unwrap()), [=>sign_mask.0] ; add Rq(temp.rq().unwrap()), [=>sign_mask.0]
; ret: ; ret:
); );
@@ -3265,30 +3269,84 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|a| wasmparser::Ieee64((a as f64).to_bits()) |a| wasmparser::Ieee64((a as f64).to_bits())
); );
conversion!( pub fn i64_truncate_f32_s(&mut self) {
i64_truncate_f32_s, let mut val = self.pop();
cvttss2si,
Rx, let out_val = match val {
rx, ValueLocation::Immediate(imm) => ValueLocation::Immediate(
Rq, (f32::from_bits(imm.as_f32().unwrap().bits()) as i32).into(),
rq, ),
f32, other => {
i64, let reg = self.into_temp_reg(F32, other);
as_f32, val = ValueLocation::Reg(reg);
|a: wasmparser::Ieee32| f32::from_bits(a.bits()) as i64 let temp = self.block_state.regs.take(I32);
);
conversion!( let sign_mask = self.aligned_label(16, LabelValue::I64(SIGN_MASK_F64 as i64));
i64_truncate_f64_s, let float_cmp_mask = self.aligned_label(16, LabelValue::I32(0xdf000000u32 as i32));
cvttsd2si, let zero = self.aligned_label(16, LabelValue::I64(0));
Rx, let trap_label = self.trap_label();
rx,
Rq, dynasm!(self.asm
rq, ; cvttss2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap())
f64, ; cmp Rq(temp.rq().unwrap()), [=>sign_mask.0]
i64, ; jne >ret
as_f64, ; ucomiss Rx(reg.rx().unwrap()), Rx(reg.rx().unwrap())
|a: wasmparser::Ieee64| f64::from_bits(a.bits()) as i64 ; jp =>trap_label.0
); ; ucomiss Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
; jnae =>trap_label.0
; ucomiss Rx(reg.rx().unwrap()), [=>zero.0]
; jnb =>trap_label.0
; ret:
);
ValueLocation::Reg(temp)
}
};
self.free_value(val);
self.push(out_val);
}
pub fn i64_truncate_f64_s(&mut self) {
let mut val = self.pop();
let out_val = match val {
ValueLocation::Immediate(imm) => ValueLocation::Immediate(
(f64::from_bits(imm.as_f64().unwrap().bits()) as i32).into(),
),
other => {
let reg = self.into_reg(F32, other);
let temp = self.block_state.regs.take(I32);
val = ValueLocation::Reg(reg);
let sign_mask = self.aligned_label(8, LabelValue::I64(SIGN_MASK_F64 as i64));
let float_cmp_mask =
self.aligned_label(16, LabelValue::I64(0xc3e0000000000000u64 as i64));
let zero = self.aligned_label(16, LabelValue::I64(0));
let trap_label = self.trap_label();
dynasm!(self.asm
; cvttsd2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; cmp Rq(temp.rq().unwrap()), [=>sign_mask.0]
; jne >ret
; ucomisd Rx(reg.rx().unwrap()), Rx(reg.rx().unwrap())
; jp =>trap_label.0
; ucomisd Rx(reg.rx().unwrap()), [=>float_cmp_mask.0]
; jnae =>trap_label.0
; ucomisd Rx(reg.rx().unwrap()), [=>zero.0]
; jnb =>trap_label.0
; ret:
);
ValueLocation::Reg(temp)
}
};
self.free_value(val);
self.push(out_val);
}
pub fn i64_truncate_f32_u(&mut self) { pub fn i64_truncate_f32_u(&mut self) {
struct Trunc; struct Trunc;
@@ -3304,17 +3362,24 @@ impl<'this, M: ModuleContext> Context<'this, M> {
val = ValueLocation::Reg(reg); val = ValueLocation::Reg(reg);
let temp = self.block_state.regs.take(I64); let temp = self.block_state.regs.take(I64);
let sign_mask = self.aligned_label(16, LabelValue::I64(SIGN_MASK_F64 as i64));
let u64_trunc_f32_const = self.aligned_label(16, LabelValue::I32(0x5F000000)); let u64_trunc_f32_const = self.aligned_label(16, LabelValue::I32(0x5F000000));
let trap_label = self.trap_label();
dynasm!(self.asm dynasm!(self.asm
; comiss Rx(reg.rx().unwrap()), [=>u64_trunc_f32_const.0] ; comiss Rx(reg.rx().unwrap()), [=>u64_trunc_f32_const.0]
; jnb >large ; jae >large
; jp =>trap_label.0
; cvttss2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttss2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; test Rq(temp.rq().unwrap()), Rq(temp.rq().unwrap())
; js =>trap_label.0
; jmp >cont ; jmp >cont
; large: ; large:
; subss Rx(reg.rx().unwrap()), [=>u64_trunc_f32_const.0] ; subss Rx(reg.rx().unwrap()), [=>u64_trunc_f32_const.0]
; cvttss2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttss2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; btc Rq(temp.rq().unwrap()), 0b00111111 ; test Rq(temp.rq().unwrap()), Rq(temp.rq().unwrap())
; js =>trap_label.0
; add Rq(temp.rq().unwrap()), [=>sign_mask.0]
; cont: ; cont:
); );
@@ -3339,18 +3404,25 @@ impl<'this, M: ModuleContext> Context<'this, M> {
val = ValueLocation::Reg(reg); val = ValueLocation::Reg(reg);
let temp = self.block_state.regs.take(I64); let temp = self.block_state.regs.take(I64);
let sign_mask = self.aligned_label(16, LabelValue::I64(SIGN_MASK_F64 as i64));
let u64_trunc_f64_const = let u64_trunc_f64_const =
self.aligned_label(16, LabelValue::I64(0x43E0000000000000)); self.aligned_label(16, LabelValue::I64(0x43e0000000000000));
let trap_label = self.trap_label();
dynasm!(self.asm dynasm!(self.asm
; comisd Rx(reg.rx().unwrap()), [=>u64_trunc_f64_const.0] ; comisd Rx(reg.rx().unwrap()), [=>u64_trunc_f64_const.0]
; jnb >large ; jnb >large
; jp =>trap_label.0
; cvttsd2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttsd2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; jmp >cont ; cmp Rq(temp.rq().unwrap()), 0
; jge >cont
; jmp =>trap_label.0
; large: ; large:
; subsd Rx(reg.rx().unwrap()), [=>u64_trunc_f64_const.0] ; subsd Rx(reg.rx().unwrap()), [=>u64_trunc_f64_const.0]
; cvttsd2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap()) ; cvttsd2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap())
; btc Rq(temp.rq().unwrap()), 0b00111111 ; cmp Rq(temp.rq().unwrap()), 0
; jnge =>trap_label.0
; add Rq(temp.rq().unwrap()), [=>sign_mask.0]
; cont: ; cont:
); );
@@ -3435,6 +3507,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
; test Rq(reg.rq().unwrap()), Rq(reg.rq().unwrap()) ; test Rq(reg.rq().unwrap()), Rq(reg.rq().unwrap())
; js >negative ; js >negative
; cvtsi2ss Rx(out.rx().unwrap()), Rq(reg.rq().unwrap()) ; cvtsi2ss Rx(out.rx().unwrap()), Rq(reg.rq().unwrap())
; jmp >ret
; negative: ; negative:
; mov Rq(temp.rq().unwrap()), Rq(reg.rq().unwrap()) ; mov Rq(temp.rq().unwrap()), Rq(reg.rq().unwrap())
; shr Rq(temp.rq().unwrap()), 1 ; shr Rq(temp.rq().unwrap()), 1
@@ -3442,6 +3515,7 @@ impl<'this, M: ModuleContext> Context<'this, M> {
; or Rq(reg.rq().unwrap()), Rq(temp.rq().unwrap()) ; or Rq(reg.rq().unwrap()), Rq(temp.rq().unwrap())
; cvtsi2ss Rx(out.rx().unwrap()), Rq(reg.rq().unwrap()) ; cvtsi2ss Rx(out.rx().unwrap()), Rq(reg.rq().unwrap())
; addss Rx(out.rx().unwrap()), Rx(out.rx().unwrap()) ; addss Rx(out.rx().unwrap()), Rx(out.rx().unwrap())
; ret:
); );
self.free_value(ValueLocation::Reg(temp)); self.free_value(ValueLocation::Reg(temp));
@@ -3466,27 +3540,22 @@ impl<'this, M: ModuleContext> Context<'this, M> {
let reg = self.into_reg(I64, val); let reg = self.into_reg(I64, val);
val = ValueLocation::Reg(reg); val = ValueLocation::Reg(reg);
let out = self.block_state.regs.take(F64); let out = self.block_state.regs.take(F32);
let temp = self.block_state.regs.take(F64); let temp = self.block_state.regs.take(I64);
let conv_const_0 = self.aligned_label(
16,
(LabelValue::I32(0x43300000), LabelValue::I32(0x43300000)),
);
let conv_const_1 = self.aligned_label(
16,
(
LabelValue::I64(0x4330000000000000),
LabelValue::I64(0x4530000000000000),
),
);
dynasm!(self.asm dynasm!(self.asm
; movq Rx(temp.rx().unwrap()), rdi ; test Rq(reg.rq().unwrap()), Rq(reg.rq().unwrap())
; punpckldq Rx(temp.rx().unwrap()), [=>conv_const_0.0] ; js >negative
; subpd Rx(temp.rx().unwrap()), [=>conv_const_1.0] ; cvtsi2sd Rx(out.rx().unwrap()), Rq(reg.rq().unwrap())
; pshufd Rx(out.rx().unwrap()), Rx(temp.rx().unwrap()), 78 ; jmp >ret
; addpd Rx(out.rx().unwrap()), Rx(temp.rx().unwrap()) ; negative:
; mov Rq(temp.rq().unwrap()), Rq(reg.rq().unwrap())
; shr Rq(temp.rq().unwrap()), 1
; and Rq(reg.rq().unwrap()), 1
; or Rq(reg.rq().unwrap()), Rq(temp.rq().unwrap())
; cvtsi2sd Rx(out.rx().unwrap()), Rq(reg.rq().unwrap())
; addsd Rx(out.rx().unwrap()), Rx(out.rx().unwrap())
; ret:
); );
self.free_value(ValueLocation::Reg(temp)); self.free_value(ValueLocation::Reg(temp));