| author | |
| committer | |
| log | cf46cd5f2b0f87430185c5d89056321d16f42d58 |
| tree | 1fb55a248604b229b06d078d164810d9a8b31db2 |
| parent | 38f898e9c74df3b25e1443273b19bc91e732798c |
4 files changed, 528 insertions(+), 515 deletions(-)
CMakeLists.txt+1-1| ... | ... | @@ -311,7 +311,7 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/special/bootstrap.zig" DESTINATION "${ZIG |
| 311 | 311 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_file_template.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 312 | 312 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/build_runner.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 313 | 313 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/builtin.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 314 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}/special") | |
| 314 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/compiler_rt/index.zig" DESTINATION "${ZIG_STD_DEST}/special/compiler_rt") | |
| 315 | 315 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/test_runner.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 316 | 316 | install(FILES "${CMAKE_SOURCE_DIR}/std/special/zigrt.zig" DESTINATION "${ZIG_STD_DEST}/special") |
| 317 | 317 |
src/link.cpp+20-7| ... | ... | @@ -31,11 +31,7 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) { |
| 31 | 31 | return buf_ptr(out_buf); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | static Buf *build_o(CodeGen *parent_gen, const char *oname) { | |
| 35 | Buf *source_basename = buf_sprintf("%s.zig", oname); | |
| 36 | Buf *full_path = buf_alloc(); | |
| 37 | os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path); | |
| 38 | ||
| 34 | static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) { | |
| 39 | 35 | ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; |
| 40 | 36 | CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode); |
| 41 | 37 | |
| ... | ... | @@ -65,6 +61,23 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) { |
| 65 | 61 | return output_path; |
| 66 | 62 | } |
| 67 | 63 | |
| 64 | static Buf *build_o(CodeGen *parent_gen, const char *oname) { | |
| 65 | Buf *source_basename = buf_sprintf("%s.zig", oname); | |
| 66 | Buf *full_path = buf_alloc(); | |
| 67 | os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path); | |
| 68 | ||
| 69 | return build_o_raw(parent_gen, oname, full_path); | |
| 70 | } | |
| 71 | ||
| 72 | static Buf *build_compiler_rt(CodeGen *parent_gen) { | |
| 73 | Buf *dir_path = buf_alloc(); | |
| 74 | os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("compiler_rt"), dir_path); | |
| 75 | Buf *full_path = buf_alloc(); | |
| 76 | os_path_join(dir_path, buf_create_from_str("index.zig"), full_path); | |
| 77 | ||
| 78 | return build_o_raw(parent_gen, "compiler_rt", full_path); | |
| 79 | } | |
| 80 | ||
| 68 | 81 | static const char *get_exe_file_extension(CodeGen *g) { |
| 69 | 82 | if (g->zig_target.os == ZigLLVM_Win32) { |
| 70 | 83 | return ".exe"; |
| ... | ... | @@ -263,7 +276,7 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 263 | 276 | Buf *builtin_o_path = build_o(g, "builtin"); |
| 264 | 277 | lj->args.append(buf_ptr(builtin_o_path)); |
| 265 | 278 | |
| 266 | Buf *compiler_rt_o_path = build_o(g, "compiler_rt"); | |
| 279 | Buf *compiler_rt_o_path = build_compiler_rt(g); | |
| 267 | 280 | lj->args.append(buf_ptr(compiler_rt_o_path)); |
| 268 | 281 | } |
| 269 | 282 | |
| ... | ... | @@ -401,7 +414,7 @@ static void construct_linker_job_coff(LinkJob *lj) { |
| 401 | 414 | Buf *builtin_o_path = build_o(g, "builtin"); |
| 402 | 415 | lj->args.append(buf_ptr(builtin_o_path)); |
| 403 | 416 | |
| 404 | Buf *compiler_rt_o_path = build_o(g, "compiler_rt"); | |
| 417 | Buf *compiler_rt_o_path = build_compiler_rt(g); | |
| 405 | 418 | lj->args.append(buf_ptr(compiler_rt_o_path)); |
| 406 | 419 | } |
| 407 | 420 |
std/special/compiler_rt.zig deleted-507| ... | ... | @@ -1,507 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | const CHAR_BIT = 8; | |
| 4 | const du_int = u64; | |
| 5 | const di_int = i64; | |
| 6 | const si_int = c_int; | |
| 7 | const su_int = c_uint; | |
| 8 | ||
| 9 | const udwords = [2]su_int; | |
| 10 | const low = if (builtin.is_big_endian) 1 else 0; | |
| 11 | const high = 1 - low; | |
| 12 | ||
| 13 | export fn __udivdi3(a: du_int, b: du_int) -> du_int { | |
| 14 | @setDebugSafety(this, false); | |
| 15 | return __udivmoddi4(a, b, null); | |
| 16 | } | |
| 17 | ||
| 18 | fn du_int_to_udwords(x: du_int) -> udwords { | |
| 19 | @setDebugSafety(this, false); | |
| 20 | return *@ptrCast(&udwords, &x); | |
| 21 | } | |
| 22 | ||
| 23 | export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { | |
| 24 | @setDebugSafety(this, false); | |
| 25 | ||
| 26 | const n_uword_bits = @sizeOf(su_int) * CHAR_BIT; | |
| 27 | const n_udword_bits = @sizeOf(du_int) * CHAR_BIT; | |
| 28 | var n = du_int_to_udwords(a); | |
| 29 | var d = du_int_to_udwords(b); | |
| 30 | var q: udwords = undefined; | |
| 31 | var r: udwords = undefined; | |
| 32 | var sr: c_uint = undefined; | |
| 33 | // special cases, X is unknown, K != 0 | |
| 34 | if (n[high] == 0) { | |
| 35 | if (d[high] == 0) { | |
| 36 | // 0 X | |
| 37 | // --- | |
| 38 | // 0 X | |
| 39 | if (maybe_rem) |rem| { | |
| 40 | *rem = n[low] % d[low]; | |
| 41 | } | |
| 42 | return n[low] / d[low]; | |
| 43 | } | |
| 44 | // 0 X | |
| 45 | // --- | |
| 46 | // K X | |
| 47 | if (maybe_rem) |rem| { | |
| 48 | *rem = n[low]; | |
| 49 | } | |
| 50 | return 0; | |
| 51 | } | |
| 52 | // n[high] != 0 | |
| 53 | if (d[low] == 0) { | |
| 54 | if (d[high] == 0) { | |
| 55 | // K X | |
| 56 | // --- | |
| 57 | // 0 0 | |
| 58 | if (maybe_rem) |rem| { | |
| 59 | *rem = n[high] % d[low]; | |
| 60 | } | |
| 61 | return n[high] / d[low]; | |
| 62 | } | |
| 63 | // d[high] != 0 | |
| 64 | if (n[low] == 0) { | |
| 65 | // K 0 | |
| 66 | // --- | |
| 67 | // K 0 | |
| 68 | if (maybe_rem) |rem| { | |
| 69 | r[high] = n[high] % d[high]; | |
| 70 | r[low] = 0; | |
| 71 | *rem = *@ptrCast(&du_int, &r[0]); | |
| 72 | } | |
| 73 | return n[high] / d[high]; | |
| 74 | } | |
| 75 | // K K | |
| 76 | // --- | |
| 77 | // K 0 | |
| 78 | // if d is a power of 2 | |
| 79 | if ((d[high] & (d[high] - 1)) == 0) { | |
| 80 | if (maybe_rem) |rem| { | |
| 81 | r[low] = n[low]; | |
| 82 | r[high] = n[high] & (d[high] - 1); | |
| 83 | *rem = *@ptrCast(&du_int, &r[0]); | |
| 84 | } | |
| 85 | return n[high] >> @ctz(d[high]); | |
| 86 | } | |
| 87 | // K K | |
| 88 | // --- | |
| 89 | // K 0 | |
| 90 | sr = @clz(su_int(d[high])) - @clz(su_int(n[high])); | |
| 91 | // 0 <= sr <= n_uword_bits - 2 or sr large | |
| 92 | if (sr > n_uword_bits - 2) { | |
| 93 | if (maybe_rem) |rem| { | |
| 94 | *rem = *@ptrCast(&du_int, &n[0]); | |
| 95 | } | |
| 96 | return 0; | |
| 97 | } | |
| 98 | sr += 1; | |
| 99 | // 1 <= sr <= n_uword_bits - 1 | |
| 100 | // q.all = n.all << (n_udword_bits - sr); | |
| 101 | q[low] = 0; | |
| 102 | q[high] = n[low] << (n_uword_bits - sr); | |
| 103 | // r.all = n.all >> sr; | |
| 104 | r[high] = n[high] >> sr; | |
| 105 | r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); | |
| 106 | } else { | |
| 107 | // d[low] != 0 | |
| 108 | if (d[high] == 0) { | |
| 109 | // K X | |
| 110 | // --- | |
| 111 | // 0 K | |
| 112 | // if d is a power of 2 | |
| 113 | if ((d[low] & (d[low] - 1)) == 0) { | |
| 114 | if (maybe_rem) |rem| { | |
| 115 | *rem = n[low] & (d[low] - 1); | |
| 116 | } | |
| 117 | if (d[low] == 1) { | |
| 118 | return *@ptrCast(&du_int, &n[0]); | |
| 119 | } | |
| 120 | sr = @ctz(d[low]); | |
| 121 | q[high] = n[high] >> sr; | |
| 122 | q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); | |
| 123 | return *@ptrCast(&du_int, &q[0]); | |
| 124 | } | |
| 125 | // K X | |
| 126 | // --- | |
| 127 | // 0 K | |
| 128 | sr = 1 + n_uword_bits + @clz(su_int(d[low])) - @clz(su_int(n[high])); | |
| 129 | // 2 <= sr <= n_udword_bits - 1 | |
| 130 | // q.all = n.all << (n_udword_bits - sr); | |
| 131 | // r.all = n.all >> sr; | |
| 132 | if (sr == n_uword_bits) { | |
| 133 | q[low] = 0; | |
| 134 | q[high] = n[low]; | |
| 135 | r[high] = 0; | |
| 136 | r[low] = n[high]; | |
| 137 | } else if (sr < n_uword_bits) { | |
| 138 | // 2 <= sr <= n_uword_bits - 1 | |
| 139 | q[low] = 0; | |
| 140 | q[high] = n[low] << (n_uword_bits - sr); | |
| 141 | r[high] = n[high] >> sr; | |
| 142 | r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); | |
| 143 | } else { | |
| 144 | // n_uword_bits + 1 <= sr <= n_udword_bits - 1 | |
| 145 | q[low] = n[low] << (n_udword_bits - sr); | |
| 146 | q[high] = (n[high] << (n_udword_bits - sr)) | | |
| 147 | (n[low] >> (sr - n_uword_bits)); | |
| 148 | r[high] = 0; | |
| 149 | r[low] = n[high] >> (sr - n_uword_bits); | |
| 150 | } | |
| 151 | } else { | |
| 152 | // K X | |
| 153 | // --- | |
| 154 | // K K | |
| 155 | sr = @clz(su_int(d[high])) - @clz(su_int(n[high])); | |
| 156 | // 0 <= sr <= n_uword_bits - 1 or sr large | |
| 157 | if (sr > n_uword_bits - 1) { | |
| 158 | if (maybe_rem) |rem| { | |
| 159 | *rem = *@ptrCast(&du_int, &n[0]); | |
| 160 | } | |
| 161 | return 0; | |
| 162 | } | |
| 163 | sr += 1; | |
| 164 | // 1 <= sr <= n_uword_bits | |
| 165 | // q.all = n.all << (n_udword_bits - sr); | |
| 166 | q[low] = 0; | |
| 167 | if (sr == n_uword_bits) { | |
| 168 | q[high] = n[low]; | |
| 169 | r[high] = 0; | |
| 170 | r[low] = n[high]; | |
| 171 | } else { | |
| 172 | q[high] = n[low] << (n_uword_bits - sr); | |
| 173 | r[high] = n[high] >> sr; | |
| 174 | r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); | |
| 175 | } | |
| 176 | } | |
| 177 | } | |
| 178 | // Not a special case | |
| 179 | // q and r are initialized with: | |
| 180 | // q.all = n.all << (n_udword_bits - sr); | |
| 181 | // r.all = n.all >> sr; | |
| 182 | // 1 <= sr <= n_udword_bits - 1 | |
| 183 | var carry: su_int = 0; | |
| 184 | while (sr > 0) { | |
| 185 | // r:q = ((r:q) << 1) | carry | |
| 186 | r[high] = (r[high] << 1) | (r[low] >> (n_uword_bits - 1)); | |
| 187 | r[low] = (r[low] << 1) | (q[high] >> (n_uword_bits - 1)); | |
| 188 | q[high] = (q[high] << 1) | (q[low] >> (n_uword_bits - 1)); | |
| 189 | q[low] = (q[low] << 1) | carry; | |
| 190 | // carry = 0; | |
| 191 | // if (r.all >= d.all) | |
| 192 | // { | |
| 193 | // r.all -= d.all; | |
| 194 | // carry = 1; | |
| 195 | // } | |
| 196 | const s: di_int = (di_int)(*@ptrCast(&du_int, &d[0]) - *@ptrCast(&du_int, &r[0]) - 1) >> (n_udword_bits - 1); | |
| 197 | carry = su_int(s & 1); | |
| 198 | *@ptrCast(&du_int, &r[0]) -= *@ptrCast(&du_int, &d[0]) & u64(s); | |
| 199 | ||
| 200 | sr -= 1; | |
| 201 | } | |
| 202 | *@ptrCast(&du_int, &q[0]) = (*@ptrCast(&du_int, &q[0]) << 1) | u64(carry); | |
| 203 | if (maybe_rem) |rem| { | |
| 204 | *rem = *@ptrCast(&du_int, &r[0]); | |
| 205 | } | |
| 206 | return *@ptrCast(&du_int, &q[0]); | |
| 207 | } | |
| 208 | ||
| 209 | export fn __umoddi3(a: du_int, b: du_int) -> du_int { | |
| 210 | @setDebugSafety(this, false); | |
| 211 | ||
| 212 | var r: du_int = undefined; | |
| 213 | _ = __udivmoddi4(a, b, &r); | |
| 214 | return r; | |
| 215 | } | |
| 216 | ||
| 217 | fn isArmArch() -> bool { | |
| 218 | return switch (builtin.arch) { | |
| 219 | builtin.Arch.armv8_2a, | |
| 220 | builtin.Arch.armv8_1a, | |
| 221 | builtin.Arch.armv8, | |
| 222 | builtin.Arch.armv8m_baseline, | |
| 223 | builtin.Arch.armv8m_mainline, | |
| 224 | builtin.Arch.armv7, | |
| 225 | builtin.Arch.armv7em, | |
| 226 | builtin.Arch.armv7m, | |
| 227 | builtin.Arch.armv7s, | |
| 228 | builtin.Arch.armv7k, | |
| 229 | builtin.Arch.armv6, | |
| 230 | builtin.Arch.armv6m, | |
| 231 | builtin.Arch.armv6k, | |
| 232 | builtin.Arch.armv6t2, | |
| 233 | builtin.Arch.armv5, | |
| 234 | builtin.Arch.armv5te, | |
| 235 | builtin.Arch.armv4t, | |
| 236 | builtin.Arch.armeb => true, | |
| 237 | else => false, | |
| 238 | }; | |
| 239 | } | |
| 240 | ||
| 241 | export nakedcc fn __aeabi_uidivmod() { | |
| 242 | @setDebugSafety(this, false); | |
| 243 | ||
| 244 | if (comptime isArmArch()) { | |
| 245 | asm volatile ( | |
| 246 | \\ push { lr } | |
| 247 | \\ sub sp, sp, #4 | |
| 248 | \\ mov r2, sp | |
| 249 | \\ bl __udivmodsi4 | |
| 250 | \\ ldr r1, [sp] | |
| 251 | \\ add sp, sp, #4 | |
| 252 | \\ pop { pc } | |
| 253 | ::: "r2", "r1"); | |
| 254 | unreachable; | |
| 255 | } | |
| 256 | ||
| 257 | @setGlobalLinkage(__aeabi_uidivmod, builtin.GlobalLinkage.Internal); | |
| 258 | } | |
| 259 | ||
| 260 | export fn __udivmodsi4(a: su_int, b: su_int, rem: &su_int) -> su_int { | |
| 261 | @setDebugSafety(this, false); | |
| 262 | ||
| 263 | const d = __udivsi3(a, b); | |
| 264 | *rem = su_int(si_int(a) -% (si_int(d) * si_int(b))); | |
| 265 | return d; | |
| 266 | } | |
| 267 | ||
| 268 | ||
| 269 | // TODO make this an alias instead of an extra function call | |
| 270 | // https://github.com/andrewrk/zig/issues/256 | |
| 271 | ||
| 272 | export fn __aeabi_uidiv(n: su_int, d: su_int) -> su_int { | |
| 273 | @setDebugSafety(this, false); | |
| 274 | ||
| 275 | return __udivsi3(n, d); | |
| 276 | } | |
| 277 | ||
| 278 | export fn __udivsi3(n: su_int, d: su_int) -> su_int { | |
| 279 | @setDebugSafety(this, false); | |
| 280 | ||
| 281 | const n_uword_bits: c_uint = @sizeOf(su_int) * CHAR_BIT; | |
| 282 | // special cases | |
| 283 | if (d == 0) | |
| 284 | return 0; // ?! | |
| 285 | if (n == 0) | |
| 286 | return 0; | |
| 287 | var sr: c_uint = @clz(d) - @clz(n); | |
| 288 | // 0 <= sr <= n_uword_bits - 1 or sr large | |
| 289 | if (sr > n_uword_bits - 1) // d > r | |
| 290 | return 0; | |
| 291 | if (sr == n_uword_bits - 1) // d == 1 | |
| 292 | return n; | |
| 293 | sr += 1; | |
| 294 | // 1 <= sr <= n_uword_bits - 1 | |
| 295 | // Not a special case | |
| 296 | var q: su_int = n << (n_uword_bits - sr); | |
| 297 | var r: su_int = n >> sr; | |
| 298 | var carry: su_int = 0; | |
| 299 | while (sr > 0) : (sr -= 1) { | |
| 300 | // r:q = ((r:q) << 1) | carry | |
| 301 | r = (r << 1) | (q >> (n_uword_bits - 1)); | |
| 302 | q = (q << 1) | carry; | |
| 303 | // carry = 0; | |
| 304 | // if (r.all >= d.all) | |
| 305 | // { | |
| 306 | // r.all -= d.all; | |
| 307 | // carry = 1; | |
| 308 | // } | |
| 309 | const s = si_int(d - r - 1) >> si_int(n_uword_bits - 1); | |
| 310 | carry = su_int(s & 1); | |
| 311 | r -= d & su_int(s); | |
| 312 | } | |
| 313 | q = (q << 1) | carry; | |
| 314 | return q; | |
| 315 | } | |
| 316 | ||
| 317 | test "test_umoddi3" { | |
| 318 | test_one_umoddi3(0, 1, 0); | |
| 319 | test_one_umoddi3(2, 1, 0); | |
| 320 | test_one_umoddi3(0x8000000000000000, 1, 0x0); | |
| 321 | test_one_umoddi3(0x8000000000000000, 2, 0x0); | |
| 322 | test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1); | |
| 323 | } | |
| 324 | ||
| 325 | fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) { | |
| 326 | const r = __umoddi3(a, b); | |
| 327 | assert(r == expected_r); | |
| 328 | } | |
| 329 | ||
| 330 | test "test_udivmoddi4" { | |
| 331 | const cases = [][4]du_int { | |
| 332 | []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000}, | |
| 333 | []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000}, | |
| 334 | []du_int{0x7FFFFFFF00000001, 0x0000000000000001, 0x7FFFFFFF00000001, 0x0000000000000000}, | |
| 335 | []du_int{0x7FFFFFFF7FFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000, 0x7FFFFFFF7FFFFFFF}, | |
| 336 | []du_int{0x8000000000000002, 0xFFFFFFFFFFFFFFFE, 0x0000000000000000, 0x8000000000000002}, | |
| 337 | []du_int{0x80000000FFFFFFFD, 0xFFFFFFFFFFFFFFFD, 0x0000000000000000, 0x80000000FFFFFFFD}, | |
| 338 | []du_int{0xFFFFFFFD00000010, 0xFFFFFFFF80000000, 0x0000000000000000, 0xFFFFFFFD00000010}, | |
| 339 | []du_int{0xFFFFFFFDFFFFFFFF, 0xFFFFFFFF7FFFFFFF, 0x0000000000000000, 0xFFFFFFFDFFFFFFFF}, | |
| 340 | []du_int{0xFFFFFFFE0747AE14, 0xFFFFFFFF0747AE14, 0x0000000000000000, 0xFFFFFFFE0747AE14}, | |
| 341 | []du_int{0xFFFFFFFF00000001, 0xFFFFFFFF078644FA, 0x0000000000000000, 0xFFFFFFFF00000001}, | |
| 342 | []du_int{0xFFFFFFFF80000000, 0xFFFFFFFF00000010, 0x0000000000000001, 0x000000007FFFFFF0}, | |
| 343 | []du_int{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000}, | |
| 344 | }; | |
| 345 | ||
| 346 | for (cases) |case| { | |
| 347 | test_one_udivmoddi4(case[0], case[1], case[2], case[3]); | |
| 348 | } | |
| 349 | } | |
| 350 | ||
| 351 | fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_int) { | |
| 352 | var r: du_int = undefined; | |
| 353 | const q = __udivmoddi4(a, b, &r); | |
| 354 | assert(q == expected_q); | |
| 355 | assert(r == expected_r); | |
| 356 | } | |
| 357 | ||
| 358 | test "test_udivsi3" { | |
| 359 | const cases = [][3]su_int { | |
| 360 | []su_int{0x00000000, 0x00000001, 0x00000000}, | |
| 361 | []su_int{0x00000000, 0x00000002, 0x00000000}, | |
| 362 | []su_int{0x00000000, 0x00000003, 0x00000000}, | |
| 363 | []su_int{0x00000000, 0x00000010, 0x00000000}, | |
| 364 | []su_int{0x00000000, 0x078644FA, 0x00000000}, | |
| 365 | []su_int{0x00000000, 0x0747AE14, 0x00000000}, | |
| 366 | []su_int{0x00000000, 0x7FFFFFFF, 0x00000000}, | |
| 367 | []su_int{0x00000000, 0x80000000, 0x00000000}, | |
| 368 | []su_int{0x00000000, 0xFFFFFFFD, 0x00000000}, | |
| 369 | []su_int{0x00000000, 0xFFFFFFFE, 0x00000000}, | |
| 370 | []su_int{0x00000000, 0xFFFFFFFF, 0x00000000}, | |
| 371 | []su_int{0x00000001, 0x00000001, 0x00000001}, | |
| 372 | []su_int{0x00000001, 0x00000002, 0x00000000}, | |
| 373 | []su_int{0x00000001, 0x00000003, 0x00000000}, | |
| 374 | []su_int{0x00000001, 0x00000010, 0x00000000}, | |
| 375 | []su_int{0x00000001, 0x078644FA, 0x00000000}, | |
| 376 | []su_int{0x00000001, 0x0747AE14, 0x00000000}, | |
| 377 | []su_int{0x00000001, 0x7FFFFFFF, 0x00000000}, | |
| 378 | []su_int{0x00000001, 0x80000000, 0x00000000}, | |
| 379 | []su_int{0x00000001, 0xFFFFFFFD, 0x00000000}, | |
| 380 | []su_int{0x00000001, 0xFFFFFFFE, 0x00000000}, | |
| 381 | []su_int{0x00000001, 0xFFFFFFFF, 0x00000000}, | |
| 382 | []su_int{0x00000002, 0x00000001, 0x00000002}, | |
| 383 | []su_int{0x00000002, 0x00000002, 0x00000001}, | |
| 384 | []su_int{0x00000002, 0x00000003, 0x00000000}, | |
| 385 | []su_int{0x00000002, 0x00000010, 0x00000000}, | |
| 386 | []su_int{0x00000002, 0x078644FA, 0x00000000}, | |
| 387 | []su_int{0x00000002, 0x0747AE14, 0x00000000}, | |
| 388 | []su_int{0x00000002, 0x7FFFFFFF, 0x00000000}, | |
| 389 | []su_int{0x00000002, 0x80000000, 0x00000000}, | |
| 390 | []su_int{0x00000002, 0xFFFFFFFD, 0x00000000}, | |
| 391 | []su_int{0x00000002, 0xFFFFFFFE, 0x00000000}, | |
| 392 | []su_int{0x00000002, 0xFFFFFFFF, 0x00000000}, | |
| 393 | []su_int{0x00000003, 0x00000001, 0x00000003}, | |
| 394 | []su_int{0x00000003, 0x00000002, 0x00000001}, | |
| 395 | []su_int{0x00000003, 0x00000003, 0x00000001}, | |
| 396 | []su_int{0x00000003, 0x00000010, 0x00000000}, | |
| 397 | []su_int{0x00000003, 0x078644FA, 0x00000000}, | |
| 398 | []su_int{0x00000003, 0x0747AE14, 0x00000000}, | |
| 399 | []su_int{0x00000003, 0x7FFFFFFF, 0x00000000}, | |
| 400 | []su_int{0x00000003, 0x80000000, 0x00000000}, | |
| 401 | []su_int{0x00000003, 0xFFFFFFFD, 0x00000000}, | |
| 402 | []su_int{0x00000003, 0xFFFFFFFE, 0x00000000}, | |
| 403 | []su_int{0x00000003, 0xFFFFFFFF, 0x00000000}, | |
| 404 | []su_int{0x00000010, 0x00000001, 0x00000010}, | |
| 405 | []su_int{0x00000010, 0x00000002, 0x00000008}, | |
| 406 | []su_int{0x00000010, 0x00000003, 0x00000005}, | |
| 407 | []su_int{0x00000010, 0x00000010, 0x00000001}, | |
| 408 | []su_int{0x00000010, 0x078644FA, 0x00000000}, | |
| 409 | []su_int{0x00000010, 0x0747AE14, 0x00000000}, | |
| 410 | []su_int{0x00000010, 0x7FFFFFFF, 0x00000000}, | |
| 411 | []su_int{0x00000010, 0x80000000, 0x00000000}, | |
| 412 | []su_int{0x00000010, 0xFFFFFFFD, 0x00000000}, | |
| 413 | []su_int{0x00000010, 0xFFFFFFFE, 0x00000000}, | |
| 414 | []su_int{0x00000010, 0xFFFFFFFF, 0x00000000}, | |
| 415 | []su_int{0x078644FA, 0x00000001, 0x078644FA}, | |
| 416 | []su_int{0x078644FA, 0x00000002, 0x03C3227D}, | |
| 417 | []su_int{0x078644FA, 0x00000003, 0x028216FE}, | |
| 418 | []su_int{0x078644FA, 0x00000010, 0x0078644F}, | |
| 419 | []su_int{0x078644FA, 0x078644FA, 0x00000001}, | |
| 420 | []su_int{0x078644FA, 0x0747AE14, 0x00000001}, | |
| 421 | []su_int{0x078644FA, 0x7FFFFFFF, 0x00000000}, | |
| 422 | []su_int{0x078644FA, 0x80000000, 0x00000000}, | |
| 423 | []su_int{0x078644FA, 0xFFFFFFFD, 0x00000000}, | |
| 424 | []su_int{0x078644FA, 0xFFFFFFFE, 0x00000000}, | |
| 425 | []su_int{0x078644FA, 0xFFFFFFFF, 0x00000000}, | |
| 426 | []su_int{0x0747AE14, 0x00000001, 0x0747AE14}, | |
| 427 | []su_int{0x0747AE14, 0x00000002, 0x03A3D70A}, | |
| 428 | []su_int{0x0747AE14, 0x00000003, 0x026D3A06}, | |
| 429 | []su_int{0x0747AE14, 0x00000010, 0x00747AE1}, | |
| 430 | []su_int{0x0747AE14, 0x078644FA, 0x00000000}, | |
| 431 | []su_int{0x0747AE14, 0x0747AE14, 0x00000001}, | |
| 432 | []su_int{0x0747AE14, 0x7FFFFFFF, 0x00000000}, | |
| 433 | []su_int{0x0747AE14, 0x80000000, 0x00000000}, | |
| 434 | []su_int{0x0747AE14, 0xFFFFFFFD, 0x00000000}, | |
| 435 | []su_int{0x0747AE14, 0xFFFFFFFE, 0x00000000}, | |
| 436 | []su_int{0x0747AE14, 0xFFFFFFFF, 0x00000000}, | |
| 437 | []su_int{0x7FFFFFFF, 0x00000001, 0x7FFFFFFF}, | |
| 438 | []su_int{0x7FFFFFFF, 0x00000002, 0x3FFFFFFF}, | |
| 439 | []su_int{0x7FFFFFFF, 0x00000003, 0x2AAAAAAA}, | |
| 440 | []su_int{0x7FFFFFFF, 0x00000010, 0x07FFFFFF}, | |
| 441 | []su_int{0x7FFFFFFF, 0x078644FA, 0x00000011}, | |
| 442 | []su_int{0x7FFFFFFF, 0x0747AE14, 0x00000011}, | |
| 443 | []su_int{0x7FFFFFFF, 0x7FFFFFFF, 0x00000001}, | |
| 444 | []su_int{0x7FFFFFFF, 0x80000000, 0x00000000}, | |
| 445 | []su_int{0x7FFFFFFF, 0xFFFFFFFD, 0x00000000}, | |
| 446 | []su_int{0x7FFFFFFF, 0xFFFFFFFE, 0x00000000}, | |
| 447 | []su_int{0x7FFFFFFF, 0xFFFFFFFF, 0x00000000}, | |
| 448 | []su_int{0x80000000, 0x00000001, 0x80000000}, | |
| 449 | []su_int{0x80000000, 0x00000002, 0x40000000}, | |
| 450 | []su_int{0x80000000, 0x00000003, 0x2AAAAAAA}, | |
| 451 | []su_int{0x80000000, 0x00000010, 0x08000000}, | |
| 452 | []su_int{0x80000000, 0x078644FA, 0x00000011}, | |
| 453 | []su_int{0x80000000, 0x0747AE14, 0x00000011}, | |
| 454 | []su_int{0x80000000, 0x7FFFFFFF, 0x00000001}, | |
| 455 | []su_int{0x80000000, 0x80000000, 0x00000001}, | |
| 456 | []su_int{0x80000000, 0xFFFFFFFD, 0x00000000}, | |
| 457 | []su_int{0x80000000, 0xFFFFFFFE, 0x00000000}, | |
| 458 | []su_int{0x80000000, 0xFFFFFFFF, 0x00000000}, | |
| 459 | []su_int{0xFFFFFFFD, 0x00000001, 0xFFFFFFFD}, | |
| 460 | []su_int{0xFFFFFFFD, 0x00000002, 0x7FFFFFFE}, | |
| 461 | []su_int{0xFFFFFFFD, 0x00000003, 0x55555554}, | |
| 462 | []su_int{0xFFFFFFFD, 0x00000010, 0x0FFFFFFF}, | |
| 463 | []su_int{0xFFFFFFFD, 0x078644FA, 0x00000022}, | |
| 464 | []su_int{0xFFFFFFFD, 0x0747AE14, 0x00000023}, | |
| 465 | []su_int{0xFFFFFFFD, 0x7FFFFFFF, 0x00000001}, | |
| 466 | []su_int{0xFFFFFFFD, 0x80000000, 0x00000001}, | |
| 467 | []su_int{0xFFFFFFFD, 0xFFFFFFFD, 0x00000001}, | |
| 468 | []su_int{0xFFFFFFFD, 0xFFFFFFFE, 0x00000000}, | |
| 469 | []su_int{0xFFFFFFFD, 0xFFFFFFFF, 0x00000000}, | |
| 470 | []su_int{0xFFFFFFFE, 0x00000001, 0xFFFFFFFE}, | |
| 471 | []su_int{0xFFFFFFFE, 0x00000002, 0x7FFFFFFF}, | |
| 472 | []su_int{0xFFFFFFFE, 0x00000003, 0x55555554}, | |
| 473 | []su_int{0xFFFFFFFE, 0x00000010, 0x0FFFFFFF}, | |
| 474 | []su_int{0xFFFFFFFE, 0x078644FA, 0x00000022}, | |
| 475 | []su_int{0xFFFFFFFE, 0x0747AE14, 0x00000023}, | |
| 476 | []su_int{0xFFFFFFFE, 0x7FFFFFFF, 0x00000002}, | |
| 477 | []su_int{0xFFFFFFFE, 0x80000000, 0x00000001}, | |
| 478 | []su_int{0xFFFFFFFE, 0xFFFFFFFD, 0x00000001}, | |
| 479 | []su_int{0xFFFFFFFE, 0xFFFFFFFE, 0x00000001}, | |
| 480 | []su_int{0xFFFFFFFE, 0xFFFFFFFF, 0x00000000}, | |
| 481 | []su_int{0xFFFFFFFF, 0x00000001, 0xFFFFFFFF}, | |
| 482 | []su_int{0xFFFFFFFF, 0x00000002, 0x7FFFFFFF}, | |
| 483 | []su_int{0xFFFFFFFF, 0x00000003, 0x55555555}, | |
| 484 | []su_int{0xFFFFFFFF, 0x00000010, 0x0FFFFFFF}, | |
| 485 | []su_int{0xFFFFFFFF, 0x078644FA, 0x00000022}, | |
| 486 | []su_int{0xFFFFFFFF, 0x0747AE14, 0x00000023}, | |
| 487 | []su_int{0xFFFFFFFF, 0x7FFFFFFF, 0x00000002}, | |
| 488 | []su_int{0xFFFFFFFF, 0x80000000, 0x00000001}, | |
| 489 | []su_int{0xFFFFFFFF, 0xFFFFFFFD, 0x00000001}, | |
| 490 | []su_int{0xFFFFFFFF, 0xFFFFFFFE, 0x00000001}, | |
| 491 | []su_int{0xFFFFFFFF, 0xFFFFFFFF, 0x00000001}, | |
| 492 | }; | |
| 493 | ||
| 494 | for (cases) |case| { | |
| 495 | test_one_udivsi3(case[0], case[1], case[2]); | |
| 496 | } | |
| 497 | } | |
| 498 | ||
| 499 | fn test_one_udivsi3(a: su_int, b: su_int, expected_q: su_int) { | |
| 500 | const q: su_int = __udivsi3(a, b); | |
| 501 | assert(q == expected_q); | |
| 502 | } | |
| 503 | ||
| 504 | ||
| 505 | fn assert(ok: bool) { | |
| 506 | if (!ok) unreachable; | |
| 507 | } |
std/special/compiler_rt/index.zig created+507| ... | ... | @@ -0,0 +1,507 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | const CHAR_BIT = 8; | |
| 4 | const du_int = u64; | |
| 5 | const di_int = i64; | |
| 6 | const si_int = c_int; | |
| 7 | const su_int = c_uint; | |
| 8 | ||
| 9 | const udwords = [2]su_int; | |
| 10 | const low = if (builtin.is_big_endian) 1 else 0; | |
| 11 | const high = 1 - low; | |
| 12 | ||
| 13 | export fn __udivdi3(a: du_int, b: du_int) -> du_int { | |
| 14 | @setDebugSafety(this, false); | |
| 15 | return __udivmoddi4(a, b, null); | |
| 16 | } | |
| 17 | ||
| 18 | fn du_int_to_udwords(x: du_int) -> udwords { | |
| 19 | @setDebugSafety(this, false); | |
| 20 | return *@ptrCast(&udwords, &x); | |
| 21 | } | |
| 22 | ||
| 23 | export fn __udivmoddi4(a: du_int, b: du_int, maybe_rem: ?&du_int) -> du_int { | |
| 24 | @setDebugSafety(this, false); | |
| 25 | ||
| 26 | const n_uword_bits = @sizeOf(su_int) * CHAR_BIT; | |
| 27 | const n_udword_bits = @sizeOf(du_int) * CHAR_BIT; | |
| 28 | var n = du_int_to_udwords(a); | |
| 29 | var d = du_int_to_udwords(b); | |
| 30 | var q: udwords = undefined; | |
| 31 | var r: udwords = undefined; | |
| 32 | var sr: c_uint = undefined; | |
| 33 | // special cases, X is unknown, K != 0 | |
| 34 | if (n[high] == 0) { | |
| 35 | if (d[high] == 0) { | |
| 36 | // 0 X | |
| 37 | // --- | |
| 38 | // 0 X | |
| 39 | if (maybe_rem) |rem| { | |
| 40 | *rem = n[low] % d[low]; | |
| 41 | } | |
| 42 | return n[low] / d[low]; | |
| 43 | } | |
| 44 | // 0 X | |
| 45 | // --- | |
| 46 | // K X | |
| 47 | if (maybe_rem) |rem| { | |
| 48 | *rem = n[low]; | |
| 49 | } | |
| 50 | return 0; | |
| 51 | } | |
| 52 | // n[high] != 0 | |
| 53 | if (d[low] == 0) { | |
| 54 | if (d[high] == 0) { | |
| 55 | // K X | |
| 56 | // --- | |
| 57 | // 0 0 | |
| 58 | if (maybe_rem) |rem| { | |
| 59 | *rem = n[high] % d[low]; | |
| 60 | } | |
| 61 | return n[high] / d[low]; | |
| 62 | } | |
| 63 | // d[high] != 0 | |
| 64 | if (n[low] == 0) { | |
| 65 | // K 0 | |
| 66 | // --- | |
| 67 | // K 0 | |
| 68 | if (maybe_rem) |rem| { | |
| 69 | r[high] = n[high] % d[high]; | |
| 70 | r[low] = 0; | |
| 71 | *rem = *@ptrCast(&du_int, &r[0]); | |
| 72 | } | |
| 73 | return n[high] / d[high]; | |
| 74 | } | |
| 75 | // K K | |
| 76 | // --- | |
| 77 | // K 0 | |
| 78 | // if d is a power of 2 | |
| 79 | if ((d[high] & (d[high] - 1)) == 0) { | |
| 80 | if (maybe_rem) |rem| { | |
| 81 | r[low] = n[low]; | |
| 82 | r[high] = n[high] & (d[high] - 1); | |
| 83 | *rem = *@ptrCast(&du_int, &r[0]); | |
| 84 | } | |
| 85 | return n[high] >> @ctz(d[high]); | |
| 86 | } | |
| 87 | // K K | |
| 88 | // --- | |
| 89 | // K 0 | |
| 90 | sr = @clz(su_int(d[high])) - @clz(su_int(n[high])); | |
| 91 | // 0 <= sr <= n_uword_bits - 2 or sr large | |
| 92 | if (sr > n_uword_bits - 2) { | |
| 93 | if (maybe_rem) |rem| { | |
| 94 | *rem = *@ptrCast(&du_int, &n[0]); | |
| 95 | } | |
| 96 | return 0; | |
| 97 | } | |
| 98 | sr += 1; | |
| 99 | // 1 <= sr <= n_uword_bits - 1 | |
| 100 | // q.all = n.all << (n_udword_bits - sr); | |
| 101 | q[low] = 0; | |
| 102 | q[high] = n[low] << (n_uword_bits - sr); | |
| 103 | // r.all = n.all >> sr; | |
| 104 | r[high] = n[high] >> sr; | |
| 105 | r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); | |
| 106 | } else { | |
| 107 | // d[low] != 0 | |
| 108 | if (d[high] == 0) { | |
| 109 | // K X | |
| 110 | // --- | |
| 111 | // 0 K | |
| 112 | // if d is a power of 2 | |
| 113 | if ((d[low] & (d[low] - 1)) == 0) { | |
| 114 | if (maybe_rem) |rem| { | |
| 115 | *rem = n[low] & (d[low] - 1); | |
| 116 | } | |
| 117 | if (d[low] == 1) { | |
| 118 | return *@ptrCast(&du_int, &n[0]); | |
| 119 | } | |
| 120 | sr = @ctz(d[low]); | |
| 121 | q[high] = n[high] >> sr; | |
| 122 | q[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); | |
| 123 | return *@ptrCast(&du_int, &q[0]); | |
| 124 | } | |
| 125 | // K X | |
| 126 | // --- | |
| 127 | // 0 K | |
| 128 | sr = 1 + n_uword_bits + @clz(su_int(d[low])) - @clz(su_int(n[high])); | |
| 129 | // 2 <= sr <= n_udword_bits - 1 | |
| 130 | // q.all = n.all << (n_udword_bits - sr); | |
| 131 | // r.all = n.all >> sr; | |
| 132 | if (sr == n_uword_bits) { | |
| 133 | q[low] = 0; | |
| 134 | q[high] = n[low]; | |
| 135 | r[high] = 0; | |
| 136 | r[low] = n[high]; | |
| 137 | } else if (sr < n_uword_bits) { | |
| 138 | // 2 <= sr <= n_uword_bits - 1 | |
| 139 | q[low] = 0; | |
| 140 | q[high] = n[low] << (n_uword_bits - sr); | |
| 141 | r[high] = n[high] >> sr; | |
| 142 | r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); | |
| 143 | } else { | |
| 144 | // n_uword_bits + 1 <= sr <= n_udword_bits - 1 | |
| 145 | q[low] = n[low] << (n_udword_bits - sr); | |
| 146 | q[high] = (n[high] << (n_udword_bits - sr)) | | |
| 147 | (n[low] >> (sr - n_uword_bits)); | |
| 148 | r[high] = 0; | |
| 149 | r[low] = n[high] >> (sr - n_uword_bits); | |
| 150 | } | |
| 151 | } else { | |
| 152 | // K X | |
| 153 | // --- | |
| 154 | // K K | |
| 155 | sr = @clz(su_int(d[high])) - @clz(su_int(n[high])); | |
| 156 | // 0 <= sr <= n_uword_bits - 1 or sr large | |
| 157 | if (sr > n_uword_bits - 1) { | |
| 158 | if (maybe_rem) |rem| { | |
| 159 | *rem = *@ptrCast(&du_int, &n[0]); | |
| 160 | } | |
| 161 | return 0; | |
| 162 | } | |
| 163 | sr += 1; | |
| 164 | // 1 <= sr <= n_uword_bits | |
| 165 | // q.all = n.all << (n_udword_bits - sr); | |
| 166 | q[low] = 0; | |
| 167 | if (sr == n_uword_bits) { | |
| 168 | q[high] = n[low]; | |
| 169 | r[high] = 0; | |
| 170 | r[low] = n[high]; | |
| 171 | } else { | |
| 172 | q[high] = n[low] << (n_uword_bits - sr); | |
| 173 | r[high] = n[high] >> sr; | |
| 174 | r[low] = (n[high] << (n_uword_bits - sr)) | (n[low] >> sr); | |
| 175 | } | |
| 176 | } | |
| 177 | } | |
| 178 | // Not a special case | |
| 179 | // q and r are initialized with: | |
| 180 | // q.all = n.all << (n_udword_bits - sr); | |
| 181 | // r.all = n.all >> sr; | |
| 182 | // 1 <= sr <= n_udword_bits - 1 | |
| 183 | var carry: su_int = 0; | |
| 184 | while (sr > 0) { | |
| 185 | // r:q = ((r:q) << 1) | carry | |
| 186 | r[high] = (r[high] << 1) | (r[low] >> (n_uword_bits - 1)); | |
| 187 | r[low] = (r[low] << 1) | (q[high] >> (n_uword_bits - 1)); | |
| 188 | q[high] = (q[high] << 1) | (q[low] >> (n_uword_bits - 1)); | |
| 189 | q[low] = (q[low] << 1) | carry; | |
| 190 | // carry = 0; | |
| 191 | // if (r.all >= d.all) | |
| 192 | // { | |
| 193 | // r.all -= d.all; | |
| 194 | // carry = 1; | |
| 195 | // } | |
| 196 | const s: di_int = (di_int)(*@ptrCast(&du_int, &d[0]) - *@ptrCast(&du_int, &r[0]) - 1) >> (n_udword_bits - 1); | |
| 197 | carry = su_int(s & 1); | |
| 198 | *@ptrCast(&du_int, &r[0]) -= *@ptrCast(&du_int, &d[0]) & u64(s); | |
| 199 | ||
| 200 | sr -= 1; | |
| 201 | } | |
| 202 | *@ptrCast(&du_int, &q[0]) = (*@ptrCast(&du_int, &q[0]) << 1) | u64(carry); | |
| 203 | if (maybe_rem) |rem| { | |
| 204 | *rem = *@ptrCast(&du_int, &r[0]); | |
| 205 | } | |
| 206 | return *@ptrCast(&du_int, &q[0]); | |
| 207 | } | |
| 208 | ||
| 209 | export fn __umoddi3(a: du_int, b: du_int) -> du_int { | |
| 210 | @setDebugSafety(this, false); | |
| 211 | ||
| 212 | var r: du_int = undefined; | |
| 213 | _ = __udivmoddi4(a, b, &r); | |
| 214 | return r; | |
| 215 | } | |
| 216 | ||
| 217 | fn isArmArch() -> bool { | |
| 218 | return switch (builtin.arch) { | |
| 219 | builtin.Arch.armv8_2a, | |
| 220 | builtin.Arch.armv8_1a, | |
| 221 | builtin.Arch.armv8, | |
| 222 | builtin.Arch.armv8m_baseline, | |
| 223 | builtin.Arch.armv8m_mainline, | |
| 224 | builtin.Arch.armv7, | |
| 225 | builtin.Arch.armv7em, | |
| 226 | builtin.Arch.armv7m, | |
| 227 | builtin.Arch.armv7s, | |
| 228 | builtin.Arch.armv7k, | |
| 229 | builtin.Arch.armv6, | |
| 230 | builtin.Arch.armv6m, | |
| 231 | builtin.Arch.armv6k, | |
| 232 | builtin.Arch.armv6t2, | |
| 233 | builtin.Arch.armv5, | |
| 234 | builtin.Arch.armv5te, | |
| 235 | builtin.Arch.armv4t, | |
| 236 | builtin.Arch.armeb => true, | |
| 237 | else => false, | |
| 238 | }; | |
| 239 | } | |
| 240 | ||
| 241 | export nakedcc fn __aeabi_uidivmod() { | |
| 242 | @setDebugSafety(this, false); | |
| 243 | ||
| 244 | if (comptime isArmArch()) { | |
| 245 | asm volatile ( | |
| 246 | \\ push { lr } | |
| 247 | \\ sub sp, sp, #4 | |
| 248 | \\ mov r2, sp | |
| 249 | \\ bl __udivmodsi4 | |
| 250 | \\ ldr r1, [sp] | |
| 251 | \\ add sp, sp, #4 | |
| 252 | \\ pop { pc } | |
| 253 | ::: "r2", "r1"); | |
| 254 | unreachable; | |
| 255 | } | |
| 256 | ||
| 257 | @setGlobalLinkage(__aeabi_uidivmod, builtin.GlobalLinkage.Internal); | |
| 258 | } | |
| 259 | ||
| 260 | export fn __udivmodsi4(a: su_int, b: su_int, rem: &su_int) -> su_int { | |
| 261 | @setDebugSafety(this, false); | |
| 262 | ||
| 263 | const d = __udivsi3(a, b); | |
| 264 | *rem = su_int(si_int(a) -% (si_int(d) * si_int(b))); | |
| 265 | return d; | |
| 266 | } | |
| 267 | ||
| 268 | ||
| 269 | // TODO make this an alias instead of an extra function call | |
| 270 | // https://github.com/andrewrk/zig/issues/256 | |
| 271 | ||
| 272 | export fn __aeabi_uidiv(n: su_int, d: su_int) -> su_int { | |
| 273 | @setDebugSafety(this, false); | |
| 274 | ||
| 275 | return __udivsi3(n, d); | |
| 276 | } | |
| 277 | ||
| 278 | export fn __udivsi3(n: su_int, d: su_int) -> su_int { | |
| 279 | @setDebugSafety(this, false); | |
| 280 | ||
| 281 | const n_uword_bits: c_uint = @sizeOf(su_int) * CHAR_BIT; | |
| 282 | // special cases | |
| 283 | if (d == 0) | |
| 284 | return 0; // ?! | |
| 285 | if (n == 0) | |
| 286 | return 0; | |
| 287 | var sr: c_uint = @clz(d) - @clz(n); | |
| 288 | // 0 <= sr <= n_uword_bits - 1 or sr large | |
| 289 | if (sr > n_uword_bits - 1) // d > r | |
| 290 | return 0; | |
| 291 | if (sr == n_uword_bits - 1) // d == 1 | |
| 292 | return n; | |
| 293 | sr += 1; | |
| 294 | // 1 <= sr <= n_uword_bits - 1 | |
| 295 | // Not a special case | |
| 296 | var q: su_int = n << (n_uword_bits - sr); | |
| 297 | var r: su_int = n >> sr; | |
| 298 | var carry: su_int = 0; | |
| 299 | while (sr > 0) : (sr -= 1) { | |
| 300 | // r:q = ((r:q) << 1) | carry | |
| 301 | r = (r << 1) | (q >> (n_uword_bits - 1)); | |
| 302 | q = (q << 1) | carry; | |
| 303 | // carry = 0; | |
| 304 | // if (r.all >= d.all) | |
| 305 | // { | |
| 306 | // r.all -= d.all; | |
| 307 | // carry = 1; | |
| 308 | // } | |
| 309 | const s = si_int(d - r - 1) >> si_int(n_uword_bits - 1); | |
| 310 | carry = su_int(s & 1); | |
| 311 | r -= d & su_int(s); | |
| 312 | } | |
| 313 | q = (q << 1) | carry; | |
| 314 | return q; | |
| 315 | } | |
| 316 | ||
| 317 | test "test_umoddi3" { | |
| 318 | test_one_umoddi3(0, 1, 0); | |
| 319 | test_one_umoddi3(2, 1, 0); | |
| 320 | test_one_umoddi3(0x8000000000000000, 1, 0x0); | |
| 321 | test_one_umoddi3(0x8000000000000000, 2, 0x0); | |
| 322 | test_one_umoddi3(0xFFFFFFFFFFFFFFFF, 2, 0x1); | |
| 323 | } | |
| 324 | ||
| 325 | fn test_one_umoddi3(a: du_int, b: du_int, expected_r: du_int) { | |
| 326 | const r = __umoddi3(a, b); | |
| 327 | assert(r == expected_r); | |
| 328 | } | |
| 329 | ||
| 330 | test "test_udivmoddi4" { | |
| 331 | const cases = [][4]du_int { | |
| 332 | []du_int{0x0000000000000000, 0x0000000000000001, 0x0000000000000000, 0x0000000000000000}, | |
| 333 | []du_int{0x0000000080000000, 0x0000000100000001, 0x0000000000000000, 0x0000000080000000}, | |
| 334 | []du_int{0x7FFFFFFF00000001, 0x0000000000000001, 0x7FFFFFFF00000001, 0x0000000000000000}, | |
| 335 | []du_int{0x7FFFFFFF7FFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000000, 0x7FFFFFFF7FFFFFFF}, | |
| 336 | []du_int{0x8000000000000002, 0xFFFFFFFFFFFFFFFE, 0x0000000000000000, 0x8000000000000002}, | |
| 337 | []du_int{0x80000000FFFFFFFD, 0xFFFFFFFFFFFFFFFD, 0x0000000000000000, 0x80000000FFFFFFFD}, | |
| 338 | []du_int{0xFFFFFFFD00000010, 0xFFFFFFFF80000000, 0x0000000000000000, 0xFFFFFFFD00000010}, | |
| 339 | []du_int{0xFFFFFFFDFFFFFFFF, 0xFFFFFFFF7FFFFFFF, 0x0000000000000000, 0xFFFFFFFDFFFFFFFF}, | |
| 340 | []du_int{0xFFFFFFFE0747AE14, 0xFFFFFFFF0747AE14, 0x0000000000000000, 0xFFFFFFFE0747AE14}, | |
| 341 | []du_int{0xFFFFFFFF00000001, 0xFFFFFFFF078644FA, 0x0000000000000000, 0xFFFFFFFF00000001}, | |
| 342 | []du_int{0xFFFFFFFF80000000, 0xFFFFFFFF00000010, 0x0000000000000001, 0x000000007FFFFFF0}, | |
| 343 | []du_int{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0x0000000000000001, 0x0000000000000000}, | |
| 344 | }; | |
| 345 | ||
| 346 | for (cases) |case| { | |
| 347 | test_one_udivmoddi4(case[0], case[1], case[2], case[3]); | |
| 348 | } | |
| 349 | } | |
| 350 | ||
| 351 | fn test_one_udivmoddi4(a: du_int, b: du_int, expected_q: du_int, expected_r: du_int) { | |
| 352 | var r: du_int = undefined; | |
| 353 | const q = __udivmoddi4(a, b, &r); | |
| 354 | assert(q == expected_q); | |
| 355 | assert(r == expected_r); | |
| 356 | } | |
| 357 | ||
| 358 | test "test_udivsi3" { | |
| 359 | const cases = [][3]su_int { | |
| 360 | []su_int{0x00000000, 0x00000001, 0x00000000}, | |
| 361 | []su_int{0x00000000, 0x00000002, 0x00000000}, | |
| 362 | []su_int{0x00000000, 0x00000003, 0x00000000}, | |
| 363 | []su_int{0x00000000, 0x00000010, 0x00000000}, | |
| 364 | []su_int{0x00000000, 0x078644FA, 0x00000000}, | |
| 365 | []su_int{0x00000000, 0x0747AE14, 0x00000000}, | |
| 366 | []su_int{0x00000000, 0x7FFFFFFF, 0x00000000}, | |
| 367 | []su_int{0x00000000, 0x80000000, 0x00000000}, | |
| 368 | []su_int{0x00000000, 0xFFFFFFFD, 0x00000000}, | |
| 369 | []su_int{0x00000000, 0xFFFFFFFE, 0x00000000}, | |
| 370 | []su_int{0x00000000, 0xFFFFFFFF, 0x00000000}, | |
| 371 | []su_int{0x00000001, 0x00000001, 0x00000001}, | |
| 372 | []su_int{0x00000001, 0x00000002, 0x00000000}, | |
| 373 | []su_int{0x00000001, 0x00000003, 0x00000000}, | |
| 374 | []su_int{0x00000001, 0x00000010, 0x00000000}, | |
| 375 | []su_int{0x00000001, 0x078644FA, 0x00000000}, | |
| 376 | []su_int{0x00000001, 0x0747AE14, 0x00000000}, | |
| 377 | []su_int{0x00000001, 0x7FFFFFFF, 0x00000000}, | |
| 378 | []su_int{0x00000001, 0x80000000, 0x00000000}, | |
| 379 | []su_int{0x00000001, 0xFFFFFFFD, 0x00000000}, | |
| 380 | []su_int{0x00000001, 0xFFFFFFFE, 0x00000000}, | |
| 381 | []su_int{0x00000001, 0xFFFFFFFF, 0x00000000}, | |
| 382 | []su_int{0x00000002, 0x00000001, 0x00000002}, | |
| 383 | []su_int{0x00000002, 0x00000002, 0x00000001}, | |
| 384 | []su_int{0x00000002, 0x00000003, 0x00000000}, | |
| 385 | []su_int{0x00000002, 0x00000010, 0x00000000}, | |
| 386 | []su_int{0x00000002, 0x078644FA, 0x00000000}, | |
| 387 | []su_int{0x00000002, 0x0747AE14, 0x00000000}, | |
| 388 | []su_int{0x00000002, 0x7FFFFFFF, 0x00000000}, | |
| 389 | []su_int{0x00000002, 0x80000000, 0x00000000}, | |
| 390 | []su_int{0x00000002, 0xFFFFFFFD, 0x00000000}, | |
| 391 | []su_int{0x00000002, 0xFFFFFFFE, 0x00000000}, | |
| 392 | []su_int{0x00000002, 0xFFFFFFFF, 0x00000000}, | |
| 393 | []su_int{0x00000003, 0x00000001, 0x00000003}, | |
| 394 | []su_int{0x00000003, 0x00000002, 0x00000001}, | |
| 395 | []su_int{0x00000003, 0x00000003, 0x00000001}, | |
| 396 | []su_int{0x00000003, 0x00000010, 0x00000000}, | |
| 397 | []su_int{0x00000003, 0x078644FA, 0x00000000}, | |
| 398 | []su_int{0x00000003, 0x0747AE14, 0x00000000}, | |
| 399 | []su_int{0x00000003, 0x7FFFFFFF, 0x00000000}, | |
| 400 | []su_int{0x00000003, 0x80000000, 0x00000000}, | |
| 401 | []su_int{0x00000003, 0xFFFFFFFD, 0x00000000}, | |
| 402 | []su_int{0x00000003, 0xFFFFFFFE, 0x00000000}, | |
| 403 | []su_int{0x00000003, 0xFFFFFFFF, 0x00000000}, | |
| 404 | []su_int{0x00000010, 0x00000001, 0x00000010}, | |
| 405 | []su_int{0x00000010, 0x00000002, 0x00000008}, | |
| 406 | []su_int{0x00000010, 0x00000003, 0x00000005}, | |
| 407 | []su_int{0x00000010, 0x00000010, 0x00000001}, | |
| 408 | []su_int{0x00000010, 0x078644FA, 0x00000000}, | |
| 409 | []su_int{0x00000010, 0x0747AE14, 0x00000000}, | |
| 410 | []su_int{0x00000010, 0x7FFFFFFF, 0x00000000}, | |
| 411 | []su_int{0x00000010, 0x80000000, 0x00000000}, | |
| 412 | []su_int{0x00000010, 0xFFFFFFFD, 0x00000000}, | |
| 413 | []su_int{0x00000010, 0xFFFFFFFE, 0x00000000}, | |
| 414 | []su_int{0x00000010, 0xFFFFFFFF, 0x00000000}, | |
| 415 | []su_int{0x078644FA, 0x00000001, 0x078644FA}, | |
| 416 | []su_int{0x078644FA, 0x00000002, 0x03C3227D}, | |
| 417 | []su_int{0x078644FA, 0x00000003, 0x028216FE}, | |
| 418 | []su_int{0x078644FA, 0x00000010, 0x0078644F}, | |
| 419 | []su_int{0x078644FA, 0x078644FA, 0x00000001}, | |
| 420 | []su_int{0x078644FA, 0x0747AE14, 0x00000001}, | |
| 421 | []su_int{0x078644FA, 0x7FFFFFFF, 0x00000000}, | |
| 422 | []su_int{0x078644FA, 0x80000000, 0x00000000}, | |
| 423 | []su_int{0x078644FA, 0xFFFFFFFD, 0x00000000}, | |
| 424 | []su_int{0x078644FA, 0xFFFFFFFE, 0x00000000}, | |
| 425 | []su_int{0x078644FA, 0xFFFFFFFF, 0x00000000}, | |
| 426 | []su_int{0x0747AE14, 0x00000001, 0x0747AE14}, | |
| 427 | []su_int{0x0747AE14, 0x00000002, 0x03A3D70A}, | |
| 428 | []su_int{0x0747AE14, 0x00000003, 0x026D3A06}, | |
| 429 | []su_int{0x0747AE14, 0x00000010, 0x00747AE1}, | |
| 430 | []su_int{0x0747AE14, 0x078644FA, 0x00000000}, | |
| 431 | []su_int{0x0747AE14, 0x0747AE14, 0x00000001}, | |
| 432 | []su_int{0x0747AE14, 0x7FFFFFFF, 0x00000000}, | |
| 433 | []su_int{0x0747AE14, 0x80000000, 0x00000000}, | |
| 434 | []su_int{0x0747AE14, 0xFFFFFFFD, 0x00000000}, | |
| 435 | []su_int{0x0747AE14, 0xFFFFFFFE, 0x00000000}, | |
| 436 | []su_int{0x0747AE14, 0xFFFFFFFF, 0x00000000}, | |
| 437 | []su_int{0x7FFFFFFF, 0x00000001, 0x7FFFFFFF}, | |
| 438 | []su_int{0x7FFFFFFF, 0x00000002, 0x3FFFFFFF}, | |
| 439 | []su_int{0x7FFFFFFF, 0x00000003, 0x2AAAAAAA}, | |
| 440 | []su_int{0x7FFFFFFF, 0x00000010, 0x07FFFFFF}, | |
| 441 | []su_int{0x7FFFFFFF, 0x078644FA, 0x00000011}, | |
| 442 | []su_int{0x7FFFFFFF, 0x0747AE14, 0x00000011}, | |
| 443 | []su_int{0x7FFFFFFF, 0x7FFFFFFF, 0x00000001}, | |
| 444 | []su_int{0x7FFFFFFF, 0x80000000, 0x00000000}, | |
| 445 | []su_int{0x7FFFFFFF, 0xFFFFFFFD, 0x00000000}, | |
| 446 | []su_int{0x7FFFFFFF, 0xFFFFFFFE, 0x00000000}, | |
| 447 | []su_int{0x7FFFFFFF, 0xFFFFFFFF, 0x00000000}, | |
| 448 | []su_int{0x80000000, 0x00000001, 0x80000000}, | |
| 449 | []su_int{0x80000000, 0x00000002, 0x40000000}, | |
| 450 | []su_int{0x80000000, 0x00000003, 0x2AAAAAAA}, | |
| 451 | []su_int{0x80000000, 0x00000010, 0x08000000}, | |
| 452 | []su_int{0x80000000, 0x078644FA, 0x00000011}, | |
| 453 | []su_int{0x80000000, 0x0747AE14, 0x00000011}, | |
| 454 | []su_int{0x80000000, 0x7FFFFFFF, 0x00000001}, | |
| 455 | []su_int{0x80000000, 0x80000000, 0x00000001}, | |
| 456 | []su_int{0x80000000, 0xFFFFFFFD, 0x00000000}, | |
| 457 | []su_int{0x80000000, 0xFFFFFFFE, 0x00000000}, | |
| 458 | []su_int{0x80000000, 0xFFFFFFFF, 0x00000000}, | |
| 459 | []su_int{0xFFFFFFFD, 0x00000001, 0xFFFFFFFD}, | |
| 460 | []su_int{0xFFFFFFFD, 0x00000002, 0x7FFFFFFE}, | |
| 461 | []su_int{0xFFFFFFFD, 0x00000003, 0x55555554}, | |
| 462 | []su_int{0xFFFFFFFD, 0x00000010, 0x0FFFFFFF}, | |
| 463 | []su_int{0xFFFFFFFD, 0x078644FA, 0x00000022}, | |
| 464 | []su_int{0xFFFFFFFD, 0x0747AE14, 0x00000023}, | |
| 465 | []su_int{0xFFFFFFFD, 0x7FFFFFFF, 0x00000001}, | |
| 466 | []su_int{0xFFFFFFFD, 0x80000000, 0x00000001}, | |
| 467 | []su_int{0xFFFFFFFD, 0xFFFFFFFD, 0x00000001}, | |
| 468 | []su_int{0xFFFFFFFD, 0xFFFFFFFE, 0x00000000}, | |
| 469 | []su_int{0xFFFFFFFD, 0xFFFFFFFF, 0x00000000}, | |
| 470 | []su_int{0xFFFFFFFE, 0x00000001, 0xFFFFFFFE}, | |
| 471 | []su_int{0xFFFFFFFE, 0x00000002, 0x7FFFFFFF}, | |
| 472 | []su_int{0xFFFFFFFE, 0x00000003, 0x55555554}, | |
| 473 | []su_int{0xFFFFFFFE, 0x00000010, 0x0FFFFFFF}, | |
| 474 | []su_int{0xFFFFFFFE, 0x078644FA, 0x00000022}, | |
| 475 | []su_int{0xFFFFFFFE, 0x0747AE14, 0x00000023}, | |
| 476 | []su_int{0xFFFFFFFE, 0x7FFFFFFF, 0x00000002}, | |
| 477 | []su_int{0xFFFFFFFE, 0x80000000, 0x00000001}, | |
| 478 | []su_int{0xFFFFFFFE, 0xFFFFFFFD, 0x00000001}, | |
| 479 | []su_int{0xFFFFFFFE, 0xFFFFFFFE, 0x00000001}, | |
| 480 | []su_int{0xFFFFFFFE, 0xFFFFFFFF, 0x00000000}, | |
| 481 | []su_int{0xFFFFFFFF, 0x00000001, 0xFFFFFFFF}, | |
| 482 | []su_int{0xFFFFFFFF, 0x00000002, 0x7FFFFFFF}, | |
| 483 | []su_int{0xFFFFFFFF, 0x00000003, 0x55555555}, | |
| 484 | []su_int{0xFFFFFFFF, 0x00000010, 0x0FFFFFFF}, | |
| 485 | []su_int{0xFFFFFFFF, 0x078644FA, 0x00000022}, | |
| 486 | []su_int{0xFFFFFFFF, 0x0747AE14, 0x00000023}, | |
| 487 | []su_int{0xFFFFFFFF, 0x7FFFFFFF, 0x00000002}, | |
| 488 | []su_int{0xFFFFFFFF, 0x80000000, 0x00000001}, | |
| 489 | []su_int{0xFFFFFFFF, 0xFFFFFFFD, 0x00000001}, | |
| 490 | []su_int{0xFFFFFFFF, 0xFFFFFFFE, 0x00000001}, | |
| 491 | []su_int{0xFFFFFFFF, 0xFFFFFFFF, 0x00000001}, | |
| 492 | }; | |
| 493 | ||
| 494 | for (cases) |case| { | |
| 495 | test_one_udivsi3(case[0], case[1], case[2]); | |
| 496 | } | |
| 497 | } | |
| 498 | ||
| 499 | fn test_one_udivsi3(a: su_int, b: su_int, expected_q: su_int) { | |
| 500 | const q: su_int = __udivsi3(a, b); | |
| 501 | assert(q == expected_q); | |
| 502 | } | |
| 503 | ||
| 504 | ||
| 505 | fn assert(ok: bool) { | |
| 506 | if (!ok) unreachable; | |
| 507 | } |