Fix conversions trapping and fix some weirdness around conditional jumps
This commit is contained in:
38
README.md
38
README.md
@@ -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
|
||||||
|
|||||||
223
src/backend.rs
223
src/backend.rs
@@ -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,9 +2458,6 @@ 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 {
|
|
||||||
self.zero_reg(reg);
|
|
||||||
} else {
|
|
||||||
match reg {
|
match reg {
|
||||||
GPR::Rq(r) => {
|
GPR::Rq(r) => {
|
||||||
let val = val.as_bytes();
|
let val = val.as_bytes();
|
||||||
@@ -2478,7 +2481,6 @@ impl<'this, M: ModuleContext> Context<'this, M> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// The `&` and `&mut` aren't necessary (`ValueLocation` is copy) but it ensures that we don't get
|
// The `&` and `&mut` aren't necessary (`ValueLocation` is copy) but it ensures that we don't get
|
||||||
// the arguments the wrong way around. In the future we want to have a `ReadLocation` and `WriteLocation`
|
// the arguments the wrong way around. In the future we want to have a `ReadLocation` and `WriteLocation`
|
||||||
@@ -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,31 +3269,85 @@ 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);
|
||||||
|
|
||||||
|
let sign_mask = self.aligned_label(16, LabelValue::I64(SIGN_MASK_F64 as i64));
|
||||||
|
let float_cmp_mask = self.aligned_label(16, LabelValue::I32(0xdf000000u32 as i32));
|
||||||
|
let zero = self.aligned_label(16, LabelValue::I64(0));
|
||||||
|
let trap_label = self.trap_label();
|
||||||
|
|
||||||
|
dynasm!(self.asm
|
||||||
|
; cvttss2si Rq(temp.rq().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; cmp Rq(temp.rq().unwrap()), [=>sign_mask.0]
|
||||||
|
; jne >ret
|
||||||
|
; ucomiss Rx(reg.rx().unwrap()), Rx(reg.rx().unwrap())
|
||||||
|
; 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:
|
||||||
);
|
);
|
||||||
conversion!(
|
|
||||||
i64_truncate_f64_s,
|
ValueLocation::Reg(temp)
|
||||||
cvttsd2si,
|
}
|
||||||
Rx,
|
};
|
||||||
rx,
|
|
||||||
Rq,
|
self.free_value(val);
|
||||||
rq,
|
|
||||||
f64,
|
self.push(out_val);
|
||||||
i64,
|
}
|
||||||
as_f64,
|
|
||||||
|a: wasmparser::Ieee64| f64::from_bits(a.bits()) as i64
|
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));
|
||||||
|
|||||||
Reference in New Issue
Block a user