14
14
#include " std_types.h"
15
15
#include " std_expr.h"
16
16
17
+ #include < algorithm>
18
+
17
19
bool to_integer (const exprt &expr, mp_integer &int_value)
18
20
{
19
21
if (!expr.is_constant ())
@@ -285,11 +287,33 @@ bool get_bvrep_bit(
285
287
std::size_t width,
286
288
std::size_t bit_index)
287
289
{
288
- // The representation is binary, using '0'/'1',
289
- // most significant bit first.
290
290
PRECONDITION (bit_index < width);
291
- PRECONDITION (src.size () == width);
292
- return src[src.size () - 1 - bit_index] == ' 1' ;
291
+
292
+ // The representation is hex, most significant nibble first.
293
+ const auto nibble_index = bit_index >> 2 ;
294
+
295
+ if (nibble_index >= src.size ())
296
+ return false ;
297
+
298
+ char nibble = src[src.size () - 1 - nibble_index];
299
+
300
+ DATA_INVARIANT (isxdigit (nibble), " " );
301
+
302
+ unsigned nibble_value =
303
+ isdigit (nibble) ? nibble - ' 0'
304
+ : islower (nibble) ? nibble - ' a' + 10 : nibble - ' A' + 10 ;
305
+
306
+ return ((nibble_value >> (bit_index & 3 )) & 1 ) != 0 ;
307
+ }
308
+
309
+ static char nibble2hex (unsigned nibble)
310
+ {
311
+ PRECONDITION (nibble <= 0xf );
312
+
313
+ if (nibble >= 10 )
314
+ return ' A' + nibble - 10 ;
315
+ else
316
+ return ' 0' + nibble;
293
317
}
294
318
295
319
// / construct a bit-vector representation from a functor
@@ -299,12 +323,36 @@ bool get_bvrep_bit(
299
323
irep_idt
300
324
make_bvrep (const std::size_t width, const std::function<bool (std::size_t )> f)
301
325
{
302
- std::string result (width, ' ' );
326
+ std::string result;
327
+ result.reserve (width / 4 + 1 );
328
+ unsigned nibble = 0 ;
303
329
304
330
for (std::size_t i = 0 ; i < width; i++)
305
- result[width - 1 - i] = f (i) ? ' 1' : ' 0' ;
331
+ {
332
+ const auto bit_in_nibble = i % 4 ;
306
333
307
- return result;
334
+ nibble |= ((unsigned )f (i)) << bit_in_nibble;
335
+
336
+ if (bit_in_nibble == 3 )
337
+ {
338
+ result += nibble2hex (nibble);
339
+ nibble = 0 ;
340
+ }
341
+ }
342
+
343
+ if (nibble != 0 )
344
+ result += nibble2hex (nibble);
345
+
346
+ // drop leading zeros
347
+ while (!result.empty () && result.back () == ' 0' )
348
+ result.resize (result.size () - 1 );
349
+
350
+ std::reverse (result.begin (), result.end ());
351
+
352
+ if (result.empty ())
353
+ return ID_0;
354
+ else
355
+ return result;
308
356
}
309
357
310
358
// / perform a binary bit-wise operation, given as a functor,
@@ -342,14 +390,50 @@ irep_idt bvrep_bitwise_op(
342
390
}
343
391
344
392
// / convert an integer to bit-vector representation with given width
393
+ // / This uses two's complement for negative numbers.
394
+ // / If the value is out of range, it is 'wrapped around'.
345
395
irep_idt integer2bvrep (const mp_integer &src, std::size_t width)
346
396
{
347
- return integer2binary (src, width);
397
+ const mp_integer p = power (2 , width);
398
+
399
+ if (src.is_negative ())
400
+ {
401
+ // do two's complement encoding of negative numbers
402
+ mp_integer tmp = src;
403
+ tmp.negate ();
404
+ tmp %= p;
405
+ if (tmp != 0 )
406
+ tmp = p - tmp;
407
+ return integer2string (tmp, 16 );
408
+ }
409
+ else
410
+ {
411
+ // we 'wrap around' if 'src' is too large
412
+ return integer2string (src % p, 16 );
413
+ }
348
414
}
349
415
350
416
// / convert a bit-vector representation (possibly signed) to integer
351
417
mp_integer bvrep2integer (const irep_idt &src, std::size_t width, bool is_signed)
352
418
{
353
- PRECONDITION (src.size () == width);
354
- return binary2integer (id2string (src), is_signed);
419
+ if (is_signed)
420
+ {
421
+ PRECONDITION (width >= 1 );
422
+ const auto tmp = string2integer (id2string (src), 16 );
423
+ const auto p = power (2 , width - 1 );
424
+ if (tmp >= p)
425
+ {
426
+ const auto result = tmp - 2 * p;
427
+ PRECONDITION (result >= -p);
428
+ return result;
429
+ }
430
+ else
431
+ return tmp;
432
+ }
433
+ else
434
+ {
435
+ const auto result = string2integer (id2string (src), 16 );
436
+ PRECONDITION (result < power (2 , width));
437
+ return result;
438
+ }
355
439
}
0 commit comments