@@ -45,25 +45,17 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
45
45
return Ok ( EmulateItemResult :: NotSupported ) ;
46
46
}
47
47
48
+ let [ cb_in, a, b] = this. check_shim ( abi, Abi :: Unadjusted , link_name, args) ?;
49
+
48
50
let op = if unprefixed_name. starts_with ( "add" ) {
49
51
mir:: BinOp :: AddWithOverflow
50
52
} else {
51
53
mir:: BinOp :: SubWithOverflow
52
54
} ;
53
55
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 ) ?) ?;
67
59
}
68
60
69
61
// 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> {
77
69
}
78
70
79
71
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 ( ) ?;
94
72
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 ) ?) ?;
97
76
}
98
77
99
78
// Used to implement the `_mm_pause` function.
@@ -1369,15 +1348,26 @@ fn psign<'tcx>(
1369
1348
Ok ( ( ) )
1370
1349
}
1371
1350
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 > (
1374
1355
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 ( ) ) ) )
1383
1373
}
0 commit comments