strcalc.c 33.9 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Michael Beck's avatar
Michael Beck committed
6
7
/**
 * @file
8
9
 * @brief    Provides basic mathematical operations on values represented as
 *           strings.
Michael Beck's avatar
Michael Beck committed
10
11
 * @date     2003
 * @author   Mathias Heil
12
 */
13
#include <stdlib.h>
14
15
16
17
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <limits.h>
18

Michael Beck's avatar
Michael Beck committed
19
#include "strcalc.h"
Michael Beck's avatar
Michael Beck committed
20
#include "xmalloc.h"
21
#include "error.h"
Michael Beck's avatar
Michael Beck committed
22

23
24
25
26
#define SC_BITS      4
#define SC_RESULT(x) ((x) & ((1U << SC_BITS) - 1U))
#define SC_CARRY(x)  ((unsigned)(x) >> SC_BITS)

Michael Beck's avatar
Michael Beck committed
27
#define CLEAR_BUFFER(b) assert(b); memset(b, SC_0, calc_buffer_size)
28
#define SHIFT(count) (SC_1 << (count))
29
30
#define _val(a) ((a)-SC_0)
#define _digit(a) ((a)+SC_0)
31
#define _bitisset(digit, pos) (((digit) & SHIFT(pos)) != SC_0)
32

Matthias Heil's avatar
Matthias Heil committed
33
34
static char *calc_buffer = NULL;    /* buffer holding all results */
static char *output_buffer = NULL;  /* buffer for output */
Michael Beck's avatar
Michael Beck committed
35
36
37
static int bit_pattern_size;        /* maximum number of bits */
static int calc_buffer_size;        /* size of internally stored values */
static int max_value_size;          /* maximum size of values */
38

Matthias Braun's avatar
Matthias Braun committed
39
static bool carry_flag;             /**< some computation set the carry_flag:
Michael Beck's avatar
Michael Beck committed
40
                                         - right shift if bits were lost due to shifting
Michael Beck's avatar
Michael Beck committed
41
                                         - division if there was a remainder
Michael Beck's avatar
Michael Beck committed
42
43
                                         However, the meaning of carry is machine dependent
                                         and often defined in other ways! */
44

45
static const char sex_digit[4] = { SC_E, SC_C, SC_8, SC_0 };
46
static const char zex_digit[4] = { SC_1, SC_3, SC_7, SC_F };
47
48
static const char max_digit[4] = { SC_0, SC_1, SC_3, SC_7 };
static const char min_digit[4] = { SC_F, SC_E, SC_C, SC_8 };
49

50
static char const shrs_table[16][4][2] = {
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
                       { {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0}, {SC_0, SC_0} },
                       { {SC_1, SC_0}, {SC_0, SC_8}, {SC_0, SC_4}, {SC_0, SC_2} },
                       { {SC_2, SC_0}, {SC_1, SC_0}, {SC_0, SC_8}, {SC_0, SC_4} },
                       { {SC_3, SC_0}, {SC_1, SC_8}, {SC_0, SC_C}, {SC_0, SC_6} },
                       { {SC_4, SC_0}, {SC_2, SC_0}, {SC_1, SC_0}, {SC_0, SC_8} },
                       { {SC_5, SC_0}, {SC_2, SC_8}, {SC_1, SC_4}, {SC_0, SC_A} },
                       { {SC_6, SC_0}, {SC_3, SC_0}, {SC_1, SC_8}, {SC_0, SC_C} },
                       { {SC_7, SC_0}, {SC_3, SC_8}, {SC_1, SC_C}, {SC_0, SC_E} },
                       { {SC_8, SC_0}, {SC_4, SC_0}, {SC_2, SC_0}, {SC_1, SC_0} },
                       { {SC_9, SC_0}, {SC_4, SC_8}, {SC_2, SC_4}, {SC_1, SC_2} },
                       { {SC_A, SC_0}, {SC_5, SC_0}, {SC_2, SC_8}, {SC_1, SC_4} },
                       { {SC_B, SC_0}, {SC_5, SC_8}, {SC_2, SC_C}, {SC_1, SC_6} },
                       { {SC_C, SC_0}, {SC_6, SC_0}, {SC_3, SC_0}, {SC_1, SC_8} },
                       { {SC_D, SC_0}, {SC_6, SC_8}, {SC_3, SC_4}, {SC_1, SC_A} },
                       { {SC_E, SC_0}, {SC_7, SC_0}, {SC_3, SC_8}, {SC_1, SC_C} },
                       { {SC_F, SC_0}, {SC_7, SC_8}, {SC_3, SC_C}, {SC_1, SC_E} }
                                   };
68

Michael Beck's avatar
Michael Beck committed
69
/** converting a digit to a binary string */
70
static char const *const binary_table[] = {
71
72
	"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
	"1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
73
74
};

Michael Beck's avatar
Michael Beck committed
75
76
77
/**
 * implements the bitwise NOT operation
 */
