PR inline-asm/84742
[official-gcc.git] / gcc / testsuite / gcc.c-torture / execute / 20040703-1.c
bloba1b75d90bbc016490e3cd6bb5bb61cc905903e23
1 /* PR 16341 */
2 /* { dg-require-effective-target int32plus } */
4 #define PART_PRECISION (sizeof (cpp_num_part) * 8)
6 typedef unsigned int cpp_num_part;
7 typedef struct cpp_num cpp_num;
8 struct cpp_num
10 cpp_num_part high;
11 cpp_num_part low;
12 int unsignedp; /* True if value should be treated as unsigned. */
13 int overflow; /* True if the most recent calculation overflowed. */
16 static int
17 num_positive (cpp_num num, unsigned int precision)
19 if (precision > PART_PRECISION)
21 precision -= PART_PRECISION;
22 return (num.high & (cpp_num_part) 1 << (precision - 1)) == 0;
25 return (num.low & (cpp_num_part) 1 << (precision - 1)) == 0;
28 static cpp_num
29 num_trim (cpp_num num, unsigned int precision)
31 if (precision > PART_PRECISION)
33 precision -= PART_PRECISION;
34 if (precision < PART_PRECISION)
35 num.high &= ((cpp_num_part) 1 << precision) - 1;
37 else
39 if (precision < PART_PRECISION)
40 num.low &= ((cpp_num_part) 1 << precision) - 1;
41 num.high = 0;
44 return num;
47 /* Shift NUM, of width PRECISION, right by N bits. */
48 static cpp_num
49 num_rshift (cpp_num num, unsigned int precision, unsigned int n)
51 cpp_num_part sign_mask;
52 int x = num_positive (num, precision);
54 if (num.unsignedp || x)
55 sign_mask = 0;
56 else
57 sign_mask = ~(cpp_num_part) 0;
59 if (n >= precision)
60 num.high = num.low = sign_mask;
61 else
63 /* Sign-extend. */
64 if (precision < PART_PRECISION)
65 num.high = sign_mask, num.low |= sign_mask << precision;
66 else if (precision < 2 * PART_PRECISION)
67 num.high |= sign_mask << (precision - PART_PRECISION);
69 if (n >= PART_PRECISION)
71 n -= PART_PRECISION;
72 num.low = num.high;
73 num.high = sign_mask;
76 if (n)
78 num.low = (num.low >> n) | (num.high << (PART_PRECISION - n));
79 num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n));
83 num = num_trim (num, precision);
84 num.overflow = 0;
85 return num;
87 #define num_zerop(num) ((num.low | num.high) == 0)
88 #define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
90 cpp_num
91 num_lshift (cpp_num num, unsigned int precision, unsigned int n)
93 if (n >= precision)
95 num.overflow = !num.unsignedp && !num_zerop (num);
96 num.high = num.low = 0;
98 else
100 cpp_num orig;
101 unsigned int m = n;
103 orig = num;
104 if (m >= PART_PRECISION)
106 m -= PART_PRECISION;
107 num.high = num.low;
108 num.low = 0;
110 if (m)
112 num.high = (num.high << m) | (num.low >> (PART_PRECISION - m));
113 num.low <<= m;
115 num = num_trim (num, precision);
117 if (num.unsignedp)
118 num.overflow = 0;
119 else
121 cpp_num maybe_orig = num_rshift (num, precision, n);
122 num.overflow = !num_eq (orig, maybe_orig);
126 return num;
129 unsigned int precision = 64;
130 unsigned int n = 16;
132 cpp_num num = { 0, 3, 0, 0 };
134 int main()
136 cpp_num res = num_lshift (num, 64, n);
138 if (res.low != 0x30000)
139 abort ();
141 if (res.high != 0)
142 abort ();
144 if (res.overflow != 0)
145 abort ();
147 exit (0);