@@ -111,18 +111,67 @@ __contract__(ensures(return_value == b))
111111}
112112#endif /* MLD_USE_ASM_VALUE_BARRIER */
113113
114-
115- /*
116- * The mld_ct_sel_int32 function below makes deliberate use of unsigned
117- * to signed integer conversion, which is implementation-defined
118- * behaviour. Here, we assume that uint16_t -> int16_t is inverse
119- * to int16_t -> uint16_t.
120- */
121114#ifdef CBMC
122115#pragma CPROVER check push
123116#pragma CPROVER check disable "conversion"
124117#endif
125118
119+ /*************************************************
120+ * Name: mld_cast_uint32_to_int32
121+ *
122+ * Description: Cast uint32 value to int32
123+ *
124+ * Returns: For uint32_t x, the unique y in int32_t
125+ * so that x == y mod 2^32.
126+ *
127+ * Concretely:
128+ * - x < 2^31: returns x
129+ * - x >= 2^31: returns x - 2^31
130+ *
131+ **************************************************/
132+ static MLD_ALWAYS_INLINE int32_t mld_cast_uint32_to_int32 (uint32_t x )
133+ {
134+ /*
135+ * PORTABILITY: This relies on uint32_t -> int32_t
136+ * being implemented as the inverse of int32_t -> uint32_t,
137+ * which is implementation-defined (C99 6.3.1.3 (3))
138+ * CBMC (correctly) fails to prove this conversion is OK,
139+ * so we have to suppress that check here
140+ */
141+ return (int32_t )x ;
142+ }
143+
144+ #ifdef CBMC
145+ #pragma CPROVER check pop
146+ #endif
147+
148+
149+ /*************************************************
150+ * Name: mld_cast_int64_to_uint32
151+ *
152+ * Description: Cast int64 value to uint32 as per C standard.
153+ *
154+ * Returns: For int64_t x, the unique y in uint32_t
155+ * so that x == y mod 2^32.
156+ **************************************************/
157+ static MLD_ALWAYS_INLINE uint32_t mld_cast_int64_to_uint32 (int64_t x )
158+ {
159+ return (uint32_t )(x & (int64_t )UINT32_MAX );
160+ }
161+
162+ /*************************************************
163+ * Name: mld_cast_int32_to_uint32
164+ *
165+ * Description: Cast int32 value to uint32 as per C standard.
166+ *
167+ * Returns: For int32_t x, the unique y in uint32_t
168+ * so that x == y mod 2^32.
169+ **************************************************/
170+ static MLD_ALWAYS_INLINE uint32_t mld_cast_int32_to_uint32 (int32_t x )
171+ {
172+ return mld_cast_int64_to_uint32 ((int64_t )x );
173+ }
174+
126175/*************************************************
127176 * Name: mld_ct_sel_int32
128177 *
@@ -137,35 +186,17 @@ __contract__(ensures(return_value == b))
137186 *
138187 **************************************************/
139188static MLD_INLINE int32_t mld_ct_sel_int32 (int32_t a , int32_t b , uint32_t cond )
140- /* TODO: proof */
141189__contract__ (
142190 requires (cond == 0x0 || cond == 0xFFFFFFFF )
143191 ensures (return_value == (cond ? a : b ))
144192)
145193{
146- uint32_t au = a , bu = b ;
194+ uint32_t au = mld_cast_int32_to_uint32 (a );
195+ uint32_t bu = mld_cast_int32_to_uint32 (b );
147196 uint32_t res = bu ^ (mld_value_barrier_u32 (cond ) & (au ^ bu ));
148- return ( int32_t ) res ;
197+ return mld_cast_uint32_to_int32 ( res ) ;
149198}
150199
151- /* Put unsigned-to-signed warnings in CBMC back into scope */
152- #ifdef CBMC
153- #pragma CPROVER check pop
154- #endif
155-
156-
157-
158- /*
159- * The mld_ct_cmask_neg_i32 function below makes deliberate use of
160- * signed to unsigned integer conversion, which is fully defined
161- * behaviour in C. It is thus safe to disable this warning.
162- */
163- #ifdef CBMC
164- #pragma CPROVER check push
165- #pragma CPROVER check disable "conversion"
166- #endif
167-
168-
169200/*************************************************
170201 * Name: mld_ct_cmask_neg_i32
171202 *
@@ -174,22 +205,16 @@ __contract__(
174205 * Arguments: int32_t x: Value to be converted into a mask
175206 *
176207 **************************************************/
177- /* TODO: proof */
178208static MLD_INLINE uint32_t mld_ct_cmask_neg_i32 (int32_t x )
179209__contract__ (
180210 ensures (return_value == ((x < 0 ) ? 0xFFFFFFFF : 0 ))
181211)
182212{
183213 int64_t tmp = mld_value_barrier_i64 ((int64_t )x );
184214 tmp >>= 31 ;
185- return ( uint32_t ) tmp ;
215+ return mld_cast_int64_to_uint32 ( tmp ) ;
186216}
187217
188- /* Put signed-to-unsigned warnings in CBMC back into scope */
189- #ifdef CBMC
190- #pragma CPROVER check pop
191- #endif
192-
193218/*************************************************
194219 * Name: mld_ct_abs_i32
195220 *
@@ -198,7 +223,6 @@ __contract__(
198223 * Arguments: int32_t x: Input value
199224 *
200225 **************************************************/
201- /* TODO: proof */
202226static MLD_INLINE int32_t mld_ct_abs_i32 (int32_t x )
203227__contract__ (
204228 requires (x >= - INT32_MAX )
0 commit comments