about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTobias Decking <Tobias.Decking@gmail.com>2024-06-21 17:55:22 +0200
committerTobias Decking <Tobias.Decking@gmail.com>2024-06-21 17:55:22 +0200
commited83f1acced66941bfc58ce4e884d46d9e96bf64 (patch)
tree1447e0a490a284494e469841c6e506e4a5e70751
parent9afd75259155bdfb0ca707bf5ac6ea5faf50812f (diff)
downloadrust-ed83f1acced66941bfc58ce4e884d46d9e96bf64.tar.gz
rust-ed83f1acced66941bfc58ce4e884d46d9e96bf64.zip
Move out addition logic
-rw-r--r--src/tools/miri/src/shims/x86/mod.rs68
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())))
 }