authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-05 04:20:07-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-01-05 04:20:07-05:00
log97e105489085fcf4530b3944499531d76848bbd1
treeee83bb5d05b3f62c40a8d1c19dc6f543ffb9e3e8
parented21be011a57b6aa48470168315d86b5f93d29ea

fix compiler rt


1 files changed, 262 insertions(+), 263 deletions(-)

std/compiler_rt.zig+262-263
......@@ -1,263 +1,262 @@
1// TODO
2//const CHAR_BIT = 8;
3//const du_int = u64;
4//const di_int = i64;
5//const si_int = c_int;
6//const su_int = c_uint;
7//
8//const udwords = [2]su_int;
9//const low = if (@compileVar("is_big_endian")) 1 else 0;
10//const high = 1 - low;
11//
12//export fn __udivdi3(a: du_int, b: du_int) -> du_int {
13// @setDebugSafety(this, false);
14// return __udivmoddi4(a, b, null);
15//}
16//
17//fn du_int_to_udwords(x: du_int) -> udwords {
18// @setDebugSafety(this, false);
19// return *(&udwords)(&x);
20//}
21//
22//export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
23// @setDebugSafety(this, false);
24//
25// const n_uword_bits = @sizeOf(su_int) * CHAR_BIT;
26// const n_udword_bits = @sizeOf(du_int) * CHAR_BIT;
27// var n = du_int_to_udwords(a);
28// var d = du_int_to_udwords(b);
29// var q: udwords = undefined;
30// var r: udwords = undefined;
31// var sr: c_uint = undefined;
32// // special cases, X is unknown, K != 0
33// if (n[high] == 0) {
34// if (d[high] == 0) {
35// // 0 X
36// // ---
37// // 0 X
38// if (const rem ?= maybe_rem) {
39// *rem = n[low] % d[low];
40// }
41// return n[low] / d[low];
42// }
43// // 0 X
44// // ---
45// // K X
46// if (const rem ?= maybe_rem) {
47// *rem = n[low];
48// }
49// return 0;
50// }
51// // n[high] != 0
52// if (d[low] == 0) {
53// if (d[high] == 0) {
54// // K X
55// // ---
56// // 0 0
57// if (var rem ?= maybe_rem) {
58// *rem = n[high] % d[low];
59// }
60// return n[high] / d[low];
61// }
62// // d[high] != 0
63// if (n[low] == 0) {
64// // K 0
65// // ---
66// // K 0
67// if (var rem ?= maybe_rem) {
68// r[high] = n[high] % d[high];
69// r[low] = 0;
70// *rem = *(&du_int)(&r[0]);
71// }
72// return n[high] / d[high];
73// }
74// // K K
75// // ---
76// // K 0
77// // if d is a power of 2
78// if ((d[high] & (d[high] - 1)) == 0) {
79// if (var rem ?= maybe_rem) {
80// r[low] = n[low];
81// r[high] = n[high] & (d[high] - 1);
82// *rem = *(&du_int)(&r[0]);
83// }
84// return n[high] >> @ctz(@typeOf(d[high]), d[high]);
85// }
86// // K K
87// // ---
88// // K 0
89// sr = @clz(su_int, d[high]) - @clz(su_int, n[high]);
90// // 0 <= sr <= n_uword_bits - 2 or sr large
91// if (sr > n_uword_bits - 2) {
92// if (var rem ?= maybe_rem) {
93// *rem = *(&du_int)(&n[0]);
94// }
95// return 0;
96// }
97// sr += 1;
98// // 1 <= sr <= n_uword_bits - 1
99// // q.all = n.all << (n_udword_bits - sr);
100// q[low] = 0;
101// q[high] = n[low] << (n_uword_bits - sr);
102// // r.all = n.all >> sr;
103// r[high] = n[high] >> sr;
104// r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
105// } else {
106// // d[low] != 0
107// if (d[high] == 0) {
108// // K X
109// // ---
110// // 0 K
111// // if d is a power of 2
112// if ((d[low] & (d[low] - 1)) == 0) {
113// if (var rem ?= maybe_rem) {
114// *rem = n[low] & (d[low] - 1);
115// }
116// if (d[low] == 1) {
117// return *(&du_int)(&n[0]);
118// }
119// sr = @ctz(@typeOf(d[low]), d[low]);
120// q[high] = n[high] >> sr;
121// q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
122// return *(&du_int)(&q[0]);
123// }
124// // K X
125// // ---
126// // 0 K
127// sr = 1 + n_uword_bits + @clz(su_int, d[low]) - @clz(su_int, n[high]);
128// // 2 <= sr <= n_udword_bits - 1
129// // q.all = n.all << (n_udword_bits - sr);
130// // r.all = n.all >> sr;
131// if (sr == n_uword_bits) {
132// q[low] = 0;
133// q[high] = n[low];
134// r[high] = 0;
135// r[low] = n[high];
136// } else if (sr < n_uword_bits) {
137// // 2 <= sr <= n_uword_bits - 1
138// q[low] = 0;
139// q[high] = n[low] << (n_uword_bits - sr);
140// r[high] = n[high] >> sr;
141// r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
142// } else {
143// // n_uword_bits + 1 <= sr <= n_udword_bits - 1
144// q[low] = n[low] << (n_udword_bits - sr);
145// q[high] = (n[high] << (n_udword_bits - sr)) |
146// (n[low] >> (sr - n_uword_bits));
147// r[high] = 0;
148// r[low] = n[high] >> (sr - n_uword_bits);
149// }
150// } else {
151// // K X
152// // ---
153// // K K
154// sr = @clz(su_int, d[high]) - @clz(su_int, n[high]);
155// // 0 <= sr <= n_uword_bits - 1 or sr large
156// if (sr > n_uword_bits - 1) {
157// if (var rem ?= maybe_rem) {
158// *rem = *(&du_int)(&n[0]);
159// }
160// return 0;
161// }
162// sr += 1;
163// // 1 <= sr <= n_uword_bits
164// // q.all = n.all << (n_udword_bits - sr);
165// q[low] = 0;
166// if (sr == n_uword_bits) {
167// q[high] = n[low];
168// r[high] = 0;
169// r[low] = n[high];
170// } else {
171// q[high] = n[low] << (n_uword_bits - sr);
172// r[high] = n[high] >> sr;
173// r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
174// }
175// }
176// }
177// // Not a special case
178// // q and r are initialized with:
179// // q.all = n.all << (n_udword_bits - sr);
180// // r.all = n.all >> sr;
181// // 1 <= sr <= n_udword_bits - 1
182// var carry: su_int = 0;
183// while (sr > 0) {
184// // r:q = ((r:q) << 1) | carry
185// r[high] = (r[high] << 1) | (r[low] >> (n_uword_bits - 1));
186// r[low] = (r[low] << 1) | (q[high] >> (n_uword_bits - 1));
187// q[high] = (q[high] << 1) | (q[low] >> (n_uword_bits - 1));
188// q[low] = (q[low] << 1) | carry;
189// // carry = 0;
190// // if (r.all >= d.all)
191// // {
192// // r.all -= d.all;
193// // carry = 1;
194// // }
195// const s: di_int = (di_int)(*(&du_int)(&d[0]) - *(&du_int)(&r[0]) - 1) >> (n_udword_bits - 1);
196// carry = su_int(s & 1);
197// *(&du_int)(&r[0]) -= *(&du_int)(&d[0]) & u64(s);
198//
199// sr -= 1;
200// }
201// *(&du_int)(&q[0]) = (*(&du_int)(&q[0]) << 1) | u64(carry);
202// if (var rem ?= maybe_rem) {
203// *rem = *(&du_int)(&r[0]);
204// }
205// return *(&du_int)(&q[0]);
206//}
207//
208//export fn __umoddi3(a: du_int, b: du_int) -> du_int {
209// @setDebugSafety(this, false);
210//
211// var r: du_int = undefined;
212// __udivmoddi4(a, b, &r);
213// return r;
214//}
215//
216//fn test_umoddi3() {
217// @setFnTest(this);
218//
219// test_one_umoddi3(0, 1, 0);
220// test_one_umoddi3(2, 1, 0);
221// test_one_umoddi3(0x8000000000000000, 1, 0x0);
222// test_one_umoddi3(0x8000000000000000, 2, 0x0);
223// test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1);
224//}
225//
226//fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) {
227// const r = __umoddi3(a, b);
228// assert(r == expected_r);
229//}
230//
231//fn test_udivmoddi4() {
232// @setFnTest(this);
233//
234// const cases = [][4]du_int {
235// []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},
236// []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000},
237// []du_int{0x7FFFFFFF00000001, 0x0000000000000001, 0x7FFFFFFF00000001, 0x0000000000000000},
238// []du_int{0x7FFFFFFF7FFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000, 0x7FFFFFFF7FFFFFFF},
239// []du_int{0x8000000000000002, 0xFFFFFFFFFFFFFFFE, 0x0000000000000000, 0x8000000000000002},
240// []du_int{0x80000000FFFFFFFD, 0xFFFFFFFFFFFFFFFD, 0x0000000000000000, 0x80000000FFFFFFFD},
241// []du_int{0xFFFFFFFD00000010, 0xFFFFFFFF80000000, 0x0000000000000000, 0xFFFFFFFD00000010},
242// []du_int{0xFFFFFFFDFFFFFFFF, 0xFFFFFFFF7FFFFFFF, 0x0000000000000000, 0xFFFFFFFDFFFFFFFF},
243// []du_int{0xFFFFFFFE0747AE14, 0xFFFFFFFF0747AE14, 0x0000000000000000, 0xFFFFFFFE0747AE14},
244// []du_int{0xFFFFFFFF00000001, 0xFFFFFFFF078644FA, 0x0000000000000000, 0xFFFFFFFF00000001},
245// []du_int{0xFFFFFFFF80000000, 0xFFFFFFFF00000010, 0x0000000000000001, 0x000000007FFFFFF0},
246// []du_int{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000},
247// };
248//
249// for (cases) |case| {
250// test_one_udivmoddi4(case[0], case[1], case[2], case[3]);
251// }
252//}
253//
254//fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_int) {
255// var r: du_int = undefined;
256// const q = __udivmoddi4(a, b, &r);
257// assert(q == expected_q);
258// assert(r == expected_r);
259//}
260//
261//fn assert(b: bool) {
262// if (!b) @unreachable();
263//}
1const CHAR_BIT = 8;
2const du_int = u64;
3const di_int = i64;
4const si_int = c_int;
5const su_int = c_uint;
6
7const udwords = [2]su_int;
8const low = if (@compileVar("is_big_endian")) 1 else 0;
9const high = 1 - low;
10
11export fn __udivdi3(a: du_int, b: du_int) -> du_int {
12 @setDebugSafety(this, false);
13 return __udivmoddi4(a, b, null);
14}
15
16fn du_int_to_udwords(x: du_int) -> udwords {
17 @setDebugSafety(this, false);
18 return *(&udwords)(&x);
19}
20
21export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int {
22 @setDebugSafety(this, false);
23
24 const n_uword_bits = @sizeOf(su_int) * CHAR_BIT;
25 const n_udword_bits = @sizeOf(du_int) * CHAR_BIT;
26 var n = du_int_to_udwords(a);
27 var d = du_int_to_udwords(b);
28 var q: udwords = undefined;
29 var r: udwords = undefined;
30 var sr: c_uint = undefined;
31 // special cases, X is unknown, K != 0
32 if (n[high] == 0) {
33 if (d[high] == 0) {
34 // 0 X
35 // ---
36 // 0 X
37 if (const rem ?= maybe_rem) {
38 *rem = n[low] % d[low];
39 }
40 return n[low] / d[low];
41 }
42 // 0 X
43 // ---
44 // K X
45 if (const rem ?= maybe_rem) {
46 *rem = n[low];
47 }
48 return 0;
49 }
50 // n[high] != 0
51 if (d[low] == 0) {
52 if (d[high] == 0) {
53 // K X
54 // ---
55 // 0 0
56 if (var rem ?= maybe_rem) {
57 *rem = n[high] % d[low];
58 }
59 return n[high] / d[low];
60 }
61 // d[high] != 0
62 if (n[low] == 0) {
63 // K 0
64 // ---
65 // K 0
66 if (var rem ?= maybe_rem) {
67 r[high] = n[high] % d[high];
68 r[low] = 0;
69 *rem = *(&du_int)(&r[0]);
70 }
71 return n[high] / d[high];
72 }
73 // K K
74 // ---
75 // K 0
76 // if d is a power of 2
77 if ((d[high] & (d[high] - 1)) == 0) {
78 if (var rem ?= maybe_rem) {
79 r[low] = n[low];
80 r[high] = n[high] & (d[high] - 1);
81 *rem = *(&du_int)(&r[0]);
82 }
83 return n[high] >> @ctz(d[high]);
84 }
85 // K K
86 // ---
87 // K 0
88 sr = @clz(su_int(d[high])) - @clz(su_int(n[high]));
89 // 0 <= sr <= n_uword_bits - 2 or sr large
90 if (sr > n_uword_bits - 2) {
91 if (var rem ?= maybe_rem) {
92 *rem = *(&du_int)(&n[0]);
93 }
94 return 0;
95 }
96 sr += 1;
97 // 1 <= sr <= n_uword_bits - 1
98 // q.all = n.all << (n_udword_bits - sr);
99 q[low] = 0;
100 q[high] = n[low] << (n_uword_bits - sr);
101 // r.all = n.all >> sr;
102 r[high] = n[high] >> sr;
103 r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
104 } else {
105 // d[low] != 0
106 if (d[high] == 0) {
107 // K X
108 // ---
109 // 0 K
110 // if d is a power of 2
111 if ((d[low] & (d[low] - 1)) == 0) {
112 if (var rem ?= maybe_rem) {
113 *rem = n[low] & (d[low] - 1);
114 }
115 if (d[low] == 1) {
116 return *(&du_int)(&n[0]);
117 }
118 sr = @ctz(d[low]);
119 q[high] = n[high] >> sr;
120 q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
121 return *(&du_int)(&q[0]);
122 }
123 // K X
124 // ---
125 // 0 K
126 sr = 1 + n_uword_bits + @clz(su_int(d[low])) - @clz(su_int(n[high]));
127 // 2 <= sr <= n_udword_bits - 1
128 // q.all = n.all << (n_udword_bits - sr);
129 // r.all = n.all >> sr;
130 if (sr == n_uword_bits) {
131 q[low] = 0;
132 q[high] = n[low];
133 r[high] = 0;
134 r[low] = n[high];
135 } else if (sr < n_uword_bits) {
136 // 2 <= sr <= n_uword_bits - 1
137 q[low] = 0;
138 q[high] = n[low] << (n_uword_bits - sr);
139 r[high] = n[high] >> sr;
140 r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
141 } else {
142 // n_uword_bits + 1 <= sr <= n_udword_bits - 1
143 q[low] = n[low] << (n_udword_bits - sr);
144 q[high] = (n[high] << (n_udword_bits - sr)) |
145 (n[low] >> (sr - n_uword_bits));
146 r[high] = 0;
147 r[low] = n[high] >> (sr - n_uword_bits);
148 }
149 } else {
150 // K X
151 // ---
152 // K K
153 sr = @clz(su_int(d[high])) - @clz(su_int(n[high]));
154 // 0 <= sr <= n_uword_bits - 1 or sr large
155 if (sr > n_uword_bits - 1) {
156 if (var rem ?= maybe_rem) {
157 *rem = *(&du_int)(&n[0]);
158 }
159 return 0;
160 }
161 sr += 1;
162 // 1 <= sr <= n_uword_bits
163 // q.all = n.all << (n_udword_bits - sr);
164 q[low] = 0;
165 if (sr == n_uword_bits) {
166 q[high] = n[low];
167 r[high] = 0;
168 r[low] = n[high];
169 } else {
170 q[high] = n[low] << (n_uword_bits - sr);
171 r[high] = n[high] >> sr;
172 r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr);
173 }
174 }
175 }
176 // Not a special case
177 // q and r are initialized with:
178 // q.all = n.all << (n_udword_bits - sr);
179 // r.all = n.all >> sr;
180 // 1 <= sr <= n_udword_bits - 1
181 var carry: su_int = 0;
182 while (sr > 0) {
183 // r:q = ((r:q) << 1) | carry
184 r[high] = (r[high] << 1) | (r[low] >> (n_uword_bits - 1));
185 r[low] = (r[low] << 1) | (q[high] >> (n_uword_bits - 1));
186 q[high] = (q[high] << 1) | (q[low] >> (n_uword_bits - 1));
187 q[low] = (q[low] << 1) | carry;
188 // carry = 0;
189 // if (r.all >= d.all)
190 // {
191 // r.all -= d.all;
192 // carry = 1;
193 // }
194 const s: di_int = (di_int)(*(&du_int)(&d[0]) - *(&du_int)(&r[0]) - 1) >> (n_udword_bits - 1);
195 carry = su_int(s & 1);
196 *(&du_int)(&r[0]) -= *(&du_int)(&d[0]) & u64(s);
197
198 sr -= 1;
199 }
200 *(&du_int)(&q[0]) = (*(&du_int)(&q[0]) << 1) | u64(carry);
201 if (var rem ?= maybe_rem) {
202 *rem = *(&du_int)(&r[0]);
203 }
204 return *(&du_int)(&q[0]);
205}
206
207export fn __umoddi3(a: du_int, b: du_int) -> du_int {
208 @setDebugSafety(this, false);
209
210 var r: du_int = undefined;
211 __udivmoddi4(a, b, &r);
212 return r;
213}
214
215fn test_umoddi3() {
216 @setFnTest(this);
217
218 test_one_umoddi3(0, 1, 0);
219 test_one_umoddi3(2, 1, 0);
220 test_one_umoddi3(0x8000000000000000, 1, 0x0);
221 test_one_umoddi3(0x8000000000000000, 2, 0x0);
222 test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1);
223}
224
225fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) {
226 const r = __umoddi3(a, b);
227 assert(r == expected_r);
228}
229
230fn test_udivmoddi4() {
231 @setFnTest(this);
232
233 const cases = [][4]du_int {
234 []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000},
235 []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000},
236 []du_int{0x7FFFFFFF00000001, 0x0000000000000001, 0x7FFFFFFF00000001, 0x0000000000000000},
237 []du_int{0x7FFFFFFF7FFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000, 0x7FFFFFFF7FFFFFFF},
238 []du_int{0x8000000000000002, 0xFFFFFFFFFFFFFFFE, 0x0000000000000000, 0x8000000000000002},
239 []du_int{0x80000000FFFFFFFD, 0xFFFFFFFFFFFFFFFD, 0x0000000000000000, 0x80000000FFFFFFFD},
240 []du_int{0xFFFFFFFD00000010, 0xFFFFFFFF80000000, 0x0000000000000000, 0xFFFFFFFD00000010},
241 []du_int{0xFFFFFFFDFFFFFFFF, 0xFFFFFFFF7FFFFFFF, 0x0000000000000000, 0xFFFFFFFDFFFFFFFF},
242 []du_int{0xFFFFFFFE0747AE14, 0xFFFFFFFF0747AE14, 0x0000000000000000, 0xFFFFFFFE0747AE14},
243 []du_int{0xFFFFFFFF00000001, 0xFFFFFFFF078644FA, 0x0000000000000000, 0xFFFFFFFF00000001},
244 []du_int{0xFFFFFFFF80000000, 0xFFFFFFFF00000010, 0x0000000000000001, 0x000000007FFFFFF0},
245 []du_int{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000},
246 };
247
248 for (cases) |case| {
249 test_one_udivmoddi4(case[0], case[1], case[2], case[3]);
250 }
251}
252
253fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_int) {
254 var r: du_int = undefined;
255 const q = __udivmoddi4(a, b, &r);
256 assert(q == expected_q);
257 assert(r == expected_r);
258}
259
260fn assert(b: bool) {
261 if (!b) @unreachable();
262}