1/*
2 * Integer number functions.
3 *
4 *  Copyright (C) 2001-2007  Peter Johnson
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27#include "util.h"
28
29#include <ctype.h>
30#include <limits.h>
31
32#include "coretype.h"
33#include "bitvect.h"
34#include "file.h"
35
36#include "errwarn.h"
37#include "intnum.h"
38
39
40/* "Native" "word" size for intnum calculations. */
41#define BITVECT_NATIVE_SIZE     256
42
43struct yasm_intnum {
44    union val {
45        long l;                 /* integer value (for integers <32 bits) */
46        wordptr bv;             /* bit vector (for integers >=32 bits) */
47    } val;
48    enum { INTNUM_L, INTNUM_BV } type;
49};
50
51/* static bitvect used for conversions */
52static /*@only@*/ wordptr conv_bv;
53
54/* static bitvects used for computation */
55static /*@only@*/ wordptr result, spare, op1static, op2static;
56
57static /*@only@*/ BitVector_from_Dec_static_data *from_dec_data;
58
59
60void
61yasm_intnum_initialize(void)
62{
63    conv_bv = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
64    result = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
65    spare = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
66    op1static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
67    op2static = BitVector_Create(BITVECT_NATIVE_SIZE, FALSE);
68    from_dec_data = BitVector_from_Dec_static_Boot(BITVECT_NATIVE_SIZE);
69}
70
71void
72yasm_intnum_cleanup(void)
73{
74    BitVector_from_Dec_static_Shutdown(from_dec_data);
75    BitVector_Destroy(op2static);
76    BitVector_Destroy(op1static);
77    BitVector_Destroy(spare);
78    BitVector_Destroy(result);
79    BitVector_Destroy(conv_bv);
80}
81
82/* Compress a bitvector into intnum storage.
83 * If saved as a bitvector, clones the passed bitvector.
84 * Can modify the passed bitvector.
85 */
86static void
87intnum_frombv(/*@out@*/ yasm_intnum *intn, wordptr bv)
88{
89    if (Set_Max(bv) < 31) {
90        intn->type = INTNUM_L;
91        intn->val.l = (long)BitVector_Chunk_Read(bv, 31, 0);
92    } else if (BitVector_msb_(bv)) {
93        /* Negative, negate and see if we'll fit into a long. */
94        unsigned long ul;
95        BitVector_Negate(bv, bv);
96        if (Set_Max(bv) >= 32 ||
97            ((ul = BitVector_Chunk_Read(bv, 32, 0)) & 0x80000000)) {
98            /* too negative */
99            BitVector_Negate(bv, bv);
100            intn->type = INTNUM_BV;
101            intn->val.bv = BitVector_Clone(bv);
102        } else {
103            intn->type = INTNUM_L;
104            intn->val.l = -((long)ul);
105        }
106    } else {
107        intn->type = INTNUM_BV;
108        intn->val.bv = BitVector_Clone(bv);
109    }
110}
111
112/* If intnum is a BV, returns its bitvector directly.
113 * If not, converts into passed bv and returns that instead.
114 */
115static wordptr
116intnum_tobv(/*@returned@*/ wordptr bv, const yasm_intnum *intn)
117{
118    if (intn->type == INTNUM_BV)
119        return intn->val.bv;
120
121    BitVector_Empty(bv);
122    if (intn->val.l >= 0)
123        BitVector_Chunk_Store(bv, 32, 0, (unsigned long)intn->val.l);
124    else {
125        BitVector_Chunk_Store(bv, 32, 0, (unsigned long)-intn->val.l);
126        BitVector_Negate(bv, bv);
127    }
128    return bv;
129}
130
131yasm_intnum *
132yasm_intnum_create_dec(char *str)
133{
134    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
135
136    switch (BitVector_from_Dec_static(from_dec_data, conv_bv,
137                                      (unsigned char *)str)) {
138        case ErrCode_Pars:
139            yasm_error_set(YASM_ERROR_VALUE, N_("invalid decimal literal"));
140            break;
141        case ErrCode_Ovfl:
142            yasm_error_set(YASM_ERROR_OVERFLOW,
143                N_("Numeric constant too large for internal format"));
144            break;
145        default:
146            break;
147    }
148    intnum_frombv(intn, conv_bv);
149    return intn;
150}
151
152yasm_intnum *
153yasm_intnum_create_bin(char *str)
154{
155    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
156
157    switch (BitVector_from_Bin(conv_bv, (unsigned char *)str)) {
158        case ErrCode_Pars:
159            yasm_error_set(YASM_ERROR_VALUE, N_("invalid binary literal"));
160            break;
161        case ErrCode_Ovfl:
162            yasm_error_set(YASM_ERROR_OVERFLOW,
163                N_("Numeric constant too large for internal format"));
164            break;
165        default:
166            break;
167    }
168    intnum_frombv(intn, conv_bv);
169    return intn;
170}
171
172yasm_intnum *
173yasm_intnum_create_oct(char *str)
174{
175    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
176
177    switch (BitVector_from_Oct(conv_bv, (unsigned char *)str)) {
178        case ErrCode_Pars:
179            yasm_error_set(YASM_ERROR_VALUE, N_("invalid octal literal"));
180            break;
181        case ErrCode_Ovfl:
182            yasm_error_set(YASM_ERROR_OVERFLOW,
183                N_("Numeric constant too large for internal format"));
184            break;
185        default:
186            break;
187    }
188    intnum_frombv(intn, conv_bv);
189    return intn;
190}
191
192yasm_intnum *
193yasm_intnum_create_hex(char *str)
194{
195    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
196
197    switch (BitVector_from_Hex(conv_bv, (unsigned char *)str)) {
198        case ErrCode_Pars:
199            yasm_error_set(YASM_ERROR_VALUE, N_("invalid hex literal"));
200            break;
201        case ErrCode_Ovfl:
202            yasm_error_set(YASM_ERROR_OVERFLOW,
203                           N_("Numeric constant too large for internal format"));
204            break;
205        default:
206            break;
207    }
208    intnum_frombv(intn, conv_bv);
209    return intn;
210}
211
212/*@-usedef -compdef -uniondef@*/
213yasm_intnum *
214yasm_intnum_create_charconst_nasm(const char *str)
215{
216    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
217    size_t len = strlen(str);
218
219    if(len*8 > BITVECT_NATIVE_SIZE)
220        yasm_error_set(YASM_ERROR_OVERFLOW,
221                       N_("Character constant too large for internal format"));
222
223    /* be conservative in choosing bitvect in case MSB is set */
224    if (len > 3) {
225        BitVector_Empty(conv_bv);
226        intn->type = INTNUM_BV;
227    } else {
228        intn->val.l = 0;
229        intn->type = INTNUM_L;
230    }
231
232    switch (len) {
233        case 3:
234            intn->val.l |= ((unsigned long)str[2]) & 0xff;
235            intn->val.l <<= 8;
236            /*@fallthrough@*/
237        case 2:
238            intn->val.l |= ((unsigned long)str[1]) & 0xff;
239            intn->val.l <<= 8;
240            /*@fallthrough@*/
241        case 1:
242            intn->val.l |= ((unsigned long)str[0]) & 0xff;
243        case 0:
244            break;
245        default:
246            /* >=32 bit conversion */
247            while (len) {
248                BitVector_Move_Left(conv_bv, 8);
249                BitVector_Chunk_Store(conv_bv, 8, 0,
250                                      ((unsigned long)str[--len]) & 0xff);
251            }
252            intn->val.bv = BitVector_Clone(conv_bv);
253    }
254
255    return intn;
256}
257
258yasm_intnum *
259yasm_intnum_create_charconst_tasm(const char *str)
260{
261    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
262    size_t len = strlen(str);
263    size_t i;
264
265    if(len*8 > BITVECT_NATIVE_SIZE)
266        yasm_error_set(YASM_ERROR_OVERFLOW,
267                       N_("Character constant too large for internal format"));
268
269    /* be conservative in choosing bitvect in case MSB is set */
270    if (len > 3) {
271        BitVector_Empty(conv_bv);
272        intn->type = INTNUM_BV;
273    } else {
274        intn->val.l = 0;
275        intn->type = INTNUM_L;
276    }
277
278    /* tasm uses big endian notation */
279    i = 0;
280    switch (len) {
281        case 3:
282            intn->val.l |= ((unsigned long)str[i++]) & 0xff;
283            intn->val.l <<= 8;
284            /*@fallthrough@*/
285        case 2:
286            intn->val.l |= ((unsigned long)str[i++]) & 0xff;
287            intn->val.l <<= 8;
288            /*@fallthrough@*/
289        case 1:
290            intn->val.l |= ((unsigned long)str[i++]) & 0xff;
291        case 0:
292            break;
293        default:
294            /* >=32 bit conversion */
295            while (i < len) {
296                BitVector_Chunk_Store(conv_bv, 8, (len-i-1)*8,
297                                      ((unsigned long)str[i]) & 0xff);
298                i++;
299            }
300            intn->val.bv = BitVector_Clone(conv_bv);
301    }
302
303    return intn;
304}
305/*@=usedef =compdef =uniondef@*/
306
307yasm_intnum *
308yasm_intnum_create_uint(unsigned long i)
309{
310    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
311
312    if (i > LONG_MAX) {
313        /* Too big, store as bitvector */
314        intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE);
315        intn->type = INTNUM_BV;
316        BitVector_Chunk_Store(intn->val.bv, 32, 0, i);
317    } else {
318        intn->val.l = (long)i;
319        intn->type = INTNUM_L;
320    }
321
322    return intn;
323}
324
325yasm_intnum *
326yasm_intnum_create_int(long i)
327{
328    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
329
330    intn->val.l = i;
331    intn->type = INTNUM_L;
332
333    return intn;
334}
335
336yasm_intnum *
337yasm_intnum_create_leb128(const unsigned char *ptr, int sign,
338                          unsigned long *size)
339{
340    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
341    const unsigned char *ptr_orig = ptr;
342    unsigned long i = 0;
343
344    BitVector_Empty(conv_bv);
345    for (;;) {
346        BitVector_Chunk_Store(conv_bv, 7, i, *ptr);
347        i += 7;
348        if ((*ptr & 0x80) != 0x80)
349            break;
350        ptr++;
351    }
352
353    *size = (unsigned long)(ptr-ptr_orig)+1;
354
355    if(i > BITVECT_NATIVE_SIZE)
356        yasm_error_set(YASM_ERROR_OVERFLOW,
357                       N_("Numeric constant too large for internal format"));
358    else if (sign && (*ptr & 0x40) == 0x40)
359        BitVector_Interval_Fill(conv_bv, i, BITVECT_NATIVE_SIZE-1);
360
361    intnum_frombv(intn, conv_bv);
362    return intn;
363}
364
365yasm_intnum *
366yasm_intnum_create_sized(unsigned char *ptr, int sign, size_t srcsize,
367                         int bigendian)
368{
369    yasm_intnum *intn = yasm_xmalloc(sizeof(yasm_intnum));
370    unsigned long i = 0;
371
372    if (srcsize*8 > BITVECT_NATIVE_SIZE)
373        yasm_error_set(YASM_ERROR_OVERFLOW,
374                       N_("Numeric constant too large for internal format"));
375
376    /* Read the buffer into a bitvect */
377    BitVector_Empty(conv_bv);
378    if (bigendian) {
379        /* TODO */
380        yasm_internal_error(N_("big endian not implemented"));
381    } else {
382        for (i = 0; i < srcsize; i++)
383            BitVector_Chunk_Store(conv_bv, 8, i*8, ptr[i]);
384    }
385
386    /* Sign extend if needed */
387    if (srcsize*8 < BITVECT_NATIVE_SIZE && sign && (ptr[i-1] & 0x80) == 0x80)
388        BitVector_Interval_Fill(conv_bv, i*8, BITVECT_NATIVE_SIZE-1);
389
390    intnum_frombv(intn, conv_bv);
391    return intn;
392}
393
394yasm_intnum *
395yasm_intnum_copy(const yasm_intnum *intn)
396{
397    yasm_intnum *n = yasm_xmalloc(sizeof(yasm_intnum));
398
399    switch (intn->type) {
400        case INTNUM_L:
401            n->val.l = intn->val.l;
402            break;
403        case INTNUM_BV:
404            n->val.bv = BitVector_Clone(intn->val.bv);
405            break;
406    }
407    n->type = intn->type;
408
409    return n;
410}
411
412void
413yasm_intnum_destroy(yasm_intnum *intn)
414{
415    if (intn->type == INTNUM_BV)
416        BitVector_Destroy(intn->val.bv);
417    yasm_xfree(intn);
418}
419
420/*@-nullderef -nullpass -branchstate@*/
421int
422yasm_intnum_calc(yasm_intnum *acc, yasm_expr_op op, yasm_intnum *operand)
423{
424    boolean carry = 0;
425    wordptr op1, op2 = NULL;
426    N_int count;
427
428    /* Always do computations with in full bit vector.
429     * Bit vector results must be calculated through intermediate storage.
430     */
431    op1 = intnum_tobv(op1static, acc);
432    if (operand)
433        op2 = intnum_tobv(op2static, operand);
434
435    if (!operand && op != YASM_EXPR_NEG && op != YASM_EXPR_NOT &&
436        op != YASM_EXPR_LNOT) {
437        yasm_error_set(YASM_ERROR_ARITHMETIC,
438                       N_("operation needs an operand"));
439        BitVector_Empty(result);
440        return 1;
441    }
442
443    /* A operation does a bitvector computation if result is allocated. */
444    switch (op) {
445        case YASM_EXPR_ADD:
446            BitVector_add(result, op1, op2, &carry);
447            break;
448        case YASM_EXPR_SUB:
449            BitVector_sub(result, op1, op2, &carry);
450            break;
451        case YASM_EXPR_MUL:
452            BitVector_Multiply(result, op1, op2);
453            break;
454        case YASM_EXPR_DIV:
455            /* TODO: make sure op1 and op2 are unsigned */
456            if (BitVector_is_empty(op2)) {
457                yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
458                BitVector_Empty(result);
459                return 1;
460            } else
461                BitVector_Divide(result, op1, op2, spare);
462            break;
463        case YASM_EXPR_SIGNDIV:
464            if (BitVector_is_empty(op2)) {
465                yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
466                BitVector_Empty(result);
467                return 1;
468            } else
469                BitVector_Divide(result, op1, op2, spare);
470            break;
471        case YASM_EXPR_MOD:
472            /* TODO: make sure op1 and op2 are unsigned */
473            if (BitVector_is_empty(op2)) {
474                yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
475                BitVector_Empty(result);
476                return 1;
477            } else
478                BitVector_Divide(spare, op1, op2, result);
479            break;
480        case YASM_EXPR_SIGNMOD:
481            if (BitVector_is_empty(op2)) {
482                yasm_error_set(YASM_ERROR_ZERO_DIVISION, N_("divide by zero"));
483                BitVector_Empty(result);
484                return 1;
485            } else
486                BitVector_Divide(spare, op1, op2, result);
487            break;
488        case YASM_EXPR_NEG:
489            BitVector_Negate(result, op1);
490            break;
491        case YASM_EXPR_NOT:
492            Set_Complement(result, op1);
493            break;
494        case YASM_EXPR_OR:
495            Set_Union(result, op1, op2);
496            break;
497        case YASM_EXPR_AND:
498            Set_Intersection(result, op1, op2);
499            break;
500        case YASM_EXPR_XOR:
501            Set_ExclusiveOr(result, op1, op2);
502            break;
503        case YASM_EXPR_XNOR:
504            Set_ExclusiveOr(result, op1, op2);
505            Set_Complement(result, result);
506            break;
507        case YASM_EXPR_NOR:
508            Set_Union(result, op1, op2);
509            Set_Complement(result, result);
510            break;
511        case YASM_EXPR_SHL:
512            if (operand->type == INTNUM_L && operand->val.l >= 0) {
513                BitVector_Copy(result, op1);
514                BitVector_Move_Left(result, (N_int)operand->val.l);
515            } else      /* don't even bother, just zero result */
516                BitVector_Empty(result);
517            break;
518        case YASM_EXPR_SHR:
519            if (operand->type == INTNUM_L && operand->val.l >= 0) {
520                BitVector_Copy(result, op1);
521                carry = BitVector_msb_(op1);
522                count = (N_int)operand->val.l;
523                while (count-- > 0)
524                    BitVector_shift_right(result, carry);
525            } else      /* don't even bother, just zero result */
526                BitVector_Empty(result);
527            break;
528        case YASM_EXPR_LOR:
529            BitVector_Empty(result);
530            BitVector_LSB(result, !BitVector_is_empty(op1) ||
531                          !BitVector_is_empty(op2));
532            break;
533        case YASM_EXPR_LAND:
534            BitVector_Empty(result);
535            BitVector_LSB(result, !BitVector_is_empty(op1) &&
536                          !BitVector_is_empty(op2));
537            break;
538        case YASM_EXPR_LNOT:
539            BitVector_Empty(result);
540            BitVector_LSB(result, BitVector_is_empty(op1));
541            break;
542        case YASM_EXPR_LXOR:
543            BitVector_Empty(result);
544            BitVector_LSB(result, !BitVector_is_empty(op1) ^
545                          !BitVector_is_empty(op2));
546            break;
547        case YASM_EXPR_LXNOR:
548            BitVector_Empty(result);
549            BitVector_LSB(result, !(!BitVector_is_empty(op1) ^
550                          !BitVector_is_empty(op2)));
551            break;
552        case YASM_EXPR_LNOR:
553            BitVector_Empty(result);
554            BitVector_LSB(result, !(!BitVector_is_empty(op1) ||
555                          !BitVector_is_empty(op2)));
556            break;
557        case YASM_EXPR_EQ:
558            BitVector_Empty(result);
559            BitVector_LSB(result, BitVector_equal(op1, op2));
560            break;
561        case YASM_EXPR_LT:
562            BitVector_Empty(result);
563            BitVector_LSB(result, BitVector_Compare(op1, op2) < 0);
564            break;
565        case YASM_EXPR_GT:
566            BitVector_Empty(result);
567            BitVector_LSB(result, BitVector_Compare(op1, op2) > 0);
568            break;
569        case YASM_EXPR_LE:
570            BitVector_Empty(result);
571            BitVector_LSB(result, BitVector_Compare(op1, op2) <= 0);
572            break;
573        case YASM_EXPR_GE:
574            BitVector_Empty(result);
575            BitVector_LSB(result, BitVector_Compare(op1, op2) >= 0);
576            break;
577        case YASM_EXPR_NE:
578            BitVector_Empty(result);
579            BitVector_LSB(result, !BitVector_equal(op1, op2));
580            break;
581        case YASM_EXPR_SEG:
582            yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
583                           "SEG");
584            break;
585        case YASM_EXPR_WRT:
586            yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
587                           "WRT");
588            break;
589        case YASM_EXPR_SEGOFF:
590            yasm_error_set(YASM_ERROR_ARITHMETIC, N_("invalid use of '%s'"),
591                           ":");
592            break;
593        case YASM_EXPR_IDENT:
594            if (result)
595                BitVector_Copy(result, op1);
596            break;
597        default:
598            yasm_error_set(YASM_ERROR_ARITHMETIC,
599                           N_("invalid operation in intnum calculation"));
600            BitVector_Empty(result);
601            return 1;
602    }
603
604    /* Try to fit the result into 32 bits if possible */
605    if (acc->type == INTNUM_BV)
606        BitVector_Destroy(acc->val.bv);
607    intnum_frombv(acc, result);
608    return 0;
609}
610/*@=nullderef =nullpass =branchstate@*/
611
612int
613yasm_intnum_compare(const yasm_intnum *intn1, const yasm_intnum *intn2)
614{
615    wordptr op1, op2;
616
617    if (intn1->type == INTNUM_L && intn2->type == INTNUM_L) {
618        if (intn1->val.l < intn2->val.l)
619            return -1;
620        if (intn1->val.l > intn2->val.l)
621            return 1;
622        return 0;
623    }
624
625    op1 = intnum_tobv(op1static, intn1);
626    op2 = intnum_tobv(op2static, intn2);
627    return BitVector_Compare(op1, op2);
628}
629
630void
631yasm_intnum_zero(yasm_intnum *intn)
632{
633    yasm_intnum_set_int(intn, 0);
634}
635
636void
637yasm_intnum_set(yasm_intnum *intn, const yasm_intnum *val)
638{
639    if (intn->type == val->type) {
640        switch (val->type) {
641            case INTNUM_L:
642                intn->val.l = val->val.l;
643                break;
644            case INTNUM_BV:
645                BitVector_Copy(intn->val.bv, val->val.bv);
646                break;
647        }
648    } else {
649        switch (val->type) {
650            case INTNUM_L:
651                BitVector_Destroy(intn->val.bv);
652                intn->val.l = val->val.l;
653                break;
654            case INTNUM_BV:
655                intn->val.bv = BitVector_Clone(val->val.bv);
656                break;
657        }
658        intn->type = val->type;
659    }
660}
661
662void
663yasm_intnum_set_uint(yasm_intnum *intn, unsigned long val)
664{
665    if (val > LONG_MAX) {
666        if (intn->type != INTNUM_BV) {
667            intn->val.bv = BitVector_Create(BITVECT_NATIVE_SIZE, TRUE);
668            intn->type = INTNUM_BV;
669        }
670        BitVector_Chunk_Store(intn->val.bv, 32, 0, val);
671    } else {
672        if (intn->type == INTNUM_BV) {
673            BitVector_Destroy(intn->val.bv);
674            intn->type = INTNUM_L;
675        }
676        intn->val.l = (long)val;
677    }
678}
679
680void
681yasm_intnum_set_int(yasm_intnum *intn, long val)
682{
683    if (intn->type == INTNUM_BV)
684        BitVector_Destroy(intn->val.bv);
685    intn->type = INTNUM_L;
686    intn->val.l = val;
687}
688
689int
690yasm_intnum_is_zero(const yasm_intnum *intn)
691{
692    return (intn->type == INTNUM_L && intn->val.l == 0);
693}
694
695int
696yasm_intnum_is_pos1(const yasm_intnum *intn)
697{
698    return (intn->type == INTNUM_L && intn->val.l == 1);
699}
700
701int
702yasm_intnum_is_neg1(const yasm_intnum *intn)
703{
704    return (intn->type == INTNUM_L && intn->val.l == -1);
705}
706
707int
708yasm_intnum_sign(const yasm_intnum *intn)
709{
710    if (intn->type == INTNUM_L) {
711        if (intn->val.l == 0)
712            return 0;
713        else if (intn->val.l < 0)
714            return -1;
715        else
716            return 1;
717    } else
718        return BitVector_Sign(intn->val.bv);
719}
720
721unsigned long
722yasm_intnum_get_uint(const yasm_intnum *intn)
723{
724    switch (intn->type) {
725        case INTNUM_L:
726            if (intn->val.l < 0)
727                return 0;
728            return (unsigned long)intn->val.l;
729        case INTNUM_BV:
730            if (BitVector_msb_(intn->val.bv))
731                return 0;
732            if (Set_Max(intn->val.bv) > 32)
733                return ULONG_MAX;
734            return BitVector_Chunk_Read(intn->val.bv, 32, 0);
735        default:
736            yasm_internal_error(N_("unknown intnum type"));
737            /*@notreached@*/
738            return 0;
739    }
740}
741
742long
743yasm_intnum_get_int(const yasm_intnum *intn)
744{
745    switch (intn->type) {
746        case INTNUM_L:
747            return intn->val.l;
748        case INTNUM_BV:
749            if (BitVector_msb_(intn->val.bv)) {
750                /* it's negative: negate the bitvector to get a positive
751                 * number, then negate the positive number.
752                 */
753                unsigned long ul;
754
755                BitVector_Negate(conv_bv, intn->val.bv);
756                if (Set_Max(conv_bv) >= 32) {
757                    /* too negative */
758                    return LONG_MIN;
759                }
760                ul = BitVector_Chunk_Read(conv_bv, 32, 0);
761                /* check for too negative */
762                return (ul & 0x80000000) ? LONG_MIN : -((long)ul);
763            }
764
765            /* it's positive, and since it's a BV, it must be >0x7FFFFFFF */
766            return LONG_MAX;
767        default:
768            yasm_internal_error(N_("unknown intnum type"));
769            /*@notreached@*/
770            return 0;
771    }
772}
773
774void
775yasm_intnum_get_sized(const yasm_intnum *intn, unsigned char *ptr,
776                      size_t destsize, size_t valsize, int shift,
777                      int bigendian, int warn)
778{
779    wordptr op1 = op1static, op2;
780    unsigned char *buf;
781    unsigned int len;
782    size_t rshift = shift < 0 ? (size_t)(-shift) : 0;
783    int carry_in;
784
785    /* Currently don't support destinations larger than our native size */
786    if (destsize*8 > BITVECT_NATIVE_SIZE)
787        yasm_internal_error(N_("destination too large"));
788
789    /* General size warnings */
790    if (warn<0 && !yasm_intnum_check_size(intn, valsize, rshift, 1))
791        yasm_warn_set(YASM_WARN_GENERAL,
792                      N_("value does not fit in signed %d bit field"),
793                      valsize);
794    if (warn>0 && !yasm_intnum_check_size(intn, valsize, rshift, 2))
795        yasm_warn_set(YASM_WARN_GENERAL,
796                      N_("value does not fit in %d bit field"), valsize);
797
798    /* Read the original data into a bitvect */
799    if (bigendian) {
800        /* TODO */
801        yasm_internal_error(N_("big endian not implemented"));
802    } else
803        BitVector_Block_Store(op1, ptr, (N_int)destsize);
804
805    /* If not already a bitvect, convert value to be written to a bitvect */
806    op2 = intnum_tobv(op2static, intn);
807
808    /* Check low bits if right shifting and warnings enabled */
809    if (warn && rshift > 0) {
810        BitVector_Copy(conv_bv, op2);
811        BitVector_Move_Left(conv_bv, (N_int)(BITVECT_NATIVE_SIZE-rshift));
812        if (!BitVector_is_empty(conv_bv))
813            yasm_warn_set(YASM_WARN_GENERAL,
814                          N_("misaligned value, truncating to boundary"));
815    }
816
817    /* Shift right if needed */
818    if (rshift > 0) {
819        carry_in = BitVector_msb_(op2);
820        while (rshift-- > 0)
821            BitVector_shift_right(op2, carry_in);
822        shift = 0;
823    }
824
825    /* Write the new value into the destination bitvect */
826    BitVector_Interval_Copy(op1, op2, (unsigned int)shift, 0, (N_int)valsize);
827
828    /* Write out the new data */
829    buf = BitVector_Block_Read(op1, &len);
830    if (bigendian) {
831        /* TODO */
832        yasm_internal_error(N_("big endian not implemented"));
833    } else
834        memcpy(ptr, buf, destsize);
835    yasm_xfree(buf);
836}
837
838/* Return 1 if okay size, 0 if not */
839int
840yasm_intnum_check_size(const yasm_intnum *intn, size_t size, size_t rshift,
841                       int rangetype)
842{
843    wordptr val;
844
845    /* If not already a bitvect, convert value to a bitvect */
846    if (intn->type == INTNUM_BV) {
847        if (rshift > 0) {
848            val = conv_bv;
849            BitVector_Copy(val, intn->val.bv);
850        } else
851            val = intn->val.bv;
852    } else
853        val = intnum_tobv(conv_bv, intn);
854
855    if (size >= BITVECT_NATIVE_SIZE)
856        return 1;
857
858    if (rshift > 0) {
859        int carry_in = BitVector_msb_(val);
860        while (rshift-- > 0)
861            BitVector_shift_right(val, carry_in);
862    }
863
864    if (rangetype > 0) {
865        if (BitVector_msb_(val)) {
866            /* it's negative */
867            int retval;
868
869            BitVector_Negate(conv_bv, val);
870            BitVector_dec(conv_bv, conv_bv);
871            retval = Set_Max(conv_bv) < (long)size-1;
872
873            return retval;
874        }
875
876        if (rangetype == 1)
877            size--;
878    }
879    return (Set_Max(val) < (long)size);
880}
881
882int
883yasm_intnum_in_range(const yasm_intnum *intn, long low, long high)
884{
885    wordptr val = intnum_tobv(result, intn);
886    wordptr lval = op1static;
887    wordptr hval = op2static;
888
889    /* Convert high and low to bitvects */
890    BitVector_Empty(lval);
891    if (low >= 0)
892        BitVector_Chunk_Store(lval, 32, 0, (unsigned long)low);
893    else {
894        BitVector_Chunk_Store(lval, 32, 0, (unsigned long)(-low));
895        BitVector_Negate(lval, lval);
896    }
897
898    BitVector_Empty(hval);
899    if (high >= 0)
900        BitVector_Chunk_Store(hval, 32, 0, (unsigned long)high);
901    else {
902        BitVector_Chunk_Store(hval, 32, 0, (unsigned long)(-high));
903        BitVector_Negate(hval, hval);
904    }
905
906    /* Compare! */
907    return (BitVector_Compare(val, lval) >= 0
908            && BitVector_Compare(val, hval) <= 0);
909}
910
911static unsigned long
912get_leb128(wordptr val, unsigned char *ptr, int sign)
913{
914    unsigned long i, size;
915    unsigned char *ptr_orig = ptr;
916
917    if (sign) {
918        /* Signed mode */
919        if (BitVector_msb_(val)) {
920            /* Negative */
921            BitVector_Negate(conv_bv, val);
922            size = Set_Max(conv_bv)+2;
923        } else {
924            /* Positive */
925            size = Set_Max(val)+2;
926        }
927    } else {
928        /* Unsigned mode */
929        size = Set_Max(val)+1;
930    }
931
932    /* Positive/Unsigned write */
933    for (i=0; i<size; i += 7) {
934        *ptr = (unsigned char)BitVector_Chunk_Read(val, 7, i);
935        *ptr |= 0x80;
936        ptr++;
937    }
938    *(ptr-1) &= 0x7F;   /* Clear MSB of last byte */
939    return (unsigned long)(ptr-ptr_orig);
940}
941
942static unsigned long
943size_leb128(wordptr val, int sign)
944{
945    if (sign) {
946        /* Signed mode */
947        if (BitVector_msb_(val)) {
948            /* Negative */
949            BitVector_Negate(conv_bv, val);
950            return (Set_Max(conv_bv)+8)/7;
951        } else {
952            /* Positive */
953            return (Set_Max(val)+8)/7;
954        }
955    } else {
956        /* Unsigned mode */
957        return (Set_Max(val)+7)/7;
958    }
959}
960
961unsigned long
962yasm_intnum_get_leb128(const yasm_intnum *intn, unsigned char *ptr, int sign)
963{
964    wordptr val;
965
966    /* Shortcut 0 */
967    if (intn->type == INTNUM_L && intn->val.l == 0) {
968        *ptr = 0;
969        return 1;
970    }
971
972    /* If not already a bitvect, convert value to be written to a bitvect */
973    val = intnum_tobv(op1static, intn);
974
975    return get_leb128(val, ptr, sign);
976}
977
978unsigned long
979yasm_intnum_size_leb128(const yasm_intnum *intn, int sign)
980{
981    wordptr val;
982
983    /* Shortcut 0 */
984    if (intn->type == INTNUM_L && intn->val.l == 0) {
985        return 1;
986    }
987
988    /* If not already a bitvect, convert value to a bitvect */
989    val = intnum_tobv(op1static, intn);
990
991    return size_leb128(val, sign);
992}
993
994unsigned long
995yasm_get_sleb128(long v, unsigned char *ptr)
996{
997    wordptr val = op1static;
998
999    /* Shortcut 0 */
1000    if (v == 0) {
1001        *ptr = 0;
1002        return 1;
1003    }
1004
1005    BitVector_Empty(val);
1006    if (v >= 0)
1007        BitVector_Chunk_Store(val, 32, 0, (unsigned long)v);
1008    else {
1009        BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v));
1010        BitVector_Negate(val, val);
1011    }
1012    return get_leb128(val, ptr, 1);
1013}
1014
1015unsigned long
1016yasm_size_sleb128(long v)
1017{
1018    wordptr val = op1static;
1019
1020    if (v == 0)
1021        return 1;
1022
1023    BitVector_Empty(val);
1024    if (v >= 0)
1025        BitVector_Chunk_Store(val, 32, 0, (unsigned long)v);
1026    else {
1027        BitVector_Chunk_Store(val, 32, 0, (unsigned long)(-v));
1028        BitVector_Negate(val, val);
1029    }
1030    return size_leb128(val, 1);
1031}
1032
1033unsigned long
1034yasm_get_uleb128(unsigned long v, unsigned char *ptr)
1035{
1036    wordptr val = op1static;
1037
1038    /* Shortcut 0 */
1039    if (v == 0) {
1040        *ptr = 0;
1041        return 1;
1042    }
1043
1044    BitVector_Empty(val);
1045    BitVector_Chunk_Store(val, 32, 0, v);
1046    return get_leb128(val, ptr, 0);
1047}
1048
1049unsigned long
1050yasm_size_uleb128(unsigned long v)
1051{
1052    wordptr val = op1static;
1053
1054    if (v == 0)
1055        return 1;
1056
1057    BitVector_Empty(val);
1058    BitVector_Chunk_Store(val, 32, 0, v);
1059    return size_leb128(val, 0);
1060}
1061
1062char *
1063yasm_intnum_get_str(const yasm_intnum *intn)
1064{
1065    unsigned char *s;
1066
1067    switch (intn->type) {
1068        case INTNUM_L:
1069            s = yasm_xmalloc(16);
1070            sprintf((char *)s, "%ld", intn->val.l);
1071            return (char *)s;
1072            break;
1073        case INTNUM_BV:
1074            return (char *)BitVector_to_Dec(intn->val.bv);
1075            break;
1076    }
1077    /*@notreached@*/
1078    return NULL;
1079}
1080
1081void
1082yasm_intnum_print(const yasm_intnum *intn, FILE *f)
1083{
1084    unsigned char *s;
1085
1086    switch (intn->type) {
1087        case INTNUM_L:
1088            fprintf(f, "0x%lx", intn->val.l);
1089            break;
1090        case INTNUM_BV:
1091            s = BitVector_to_Hex(intn->val.bv);
1092            fprintf(f, "0x%s", (char *)s);
1093            yasm_xfree(s);
1094            break;
1095    }
1096}
1097