78
79
static void do_bitnot(const char *val, char *buffer)
{
Matthias Braun's avatar
Matthias Braun committed
80
	for (int counter = 0; counter<calc_buffer_size; counter++)
81
		buffer[counter] = val[counter] ^ SC_F;
82
83
}

Michael Beck's avatar
Michael Beck committed
84
85
86
/**
 * implements the bitwise OR operation
 */
87
88
static void do_bitor(const char *val1, const char *val2, char *buffer)
{
Matthias Braun's avatar
Matthias Braun committed
89
	for (int counter = 0; counter<calc_buffer_size; counter++)
90
		buffer[counter] = val1[counter] | val2[counter];
91
92
}

Michael Beck's avatar
Michael Beck committed
93
94
95
/**
 * implements the bitwise eXclusive OR operation
 */
96
97
static void do_bitxor(const char *val1, const char *val2, char *buffer)
{
Matthias Braun's avatar
Matthias Braun committed
98
	for (int counter = 0; counter<calc_buffer_size; counter++)
99
		buffer[counter] = val1[counter] ^ val2[counter];
100
101
}

Michael Beck's avatar
Michael Beck committed
102
103
104
/**
 * implements the bitwise AND operation
 */
105
106
static void do_bitand(const char *val1, const char *val2, char *buffer)
{
Matthias Braun's avatar
Matthias Braun committed
107
	for (int counter = 0; counter<calc_buffer_size; counter++)
108
		buffer[counter] = val1[counter] & val2[counter];
109
110
}

111
112
113
114
115
/**
 * implements the bitwise AND not operation
 */
static void do_bitandnot(const char *val1, const char *val2, char *buffer)
{
Matthias Braun's avatar
Matthias Braun committed
116
	for (int counter = 0; counter < calc_buffer_size; ++counter)
117
118
119
		buffer[counter] = val1[counter] & (SC_F ^ val2[counter]);
}

Michael Beck's avatar
Michael Beck committed
120
121
122
/**
 * returns the sign bit.
 */
123
124
static int do_sign(const char *val)
{
125
	return (val[calc_buffer_size-1] <= SC_7) ? (1) : (-1);
126
127
}

Michael Beck's avatar
Michael Beck committed
128
/**
Michael Beck's avatar
Michael Beck committed
129
130
 * returns non-zero if bit at position pos is set
 */
131
132
static int do_bit(const char *val, int pos)
{
133
134
	int bit    = pos & 3;
	int nibble = pos >> 2;
Michael Beck's avatar
Michael Beck committed
135

136
	return _bitisset(val[nibble], bit);
Michael Beck's avatar
Michael Beck committed
137
138
}

Michael Beck's avatar
Michael Beck committed
139
140
141
/**
 * Implements a fast ADD + 1
 */
142
143
static void do_inc(const char *val, char *buffer)
{
144
145
146
147
148
149
150
151
	int counter = 0;

	while (counter++ < calc_buffer_size) {
		if (*val == SC_F) {
			*buffer++ = SC_0;
			val++;
		} else {
			/* No carry here, *val != SC_F */
152
			*buffer = *val + SC_1;
153
154
155
156
157
			return;
		}
	}
	/* here a carry could be lost, this is intended because this should
	 * happen only when a value changes sign. */
158
159
}

Michael Beck's avatar
Michael Beck committed
160
161
162
/**
 * Implements a unary MINUS
 */
163
164
static void do_negate(const char *val, char *buffer)
{
165
166
	do_bitnot(val, buffer);
	do_inc(buffer, buffer);
167
168
}

Michael Beck's avatar
Michael Beck committed
169
170
171
/**
 * Implements a binary ADD
 */
172
173
static void do_add(const char *val1, const char *val2, char *buffer)
{
174
175
176
177
178
	unsigned carry = SC_0;
	for (int counter = 0; counter < calc_buffer_size; ++counter) {
		unsigned const sum = val1[counter] + val2[counter] + carry;
		buffer[counter] = SC_RESULT(sum);
		carry           = SC_CARRY(sum);
179
180
	}
	carry_flag = carry != SC_0;
181
182
}

Michael Beck's avatar
Michael Beck committed
183
184
185
/**
 * Implements a binary SUB
 */
186
187
static void do_sub(const char *val1, const char *val2, char *buffer)
{
188
189
	/* intermediate buffer to hold -val2 */
	char *temp_buffer = ALLOCAN(char, calc_buffer_size);
Michael Beck's avatar
Michael Beck committed
190

191
192
	do_negate(val2, temp_buffer);
	do_add(val1, temp_buffer, buffer);
Michael Beck's avatar
Michael Beck committed
193
194
195
196
197
}

/**
 * Implements a binary MUL
 */
