diff options
| author | Tobias Decking <Tobias.Decking@gmail.com> | 2024-06-21 17:55:22 +0200 |
|---|---|---|
| committer | Tobias Decking <Tobias.Decking@gmail.com> | 2024-06-21 17:55:22 +0200 |
| commit | ed83f1acced66941bfc58ce4e884d46d9e96bf64 (patch) | |
| tree | 1447e0a490a284494e469841c6e506e4a5e70751 | |
| parent | 9afd75259155bdfb0ca707bf5ac6ea5faf50812f (diff) | |
| download | rust-ed83f1acced66941bfc58ce4e884d46d9e96bf64.tar.gz rust-ed83f1acced66941bfc58ce4e884d46d9e96bf64.zip | |
Move out addition logic
| -rw-r--r-- | src/tools/miri/src/shims/x86/mod.rs | 68 |
1 files changed, 29 insertions, 39 deletions
diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 74470fad352..7bccf71f043 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -45,25 +45,17 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return Ok(EmulateItemResult::NotSupported); } + let [cb_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; + let op = if unprefixed_name.starts_with("add") { mir::BinOp::AddWithOverflow } else { mir::BinOp::SubWithOverflow }; - let [cb_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; - let cb_in = this.read_scalar(cb_in)?.to_u8()? != 0; - let a = this.read_immediate(a)?; - let b = this.read_immediate(b)?; - - let (sum, overflow1) = this.binary_op(op, &a, &b)?.to_pair(this); - let (sum, overflow2) = - this.binary_op(op, &sum, &ImmTy::from_uint(cb_in, a.layout))?.to_pair(this); - let cb_out = overflow1.to_scalar().to_bool()? | overflow2.to_scalar().to_bool()?; - - let d1 = this.project_field(dest, 0)?; - let d2 = this.project_field(dest, 1)?; - write_twice(this, &d1, Scalar::from_u8(cb_out.into()), &d2, sum)?; + let (sum, cb_out) = carrying_add(this, cb_in, a, b, op)?; + this.write_scalar(cb_out, &this.project_field(dest, 0)?)?; + this.write_immediate(*sum, &this.project_field(dest, 1)?)?; } // Used to implement the `_addcarryx_u{32, 64}` functions. They are semantically identical with the `_addcarry_u{32, 64}` functions, @@ -77,23 +69,10 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let [c_in, a, b, out] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; - let c_in = this.read_scalar(c_in)?.to_u8()? != 0; - let a = this.read_immediate(a)?; - let b = this.read_immediate(b)?; - - let (sum, overflow1) = - this.binary_op(mir::BinOp::AddWithOverflow, &a, &b)?.to_pair(this); - let (sum, overflow2) = this - .binary_op( - mir::BinOp::AddWithOverflow, - &sum, - &ImmTy::from_uint(c_in, a.layout), - )? - .to_pair(this); - let c_out = overflow1.to_scalar().to_bool()? | overflow2.to_scalar().to_bool()?; - let out = this.deref_pointer_as(out, sum.layout)?; - write_twice(this, dest, Scalar::from_u8(c_out.into()), &out, sum)?; + let (sum, c_out) = carrying_add(this, c_in, a, b, mir::BinOp::AddWithOverflow)?; + this.write_scalar(c_out, dest)?; + this.write_immediate(*sum, &this.deref_pointer_as(out, sum.layout)?)?; } // Used to implement the `_mm_pause` function. @@ -1369,15 +1348,26 @@ fn psign<'tcx>( Ok(()) } -/// Write two values `v1` and `v2` to the places `d1` and `d2`. -fn write_twice<'tcx>( +/// Calcultates either `a + b + cb_in` or `a - b - cb_in` depending on the value +/// of `op` and returns both the sum and the overflow bit. `op` is expected to be +/// either one of `mir::BinOp::AddWithOverflow` and `mir::BinOp::SubWithOverflow`. +fn carrying_add<'tcx>( this: &mut crate::MiriInterpCx<'tcx>, - d1: &MPlaceTy<'tcx>, - v1: Scalar, - d2: &MPlaceTy<'tcx>, - v2: ImmTy<'tcx>, -) -> InterpResult<'tcx, ()> { - this.write_scalar(v1, d1)?; - this.write_immediate(*v2, d2)?; - Ok(()) + cb_in: &OpTy<'tcx>, + a: &OpTy<'tcx>, + b: &OpTy<'tcx>, + op: mir::BinOp, +) -> InterpResult<'tcx, (ImmTy<'tcx>, Scalar)> { + assert!(op == mir::BinOp::AddWithOverflow || op == mir::BinOp::SubWithOverflow); + + let cb_in = this.read_scalar(cb_in)?.to_u8()? != 0; + let a = this.read_immediate(a)?; + let b = this.read_immediate(b)?; + + let (sum, overflow1) = this.binary_op(op, &a, &b)?.to_pair(this); + let (sum, overflow2) = + this.binary_op(op, &sum, &ImmTy::from_uint(cb_in, a.layout))?.to_pair(this); + let cb_out = overflow1.to_scalar().to_bool()? | overflow2.to_scalar().to_bool()?; + + Ok((sum, Scalar::from_u8(cb_out.into()))) } |
