1 /* PR 16341 */
2 /* { dg-require-effective-target int32plus } */
3 
4 #define PART_PRECISION (sizeof (cpp_num_part) * 8)
5 
6 typedef unsigned int cpp_num_part;
7 typedef struct cpp_num cpp_num;
8 struct cpp_num
9 {
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.  */
14 };
15 
16 static  int
num_positive(cpp_num num,unsigned int precision)17 num_positive (cpp_num num, unsigned int precision)
18 {
19    if (precision > PART_PRECISION)
20      {
21        precision -= PART_PRECISION;
22        return (num.high & (cpp_num_part) 1 << (precision - 1)) == 0;
23      }
24 
25    return (num.low & (cpp_num_part) 1 << (precision - 1)) == 0;
26 }
27 
28 static cpp_num
num_trim(cpp_num num,unsigned int precision)29 num_trim (cpp_num num, unsigned int precision)
30 {
31    if (precision > PART_PRECISION)
32      {
33        precision -= PART_PRECISION;
34        if (precision < PART_PRECISION)
35          num.high &= ((cpp_num_part) 1 << precision) - 1;
36      }
37    else
38      {
39        if (precision < PART_PRECISION)
40          num.low &= ((cpp_num_part) 1 << precision) - 1;
41        num.high = 0;
42      }
43 
44    return num;
45 }
46 
47 /* Shift NUM, of width PRECISION, right by N bits.  */
48 static cpp_num
num_rshift(cpp_num num,unsigned int precision,unsigned int n)49 num_rshift (cpp_num num, unsigned int precision, unsigned int n)
50 {
51    cpp_num_part sign_mask;
52    int x = num_positive (num, precision);
53 
54    if (num.unsignedp || x)
55      sign_mask = 0;
56    else
57      sign_mask = ~(cpp_num_part) 0;
58 
59    if (n >= precision)
60      num.high = num.low = sign_mask;
61    else
62      {
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);
68 
69        if (n >= PART_PRECISION)
70          {
71            n -= PART_PRECISION;
72            num.low = num.high;
73            num.high = sign_mask;
74          }
75 
76        if (n)
77          {
78            num.low = (num.low >> n) | (num.high << (PART_PRECISION - n));
79            num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n));
80          }
81      }
82 
83    num = num_trim (num, precision);
84    num.overflow = 0;
85    return num;
86 }
87                               #define num_zerop(num) ((num.low | num.high) == 0)
88 #define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
89 
90 cpp_num
num_lshift(cpp_num num,unsigned int precision,unsigned int n)91 num_lshift (cpp_num num, unsigned int precision, unsigned int n)
92 {
93    if (n >= precision)
94      {
95        num.overflow = !num.unsignedp && !num_zerop (num);
96        num.high = num.low = 0;
97      }
98    else
99      {
100        cpp_num orig;
101        unsigned int m = n;
102 
103        orig = num;
104        if (m >= PART_PRECISION)
105          {
106            m -= PART_PRECISION;
107            num.high = num.low;
108            num.low = 0;
109          }
110        if (m)
111          {
112            num.high = (num.high << m) | (num.low >> (PART_PRECISION - m));
113            num.low <<= m;
114          }
115        num = num_trim (num, precision);
116 
117        if (num.unsignedp)
118          num.overflow = 0;
119        else
120          {
121            cpp_num maybe_orig = num_rshift (num, precision, n);
122            num.overflow = !num_eq (orig, maybe_orig);
123          }
124      }
125 
126    return num;
127 }
128 
129 unsigned int precision = 64;
130 unsigned int n = 16;
131 
132 cpp_num num = { 0, 3, 0, 0 };
133 
main()134 int main()
135 {
136    cpp_num res = num_lshift (num, 64, n);
137 
138    if (res.low != 0x30000)
139      abort ();
140 
141    if (res.high != 0)
142      abort ();
143 
144    if (res.overflow != 0)
145      abort ();
146 
147    exit (0);
148 }
149