198
199
static void do_mul(const char *val1, const char *val2, char *buffer)
{
200
201
202
	char *temp_buffer = ALLOCAN(char, calc_buffer_size);
	char *neg_val1    = ALLOCAN(char, calc_buffer_size);
	char *neg_val2    = ALLOCAN(char, calc_buffer_size);
203

204
	/* init result buffer to zeros */
205
206
207
208
	memset(temp_buffer, SC_0, calc_buffer_size);

	/* the multiplication works only for positive values, for negative values *
	 * it is necessary to negate them and adjust the result accordingly       */
Matthias Braun's avatar
Matthias Braun committed
209
	char sign = 0;
210
211
	if (do_sign(val1) == -1) {
		do_negate(val1, neg_val1);
212
213
214
		val1 = neg_val1;
		sign ^= 1;
	}
215
216
	if (do_sign(val2) == -1) {
		do_negate(val2, neg_val2);
217
218
219
220
		val2 = neg_val2;
		sign ^= 1;
	}

Matthias Braun's avatar
Matthias Braun committed
221
	for (int c_outer = 0; c_outer < max_value_size; c_outer++) {
222
		if (val2[c_outer] != SC_0) {
223
			unsigned carry = SC_0; /* container for carries */
Matthias Braun's avatar
Matthias Braun committed
224
225
226
227
228
229
			for (int c_inner = 0; c_inner < max_value_size; c_inner++) {
				/* do the following calculation:
				 * Add the current carry, the value at position c_outer+c_inner
				 * and the result of the multiplication of val1[c_inner] and
				 * val2[c_outer]. This is the usual pen-and-paper multiplication
				 */
230
231

				/* multiplicate the two digits */
232
				unsigned const mul = val1[c_inner] * val2[c_outer];
233
				/* add old value to result of multiplication and the carry */
Matthias Braun's avatar
Matthias Braun committed
234
235
236
237
238
239
240
241
242
243
244
245
246
				unsigned const sum = temp_buffer[c_inner+c_outer] + mul + carry;

				/* all carries together result in new carry. This is always
				 * smaller than the base b:
				 * Both multiplicands, the carry and the value already in the
				 * temp buffer are single digits and their value is therefore
				 * at most equal to (b-1).
				 * This leads to:
				 * (b-1)(b-1)+(b-1)+(b-1) = b*b-1
				 * The tables list all operations rem b, so the carry is at
				 * most
				 * (b*b-1)rem b = -1rem b = b-1
				 */
247
248
				temp_buffer[c_inner + c_outer] = SC_RESULT(sum);
				carry                          = SC_CARRY(sum);
249
250
251
252
253
254
255
256
257
			}

			/* A carry may hang over */
			/* c_outer is always smaller than max_value_size! */
			temp_buffer[max_value_size + c_outer] = carry;
		}
	}

	if (sign)
258
		do_negate(temp_buffer, buffer);
259
260
	else
		memcpy(buffer, temp_buffer, calc_buffer_size);
261
262
}

Michael Beck's avatar
Michael Beck committed
263
264
265
/**
 * Shift the buffer to left and add a 4 bit digit
 */
266
267
static void do_push(const char digit, char *buffer)
{
Matthias Braun's avatar
Matthias Braun committed
268
	for (int counter = calc_buffer_size - 2; counter >= 0; counter--) {
269
270
271
		buffer[counter+1] = buffer[counter];
	}
	buffer[0] = digit;
272
273
}

Michael Beck's avatar
Michael Beck committed
274
275
276
277
278
/**
 * Implements truncating integer division and remainder.
 *
 * Note: This is MOST slow
 */
Matthias Braun's avatar
Matthias Braun committed
279
280
static void do_divmod(const char *rDividend, const char *divisor, char *quot,
                      char *rem)
