wasm_interp: float rounding ops

This commit is contained in:
Brian Carroll 2022-11-29 08:43:56 +00:00
parent 714586fac1
commit 17810d5134
No known key found for this signature in database
GPG key ID: 5C7B2EC4101703C0
3 changed files with 148 additions and 10 deletions

View file

@ -1051,11 +1051,42 @@ impl<'a> Instance<'a> {
let arg = self.value_stack.pop_f32();
self.value_stack.push(Value::F32(-arg));
}
F32CEIL => todo!("{:?} @ {:#x}", op_code, file_offset),
F32FLOOR => todo!("{:?} @ {:#x}", op_code, file_offset),
F32TRUNC => todo!("{:?} @ {:#x}", op_code, file_offset),
F32NEAREST => todo!("{:?} @ {:#x}", op_code, file_offset),
F32SQRT => todo!("{:?} @ {:#x}", op_code, file_offset),
F32CEIL => {
let arg = self.value_stack.pop_f32();
self.value_stack.push(Value::F32(arg.ceil()));
}
F32FLOOR => {
let arg = self.value_stack.pop_f32();
self.value_stack.push(Value::F32(arg.floor()));
}
F32TRUNC => {
let arg = self.value_stack.pop_f32();
self.value_stack.push(Value::F32(arg.trunc()));
}
F32NEAREST => {
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fnearest
let arg = self.value_stack.pop_f32();
let rounded = arg.round(); // "Rounds half-way cases away from 0.0"
let frac = arg - rounded;
let result = if frac == 0.5 || frac == -0.5 {
let rounded_half = rounded / 2.0;
let is_rounded_even = rounded_half.trunc() == rounded_half;
if is_rounded_even {
rounded
} else if rounded < arg {
rounded + 1.0
} else {
rounded - 1.0
}
} else {
rounded
};
self.value_stack.push(Value::F32(result));
}
F32SQRT => {
let arg = self.value_stack.pop_f32();
self.value_stack.push(Value::F32(arg.sqrt()));
}
F32ADD => {
let arg2 = self.value_stack.pop_f32();
let arg1 = self.value_stack.pop_f32();
@ -1088,11 +1119,42 @@ impl<'a> Instance<'a> {
let arg = self.value_stack.pop_f64();
self.value_stack.push(Value::F64(-arg));
}
F64CEIL => todo!("{:?} @ {:#x}", op_code, file_offset),
F64FLOOR => todo!("{:?} @ {:#x}", op_code, file_offset),
F64TRUNC => todo!("{:?} @ {:#x}", op_code, file_offset),
F64NEAREST => todo!("{:?} @ {:#x}", op_code, file_offset),
F64SQRT => todo!("{:?} @ {:#x}", op_code, file_offset),
F64CEIL => {
let arg = self.value_stack.pop_f64();
self.value_stack.push(Value::F64(arg.ceil()));
}
F64FLOOR => {
let arg = self.value_stack.pop_f64();
self.value_stack.push(Value::F64(arg.floor()));
}
F64TRUNC => {
let arg = self.value_stack.pop_f64();
self.value_stack.push(Value::F64(arg.trunc()));
}
F64NEAREST => {
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fnearest
let arg = self.value_stack.pop_f64();
let rounded = arg.round(); // "Rounds half-way cases away from 0.0"
let frac = arg - rounded;
let result = if frac == 0.5 || frac == -0.5 {
let rounded_half = rounded / 2.0;
let is_rounded_even = rounded_half.trunc() == rounded_half;
if is_rounded_even {
rounded
} else if rounded < arg {
rounded + 1.0
} else {
rounded - 1.0
}
} else {
rounded
};
self.value_stack.push(Value::F64(result));
}
F64SQRT => {
let arg = self.value_stack.pop_f64();
self.value_stack.push(Value::F64(arg.sqrt()));
}
F64ADD => {
let arg2 = self.value_stack.pop_f64();
let arg1 = self.value_stack.pop_f64();