@@ -45,25 +45,17 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
4545 return Ok ( EmulateItemResult :: NotSupported ) ;
4646 }
4747
48+ let [ cb_in, a, b] = this. check_shim ( abi, Abi :: Unadjusted , link_name, args) ?;
49+
4850 let op = if unprefixed_name. starts_with ( "add" ) {
4951 mir:: BinOp :: AddWithOverflow
5052 } else {
5153 mir:: BinOp :: SubWithOverflow
5254 } ;
5355
54- let [ cb_in, a, b] = this. check_shim ( abi, Abi :: Unadjusted , link_name, args) ?;
55- let cb_in = this. read_scalar ( cb_in) ?. to_u8 ( ) ? != 0 ;
56- let a = this. read_immediate ( a) ?;
57- let b = this. read_immediate ( b) ?;
58-
59- let ( sum, overflow1) = this. binary_op ( op, & a, & b) ?. to_pair ( this) ;
60- let ( sum, overflow2) =
61- this. binary_op ( op, & sum, & ImmTy :: from_uint ( cb_in, a. layout ) ) ?. to_pair ( this) ;
62- let cb_out = overflow1. to_scalar ( ) . to_bool ( ) ? | overflow2. to_scalar ( ) . to_bool ( ) ?;
63-
64- let d1 = this. project_field ( dest, 0 ) ?;
65- let d2 = this. project_field ( dest, 1 ) ?;
66- write_twice ( this, & d1, Scalar :: from_u8 ( cb_out. into ( ) ) , & d2, sum) ?;
56+ let ( sum, cb_out) = carrying_add ( this, cb_in, a, b, op) ?;
57+ this. write_scalar ( cb_out, & this. project_field ( dest, 0 ) ?) ?;
58+ this. write_immediate ( * sum, & this. project_field ( dest, 1 ) ?) ?;
6759 }
6860
6961 // 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> {
7769 }
7870
7971 let [ c_in, a, b, out] = this. check_shim ( abi, Abi :: Unadjusted , link_name, args) ?;
80- let c_in = this. read_scalar ( c_in) ?. to_u8 ( ) ? != 0 ;
81- let a = this. read_immediate ( a) ?;
82- let b = this. read_immediate ( b) ?;
83-
84- let ( sum, overflow1) =
85- this. binary_op ( mir:: BinOp :: AddWithOverflow , & a, & b) ?. to_pair ( this) ;
86- let ( sum, overflow2) = this
87- . binary_op (
88- mir:: BinOp :: AddWithOverflow ,
89- & sum,
90- & ImmTy :: from_uint ( c_in, a. layout ) ,
91- ) ?
92- . to_pair ( this) ;
93- let c_out = overflow1. to_scalar ( ) . to_bool ( ) ? | overflow2. to_scalar ( ) . to_bool ( ) ?;
9472
95- let out = this. deref_pointer_as ( out, sum. layout ) ?;
96- write_twice ( this, dest, Scalar :: from_u8 ( c_out. into ( ) ) , & out, sum) ?;
73+ let ( sum, c_out) = carrying_add ( this, c_in, a, b, mir:: BinOp :: AddWithOverflow ) ?;
74+ this. write_scalar ( c_out, dest) ?;
75+ this. write_immediate ( * sum, & this. deref_pointer_as ( out, sum. layout ) ?) ?;
9776 }
9877
9978 // Used to implement the `_mm_pause` function.
@@ -1369,15 +1348,26 @@ fn psign<'tcx>(
13691348 Ok ( ( ) )
13701349}
13711350
1372- /// Write two values `v1` and `v2` to the places `d1` and `d2`.
1373- fn write_twice < ' tcx > (
1351+ /// Calcultates either `a + b + cb_in` or `a - b - cb_in` depending on the value
1352+ /// of `op` and returns both the sum and the overflow bit. `op` is expected to be
1353+ /// either one of `mir::BinOp::AddWithOverflow` and `mir::BinOp::SubWithOverflow`.
1354+ fn carrying_add < ' tcx > (
13741355 this : & mut crate :: MiriInterpCx < ' tcx > ,
1375- d1 : & MPlaceTy < ' tcx > ,
1376- v1 : Scalar ,
1377- d2 : & MPlaceTy < ' tcx > ,
1378- v2 : ImmTy < ' tcx > ,
1379- ) -> InterpResult < ' tcx , ( ) > {
1380- this. write_scalar ( v1, d1) ?;
1381- this. write_immediate ( * v2, d2) ?;
1382- Ok ( ( ) )
1356+ cb_in : & OpTy < ' tcx > ,
1357+ a : & OpTy < ' tcx > ,
1358+ b : & OpTy < ' tcx > ,
1359+ op : mir:: BinOp ,
1360+ ) -> InterpResult < ' tcx , ( ImmTy < ' tcx > , Scalar ) > {
1361+ assert ! ( op == mir:: BinOp :: AddWithOverflow || op == mir:: BinOp :: SubWithOverflow ) ;
1362+
1363+ let cb_in = this. read_scalar ( cb_in) ?. to_u8 ( ) ? != 0 ;
1364+ let a = this. read_immediate ( a) ?;
1365+ let b = this. read_immediate ( b) ?;
1366+
1367+ let ( sum, overflow1) = this. binary_op ( op, & a, & b) ?. to_pair ( this) ;
1368+ let ( sum, overflow2) =
1369+ this. binary_op ( op, & sum, & ImmTy :: from_uint ( cb_in, a. layout ) ) ?. to_pair ( this) ;
1370+ let cb_out = overflow1. to_scalar ( ) . to_bool ( ) ? | overflow2. to_scalar ( ) . to_bool ( ) ?;
1371+
1372+ Ok ( ( sum, Scalar :: from_u8 ( cb_out. into ( ) ) ) )
13831373}
0 commit comments