281
{
282
283
284
285
286
	/* clear result buffer */
	memset(quot, SC_0, calc_buffer_size);
	memset(rem, SC_0, calc_buffer_size);

	/* if the divisor is zero this won't work (quot is zero) */
287
	assert(sc_comp(divisor, quot) != ir_relation_equal && "division by zero!");
288
289

	/* if the dividend is zero result is zero (quot is zero) */
Matthias Braun's avatar
Matthias Braun committed
290
	const char *dividend = rDividend;
291
	if (sc_comp(dividend, quot) == ir_relation_equal)
292
293
		return;

Matthias Braun's avatar
Matthias Braun committed
294
295
	char  div_sign = 0;
	char  rem_sign = 0;
296
	char *neg_val1 = ALLOCAN(char, calc_buffer_size);
297
298
	if (do_sign(dividend) == -1) {
		do_negate(dividend, neg_val1);
299
300
301
302
303
		div_sign ^= 1;
		rem_sign ^= 1;
		dividend = neg_val1;
	}

304
	char *neg_val2 = ALLOCAN(char, calc_buffer_size);
305
	do_negate(divisor, neg_val2);
Matthias Braun's avatar
Matthias Braun committed
306
	const char *minus_divisor;
307
	if (do_sign(divisor) == -1) {
308
309
310
		div_sign ^= 1;
		minus_divisor = divisor;
		divisor = neg_val2;
Matthias Braun's avatar
Matthias Braun committed
311
	} else {
312
		minus_divisor = neg_val2;
Matthias Braun's avatar
Matthias Braun committed
313
	}
314
315
316
317

	/* if divisor >= dividend division is easy
	 * (remember these are absolute values) */
	switch (sc_comp(dividend, divisor)) {
318
	case ir_relation_equal: /* dividend == divisor */
319
320
321
		quot[0] = SC_1;
		goto end;

322
	case ir_relation_less: /* dividend < divisor */
323
		memcpy(rem, dividend, calc_buffer_size);
324
325
326
327
328
329
		goto end;

	default: /* unluckily division is necessary :( */
		break;
	}

Matthias Braun's avatar
Matthias Braun committed
330
	for (int c_dividend = calc_buffer_size - 1; c_dividend >= 0; c_dividend--) {
331
332
		do_push(dividend[c_dividend], rem);
		do_push(SC_0, quot);
333

Matthias Braun's avatar
Matthias Braun committed
334
335
		if (sc_comp(rem, divisor) != ir_relation_less) {
			/* remainder >= divisor */
336
337
			/* subtract until the remainder becomes negative, this should
			 * be faster than comparing remainder with divisor  */
338
			do_add(rem, minus_divisor, rem);
339

340
			while (do_sign(rem) == 1) {
341
342
				/* TODO can this generate carry or is masking redundant? */
				quot[0] = SC_RESULT(quot[0] + SC_1);
343
				do_add(rem, minus_divisor, rem);
344
345
346
			}

			/* subtracted one too much */
347
			do_add(rem, divisor, rem);
348
349
350
351
		}
	}
end:
	/* sets carry if remainder is non-zero ??? */
Matthias Braun's avatar
Matthias Braun committed
352
	carry_flag = !sc_is_zero(rem, calc_buffer_size);
353
354

	if (div_sign)
355
		do_negate(quot, quot);
356
357

	if (rem_sign)
358
		do_negate(rem, rem);
359
360
}

Michael Beck's avatar
Michael Beck committed
361
362
363
364
/**
 * Implements a Shift Left, which can either preserve the sign bit
 * or not.
 */
Matthias Braun's avatar
Matthias Braun committed
365
static void do_shl(const char *val1, char *buffer, long shift_cnt, int bitsize,
366
                   bool is_signed)
367
{
368
369
	assert(shift_cnt >= 0);
	assert((do_sign(val1) != -1) || is_signed);
370
371

	/* if shifting far enough the result is zero */
372
	if (shift_cnt >= bitsize) {
373
374
375
376
		memset(buffer, SC_0, calc_buffer_size);
		return;
	}

377
	unsigned const shift = shift_cnt % SC_BITS;
378
	shift_cnt = shift_cnt / 4;
379
380
381

	/* shift the single digits some bytes (offset) and some bits (table)
	 * to the left */
382
	unsigned carry = SC_0;
Matthias Braun's avatar
Matthias Braun committed
383
	for (int counter = 0; counter < bitsize/4 - shift_cnt; counter++) {
384
385
386
		unsigned const shl = val1[counter] << shift | carry;
		buffer[counter + shift_cnt] = SC_RESULT(shl);
		carry = SC_CARRY(shl);
387
	}
Matthias Braun's avatar
Matthias Braun committed
388
389
	int counter   = bitsize/4 - shift_cnt;
	int bitoffset = 0;
390
	if (bitsize%4 > 0) {
391
392
		unsigned const shl = val1[counter] << shift | carry;
		buffer[counter + shift_cnt] = SC_RESULT(shl);
393
394
395
396
397
398
		bitoffset = counter;
	} else {
		bitoffset = counter - 1;
	}

	/* fill with zeroes */
Matthias Braun's avatar
Matthias Braun committed
399
	for (int counter = 0; counter < shift_cnt; counter++)
400
401
402
		buffer[counter] = SC_0;

	/* if the mode was signed, change sign when the mode's msb is now 1 */
403
404
405
	shift_cnt = bitoffset + shift_cnt;
	bitoffset = (bitsize-1) % 4;
	if (is_signed && _bitisset(buffer[shift_cnt], bitoffset)) {
406
		/* this sets the upper bits of the leftmost digit */
407
		buffer[shift_cnt] |= min_digit[bitoffset];
Matthias Braun's avatar
Matthias Braun committed
408
		for (int counter = shift_cnt+1; counter < calc_buffer_size; counter++) {
409
410
			buffer[counter] = SC_F;
		}
411
	} else if (is_signed && !_bitisset(buffer[shift_cnt], bitoffset)) {
412
		/* this clears the upper bits of the leftmost digit */
413
		buffer[shift_cnt] &= max_digit[bitoffset];
Matthias Braun's avatar
Matthias Braun committed
414
		for (int counter = shift_cnt+1; counter < calc_buffer_size; counter++) {
415
416
417
			buffer[counter] = SC_0;
		}
	}
418
419
}

Michael Beck's avatar
Michael Beck committed
420
421
422
423
/**
 * Implements a Shift Right, which can either preserve the sign bit
 * or not.
 *
424
 * @param bitsize   bitsize of the value to be shifted
Michael Beck's avatar
Michael Beck committed
425
 */
Matthias Braun's avatar
Matthias Braun committed
426
static void do_shr(const char *val1, char *buffer, long shift_cnt, int bitsize,
427
                   bool is_signed, int signed_shift)
428
{
429
	assert(shift_cnt >= 0);
430

Matthias Braun's avatar
Matthias Braun committed
431
	char sign = signed_shift && do_bit(val1, bitsize - 1) ? SC_F : SC_0;
432
433

	/* if shifting far enough the result is either 0 or -1 */
434
	if (shift_cnt >= bitsize) {
Matthias Braun's avatar
Matthias Braun committed
435
		if (!sc_is_zero(val1, calc_buffer_size)) {
Matthias Braun's avatar
Matthias Braun committed
436
			carry_flag = true;
437
438
439
440
441
		}
		memset(buffer, sign, calc_buffer_size);
		return;
	}

Matthias Braun's avatar
Matthias Braun committed
442
443
	int shift_mod = shift_cnt &  3;
	int shift_nib = shift_cnt >> 2;
444
445

	/* check if any bits are lost, and set carry_flag if so */
Matthias Braun's avatar
Matthias Braun committed
446
	for (int counter = 0; counter < shift_nib; ++counter) {
447
		if (val1[counter] != 0) {
Matthias Braun's avatar
Matthias Braun committed
448
			carry_flag = true;
449
450
451
			break;
		}
	}
Matthias Braun's avatar
Matthias Braun committed
452
	if ((_val(val1[shift_nib]) & ((1<<shift_mod)-1)) != 0)
Matthias Braun's avatar
Matthias Braun committed
453
		carry_flag = true;
454

455
	/* shift digits to the right with offset, carry and all */
456
	buffer[0] = shrs_table[_val(val1[shift_nib])][shift_mod][0];
Matthias Braun's avatar
Matthias Braun committed
457
	int counter;
458
	for (counter = 1; counter < ((bitsize + 3) >> 2) - shift_nib; counter++) {
459
		const char *shrs = shrs_table[_val(val1[counter+shift_nib])][shift_mod];
460
461
		buffer[counter]      = shrs[0];
		buffer[counter - 1] |= shrs[1];
462
463
464
	}

	/* the last digit is special in regard of signed/unsigned shift */
Matthias Braun's avatar
Matthias Braun committed
465
466
	int bitoffset = bitsize & 3;
	char msd = sign;  /* most significant digit */
467
468
469

	/* remove sign bits if mode was signed and this is an unsigned shift */
	if (!signed_shift && is_signed) {
470
		msd &= max_digit[bitoffset];
471
472
	}

Matthias Braun's avatar
Matthias Braun committed
473
	const char *shrs = shrs_table[_val(msd)][shift_mod];
474

475
476
	/* signed shift and signed mode and negative value means all bits to the
	 * left are set */
477
	if (signed_shift && sign == SC_F) {
478
		buffer[counter] = shrs[0] | min_digit[bitoffset];
479
480
481
482
	} else {
		buffer[counter] = shrs[0];
	}

483
	if (counter > 0)
484
		buffer[counter - 1] |= shrs[1];
485
486
487
488
489

	/* fill with SC_F or SC_0 depending on sign */
	for (counter++; counter < calc_buffer_size; counter++) {
		buffer[counter] = sign;
	}
490
491
}

492

493
494
const void *sc_get_buffer(void)
{
495
	return (void*)calc_buffer;
496
497
}

498
499
int sc_get_buffer_length(void)
{
500
	return calc_buffer_size;
501
502
}

503
void sign_extend(void *buffer, unsigned from_bits, bool is_signed)
504
{
Matthias Braun's avatar
Matthias Braun committed
505
	char *calc_buffer = (char*)buffer;
506
	int bits          = from_bits - 1;
507
	int nibble        = bits >> 2;
508

509
	if (is_signed) {
Matthias Braun's avatar
Matthias Braun committed
510
		int max = max_digit[bits & 3];
511
512
513
		if (calc_buffer[nibble] > max) {
			/* sign bit is set, we need sign expansion */

Matthias Braun's avatar
Matthias Braun committed
514
			for (int i = nibble + 1; i < calc_buffer_size; ++i)
515
				calc_buffer[i] = SC_F;
516
			calc_buffer[nibble] |= sex_digit[bits & 3];
517
518
		} else {
			/* set all bits to zero */
Matthias Braun's avatar
Matthias Braun committed
519
			for (int i = nibble + 1; i < calc_buffer_size; ++i)
520
				calc_buffer[i] = SC_0;
521
			calc_buffer[nibble] &= zex_digit[bits & 3];
522
523
524
		}
	} else {
		/* do zero extension */
Matthias Braun's avatar
Matthias Braun committed
525
		for (int i = nibble + 1; i < calc_buffer_size; ++i)
526
			calc_buffer[i] = SC_0;
527
		calc_buffer[nibble] &= zex_digit[bits & 3];
528
	}
529
530
}

Matthias Braun's avatar
Matthias Braun committed
531
/* ensure that our source character set conforms to ASCII for a-f, A-F, 0-9 */
532
static inline void check_ascii(void)
533
{
Matthias Braun's avatar
Matthias Braun committed
534
535
536
537
	assert((('a'-97) | ('b'-98) | ('c'-99) | ('d'-100) | ('e'-101) | ('f'-102)
	       |('A'-65) | ('B'-66) | ('C'-67) | ('D'- 68) | ('E'- 69) | ('F'- 70)
	       |('0'-48) | ('1'-49) | ('2'-50) | ('3'- 51) | ('4'- 52)
	       |('5'-53) | ('6'-54) | ('7'-55) | ('8'- 56) | ('9'- 57)) == 0);
538
}
539

540
541
bool sc_val_from_str(char sign, unsigned base, const char *str, size_t len,
                     void *buffer)
542
543
544
545
546
{
	assert(sign == -1 || sign == 1);
	assert(str != NULL);
	assert(len > 0);
	check_ascii();
547

548
	assert(base > 1 && base <= 16);
549
	char *sc_base = ALLOCAN(char, calc_buffer_size);
550
	sc_val_from_ulong(base, sc_base);
551

552
	char *val = ALLOCAN(char, calc_buffer_size);
553
554
	if (buffer == NULL)
		buffer = calc_buffer;
555
556
557
558
559
560

	CLEAR_BUFFER(buffer);
	CLEAR_BUFFER(val);

	/* BEGIN string evaluation, from left to right */
	while (len > 0) {
561
562
563
564
		char c = *str;
		unsigned v;
		if (c >= '0' && c <= '9')
			v = c - '0';
565
566
567
568
		else if (c >= 'A' && c <= 'F')
			v = c - 'A' + 10;
		else if (c >= 'a' && c <= 'f')
			v = c - 'a' + 10;
569
		else
570
			return false;
571

572
		if (v >= base)
573
			return false;
574
		val[0] = v;
575
576
577

		/* Radix conversion from base b to base B:
		 *  (UnUn-1...U1U0)b == ((((Un*b + Un-1)*b + ...)*b + U1)*b + U0)B */
578
		/* multiply current value with base */
579
		do_mul(sc_base, (const char*) buffer, (char*) buffer);
580
		/* add next digit to current value  */
581
		do_add(val, (const char*) buffer, (char*) buffer);
582
583
584
585

		/* get ready for the next letter */
		str++;
		len--;
586
	}
587

588
	if (sign < 0)
589
		do_negate((const char*) buffer, (char*) buffer);
590

591
	return true;
592
593
}

594
595
void sc_val_from_long(long value, void *buffer)
{
596
	if (buffer == NULL) buffer = calc_buffer;
Matthias Braun's avatar
Matthias Braun committed
597
	char *pos = (char*) buffer;
598

Matthias Braun's avatar
Matthias Braun committed
599
600
	char sign       = (value < 0);
	char is_minlong = value == LONG_MIN;
601

602
603
604
605
606
607
608
	/* use absolute value, special treatment of MIN_LONG to avoid overflow */
	if (sign) {
		if (is_minlong)
			value = -(value+1);
		else
			value = -value;
	}
609

610
	CLEAR_BUFFER(buffer);
611

612
613
614
615
	while ((value != 0) && (pos < (char*)buffer + calc_buffer_size)) {
		*pos++ = _digit(value & 0xf);
		value >>= 4;
	}
616

617
618
	if (sign) {
		if (is_minlong)
619
			do_inc((const char*) buffer, (char*) buffer);
620

621
		do_negate((const char*) buffer, (char*) buffer);
622
	}
623
624
}

625
626
void sc_val_from_ulong(unsigned long value, void *buffer)
{
627
	if (buffer == NULL) buffer = calc_buffer;
Matthias Braun's avatar
Matthias Braun committed
628
	unsigned char *pos = (unsigned char*) buffer;
629

630
631
632
633
	while (pos < (unsigned char *)buffer + calc_buffer_size) {
		*pos++ = (unsigned char)_digit(value & 0xf);
		value >>= 4;
	}
634
635
}

636
637
long sc_val_to_long(const void *val)
{
Andreas Zwinkau's avatar
Andreas Zwinkau committed
638
639
640
641
	unsigned long l = 0;
	int max_buffer_index = sizeof(long)*8/SC_BITS;
	for (size_t i = max_buffer_index; i-- > 0;) {
		assert(l <= (ULONG_MAX>>4) && "signed shift overflow");
642
643
644
		l = (l << 4) + _val(((char *)val)[i]);
	}
	return l;
645
646
}

647
648
649
650
651
652
uint64_t sc_val_to_uint64(const void *val)
{
	uint64_t res = 0;
	for (int i = calc_buffer_size - 1; i >= 0; i--) {
		res = (res << 4) + _val(((char*)val)[i]);
	}
Manuel Mohr's avatar
Manuel Mohr committed
653
	return res;
654
655
}

656
void sc_min_from_bits(unsigned int num_bits, bool sign, void *buffer)
657
{
658
659
	if (buffer == NULL) buffer = calc_buffer;
	CLEAR_BUFFER(buffer);
660

661
	if (!sign) return;  /* unsigned means minimum is 0(zero) */
662

Matthias Braun's avatar
Matthias Braun committed
663
	char *pos = (char*) buffer;
664

Matthias Braun's avatar
Matthias Braun committed
665
666
	int bits = num_bits - 1;
	int i;
667
668
	for (i = 0; i < bits/4; i++)
		*pos++ = SC_0;
669

670
	*pos++ = min_digit[bits%4];
671

672
673
	for (i++; i <= calc_buffer_size - 1; i++)
		*pos++ = SC_F;
674
675
}

676
void sc_max_from_bits(unsigned int num_bits, bool sign, void *buffer)
677
{
678
679
	if (buffer == NULL) buffer = calc_buffer;
	CLEAR_BUFFER(buffer);
Matthias Braun's avatar
Matthias Braun committed
680
	char *pos = (char*) buffer;
681

Matthias Braun's avatar
Matthias Braun committed
682
683
684
	int bits = num_bits - sign;
	int i    = 0;
	for ( ; i < bits/4; i++)
685
		*pos++ = SC_F;
686

687
	*pos++ = max_digit[bits%4];
688

689
690
	for (i++; i <= calc_buffer_size - 1; i++)
		*pos++ = SC_0;
691
692
}

693
694
void sc_truncate(unsigned int num_bits, void *buffer)
{
695
	char *cbuffer = (char*) buffer;
696
697
	char *pos = cbuffer + (num_bits / 4);
	char *end = cbuffer + calc_buffer_size;
698
699
700

	assert(pos < end);

701
	switch (num_bits % 4) {
702
	case 0: /* nothing to do */ break;
703
704
705
	case 1: *pos++ &= SC_1; break;
	case 2: *pos++ &= SC_3; break;
	case 3: *pos++ &= SC_7; break;
706
707
	}

708
	for ( ; pos < end; ++pos)
709
710
711
		*pos = SC_0;
}

712
ir_relation sc_comp(void const* const value1, void const* const value2)
713
{
714
715
716
717
718
719
	int counter = calc_buffer_size - 1;
	const char *val1 = (const char *)value1;
	const char *val2 = (const char *)value2;

	/* compare signs first:
	 * the loop below can only compare values of the same sign! */
720
	if (do_sign(val1) != do_sign(val2))
721
		return do_sign(val1) == 1 ? ir_relation_greater : ir_relation_less;
722
723
724
725
726

	/* loop until two digits differ, the values are equal if there
	 * are no such two digits */
	while (val1[counter] == val2[counter]) {
		counter--;
727
		if (counter < 0) return ir_relation_equal;
728
729
730
731
732
	}

	/* the leftmost digit is the most significant, so this returns
	 * the correct result.
	 * This implies the digit enum is ordered */
733
	return val1[counter] > val2[counter] ? ir_relation_greater : ir_relation_less;
734
735
}

736
737
int sc_get_highest_set_bit(const void *value)
{
Matthias Braun's avatar
Matthias Braun committed
738
739
740
	const char *val  = (const char*)value;
	int         high = calc_buffer_size * 4 - 1;
	for (int counter = calc_buffer_size-1; counter >= 0; counter--) {
741
742
743
744
745
746
747
748
749
750
		if (val[counter] == SC_0)
			high -= 4;
		else {
			if (val[counter] > SC_7) return high;
			else if (val[counter] > SC_3) return high - 1;
			else if (val[counter] > SC_1) return high - 2;
			else return high - 3;
		}
	}
	return high;
Matthias Heil's avatar
Matthias Heil committed
751
752
}

753
754
int sc_get_lowest_set_bit(const void *value)
{
755
	const char *val = (const char*)value;
Matthias Braun's avatar
Matthias Braun committed
756
757
	int         low = 0;
	for (int counter = 0; counter < calc_buffer_size; counter++) {
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
		switch (val[counter]) {
		case SC_1:
		case SC_3:
		case SC_5:
		case SC_7:
		case SC_9:
		case SC_B:
		case SC_D:
		case SC_F:
			return low;
		case SC_2:
		case SC_6:
		case SC_A:
		case SC_E:
			return low + 1;
		case SC_4:
		case SC_C:
			return low + 2;
		case SC_8:
			return low + 3;
		default:
779
780
781
782
			low += 4;
		}
	}
	return -1;
Matthias Heil's avatar
Matthias Heil committed
783
784
}

785
786
int sc_get_bit_at(const void *value, unsigned pos)
{
Matthias Braun's avatar
Matthias Braun committed
787
788
	const char *val    = (const char*) value;
	unsigned    nibble = pos >> 2;
789

790
	return (val[nibble] & SHIFT(pos & 3)) != SC_0;
791
792
}

793
794
void sc_set_bit_at(void *value, unsigned pos)
{
Matthias Braun's avatar
Matthias Braun committed
795
	char    *val    = (char*) value;
796
797
	unsigned nibble = pos >> 2;

798
	val[nibble] |= SHIFT(pos & 3);
799
800
}

Matthias Braun's avatar
Matthias Braun committed
801
802
803
804
805
806
807
808
809
void sc_clear_bit_at(void *value, unsigned pos)
{
	char    *val    = (char*) value;
	unsigned nibble = pos >> 2;

	val[nibble] &= ~SHIFT(pos & 3);
}

bool sc_is_zero(const void *value, unsigned bits)
810
{
811
	const char* val = (const char *)value;
Matthias Braun's avatar
Matthias Braun committed
812
813
814
	unsigned i;
	for (i = 0; i < bits/SC_BITS; ++i) {
		if (val[i] != SC_0)
815
			return false;
816
	}
Matthias Braun's avatar
Matthias Braun committed
817
818
819
820
821
822
823
824
825
826
827
828
829
830
	char mask = max_digit[bits%SC_BITS];
	return mask == 0 || (val[i] & mask) == SC_0;
}

bool sc_is_all_one(const void *value, unsigned bits)
{
	const char* val = (const char*)value;
	unsigned i;
	for (i = 0; i < bits/SC_BITS; ++i) {
		if (val[i] != SC_F)
			return false;
	}
	char mask = max_digit[bits%SC_BITS];
	return mask == 0 || (val[i] & mask) == mask;
831
832
}

833
bool sc_is_negative(const void *value)
834
{
835
	return do_sign((const char*) value) == -1;
836
837
}

838
839
unsigned char sc_sub_bits(const void *value, int len, unsigned byte_ofs)
{
840
	/* the current scheme uses one byte to store a nibble */
Matthias Braun's avatar
Matthias Braun committed
841
	int nibble_ofs = 2 * byte_ofs;
842
	if (4 * nibble_ofs >= len)
843
		return 0;
844

Matthias Braun's avatar
Matthias Braun committed
845
846
	const char   *val = (const char *)value;
	unsigned char res = _val(val[nibble_ofs]);
847
	if (len > 4 * (nibble_ofs + 1))
848
		res |= _val(val[nibble_ofs + 1]) << 4;
849

850
	/* kick bits outsize */
851
852
	if (len - 8 * byte_ofs < 8) {
		res &= (1 << (len - 8 * byte_ofs)) - 1;
853
	}
854
	return res;
855
856
}

Matthias Braun's avatar
Matthias Braun committed
857
858
859
860
861
862
863
864
void sc_val_from_bytes(unsigned char const *const bytes, size_t n_bytes,
                       bool big_endian, void *buffer)
{
	assert(n_bytes <= (size_t)calc_buffer_size);

	if (buffer == NULL)
		buffer = calc_buffer;
	char *p = (char*)buffer;
865
	assert(SC_BITS == 4);
Matthias Braun's avatar
Matthias Braun committed
866
	if (big_endian) {
867
		for (unsigned char const *bp = bytes+n_bytes-1; bp >= bytes; --bp) {
Matthias Braun's avatar
Matthias Braun committed
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
			unsigned char v = *bp;
			*p++ =  v     & 0xf;
			*p++ = (v>>4) & 0xf;
		}
	} else {
		for (unsigned char const *bp = bytes, *bp_end = bytes + n_bytes;
		     bp < bp_end; ++bp) {
			unsigned char v = *bp;
			*p++ =  v     & 0xf;
			*p++ = (v>>4) & 0xf;
		}
	}
	for (char *p_end = (char*)buffer+calc_buffer_size; p < p_end; ++p)
		*p = 0;
}

884
885
886
887
void sc_val_from_bits(unsigned char const *const bytes, unsigned from,
                      unsigned to, void *buffer)
{
	assert(from < to);
yb9976's avatar
yb9976 committed
888
	assert((to - from) / 8 <= (unsigned)calc_buffer_size);
889
890
891
892
893
894
895
896
897
898
899
900
901
	assert(SC_BITS == 4);

	if (buffer == NULL)
		buffer = calc_buffer;
	unsigned char *p = (unsigned char*)buffer;

	/* see which is the lowest and highest byte, special case if they are
	 * the same. */
	const unsigned char *const low      = &bytes[from/8];
	const unsigned char *const high     = &bytes[(to-1)/8];
	const uint8_t              low_bit  = from%8;
	const uint8_t              high_bit = (to-1)%8 + 1;
	if (low == high) {