╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ compiler_rt.zig ──────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
465 } 466 }; 467 // 128x128 -> 256 wide multiply for platforms that don't have such an operation; 468 // many 64-bit platforms have this operation, but they tend to have hardware 469 // floating-point, so we don't bother with a special case for them here. 470 471 const product11: u64 = S.Word_1(a) * S.Word_1(b); 472 const product12: u64 = S.Word_1(a) * S.Word_2(b); 473 const product13: u64 = S.Word_1(a) * S.Word_3(b); 474 const product14: u64 = S.Word_1(a) * S.Word_4(b); 475 const product21: u64 = S.Word_2(a) * S.Word_1(b); 476 const product22: u64 = S.Word_2(a) * S.Word_2(b); 477 const product23: u64 = S.Word_2(a) * S.Word_3(b); 478 const product24: u64 = S.Word_2(a) * S.Word_4(b); 479 const product31: u64 = S.Word_3(a) * S.Word_1(b); 480 const product32: u64 = S.Word_3(a) * S.Word_2(b); 481 const product33: u64 = S.Word_3(a) * S.Word_3(b); 482 const product34: u64 = S.Word_3(a) * S.Word_4(b); 483 const product41: u64 = S.Word_4(a) * S.Word_1(b); 484 const product42: u64 = S.Word_4(a) * S.Word_2(b); 485 const product43: u64 = S.Word_4(a) * S.Word_3(b); 486 const product44: u64 = S.Word_4(a) * S.Word_4(b); 487 488 const sum0: u128 = @as(u128, product44); 489 const sum1: u128 = @as(u128, product34) +% 490 @as(u128, product43); 491 const sum2: u128 = @as(u128, product24) +% 492 @as(u128, product33) +% 493 @as(u128, product42); 494 const sum3: u128 = @as(u128, product14) +% 495 @as(u128, product23) +% 496 @as(u128, product32) +% 497 @as(u128, product41); 498 const sum4: u128 = @as(u128, product13) +% 499 @as(u128, product22) +% 500 @as(u128, product31); 501 const sum5: u128 = @as(u128, product12) +% 502 @as(u128, product21); 503 const sum6: u128 = @as(u128, product11); 504 505 const r0: u128 = (sum0 & Word_FullMask) +% 506 ((sum1 & Word_LoMask) << 32); 507 const r1: u128 = (sum0 >> 64) +% 508 ((sum1 >> 32) & Word_FullMask) +% 509 (sum2 & Word_FullMask) +% 510 ((sum3 << 32) & Word_HiMask); 511 512 lo.* = r0 +% (r1 << 64); 513 hi.* = (r1 >> 64) +% 514 (sum1 >> 96) +% 515 (sum2 >> 64) +% 516 (sum3 >> 32) +% 517 sum4 +% 518 (sum5 << 32) +% 519 (sum6 << 64); 520 }, 521 else => @compileError("unsupported"), 522 } 523 } 524 525 pub fn normalize(comptime T: type, significand: *@Int(.unsigned, @typeInfo(T).float.bits)) i32 { 526 const Z = @Int(.unsigned, @typeInfo(T).float.bits); 527 const integerBit = @as(Z, 1) << std.math.floatFractionalBits(T); 528 529 const shift = @clz(significand.*) - @clz(integerBit); 530 significand.* <<= @as(std.math.Log2Int(Z), @intCast(shift)); 531 return @as(i32, 1) - shift; 532 } 533 534 pub inline fn fneg(a: anytype) @TypeOf(a) { 535 const F = @TypeOf(a); 536 const bits = @typeInfo(F).float.bits; 537 const U = @Int(.unsigned, bits); 538 const sign_bit_mask = @as(U, 1) << (bits - 1); 539 const negated = @as(U, @bitCast(a)) ^ sign_bit_mask; 540 return @bitCast(negated); 541 } 542 543 fn __neghf2(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { 544 return compiler_rt.f16.toAbi(fneg(compiler_rt.f16.fromAbi(a))); 545 } 546 547 fn __negsf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { 548 return compiler_rt.f32.toAbi(fneg(compiler_rt.f32.fromAbi(a))); 549 } 550 551 fn __negdf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { 552 return compiler_rt.f64.toAbi(fneg(compiler_rt.f64.fromAbi(a))); 553 } 554 555 fn __negxf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { 556 return compiler_rt.f80.toAbi(fneg(compiler_rt.f80.fromAbi(a))); 557 } 558 559 fn __negtf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { 560 return compiler_rt.f128.toAbi(fneg(compiler_rt.f128.fromAbi(a))); 561 } 562 563 fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 { 564 return fneg(a); 565 } 566 567 fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 { 568 return fneg(a); 569 } 570 571 /// Allows to access underlying bits as two equally sized lower and higher 572 /// signed or unsigned integers. 573 pub fn HalveInt(comptime T: type, comptime signed_half: bool) type { 574 return extern union { 575 pub const bits = @divExact(@typeInfo(T).int.bits, 2); 576 pub const HalfTU = @Int(.unsigned, bits); 577 pub const HalfTS = @Int(.signed, bits); 578 pub const HalfT = if (signed_half) HalfTS else HalfTU; 579 580 all: T, 581 s: if (native_endian == .little) 582 extern struct { low: HalfT, high: HalfT } 583 else 584 extern struct { high: HalfT, low: HalfT }, 585 }; 586 } 587 588 pub fn __negsi2(a: i32) callconv(.c) i32 { 589 return negXi2(i32, a); 590 } 591 592 pub fn __negdi2(a: i64) callconv(.c) i64 { 593 return negXi2(i64, a); 594 } 595 596 pub fn __negti2(a: i128) callconv(.c) i128 { 597 return negXi2(i128, a); 598 } 599 600 inline fn negXi2(comptime T: type, a: T) T { 601 return -a; 602 } 603 604 fn memsetSmallPowerOf2(d: [*]u8, b: u8, comptime size: usize) void { 605 @disableIntrinsics(); 606 607 if (size > @sizeOf(usize)) { 608 d[0..size].* = @splat(b); 609 } else { 610 const T = @Int(.unsigned, 8 * size); 611 var splatted: T = 0; // Setting this to undefined causes a memset call and thus infinite recursion in Debug test-compiler-rt. 612 @as(*[size]u8, @ptrCast(&splatted)).* = @splat(b); 613 @as(*align(1) T, @ptrCast(d)).* = splatted; 614 } 615 } 616 617 fn shortMemset( 618 log_min: comptime_int, 619 log_max: comptime_int, 620 d: [*]u8, 621 b: u8, 622 len: usize, 623 ) void { 624 @disableIntrinsics(); 625 626 if (log_min + 1 != log_max) { 627 const mid = (log_min + log_max) / 2; 628 if (len > 1 << mid) { 629 shortMemset(mid, log_max, d, b, len); 630 } else { 631 shortMemset(log_min, mid, d, b, len); 632 } 633 } else { 634 const size = 1 << log_min; 635 636 memsetSmallPowerOf2(d, b, size); 637 memsetSmallPowerOf2(d + len - size, b, size); 638 } 639 } 640 641 fn fastMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { 642 @disableIntrinsics(); 643 644 const b: u8 = @truncate(@as(c_uint, @bitCast(c))); 645 const n = std.simd.suggestVectorLength(u8) orelse @sizeOf(usize); 646 647 const d = dest.?; 648 649 if (len > 2 * n) { 650 memsetSmallPowerOf2(d, b, n); 651 652 const begin_aligned = std.mem.alignBackward(usize, @intFromPtr(d) + n, n); 653 const end_aligned = std.mem.alignForward(usize, @intFromPtr(d) + len - n, n); 654 655 const aligned_ptr: [*]align(n) u8 = @ptrFromInt(begin_aligned); 656 657 var i: usize = 0; 658 while (true) { 659 memsetSmallPowerOf2(aligned_ptr + n * i, b, n); 660 661 i += 1; 662 if (i == @divExact(end_aligned - begin_aligned, n)) 663 break; 664 } 665 666 memsetSmallPowerOf2(d + len - n, b, n); 667 } else { 668 if (len == 0) return dest; 669 670 shortMemset(0, @ctz(@as(usize, 2 * n)), d, b, len); 671 } 672 673 return dest; 674 } 675 676 fn smallMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { 677 @disableIntrinsics(); 678 679 const b: u8 = @truncate(@as(c_uint, @bitCast(c))); 680 681 if (len != 0) { 682 var d = dest.?; 683 var n = len; 684 while (true) { 685 d[0] = b; 686 n -= 1; 687 if (n == 0) break; 688 d += 1; 689 } 690 } 691 692 return dest; 693 } 694 695 pub const memset = if (builtin.optimize == .small) 696 smallMemset 697 else 698 fastMemset; 699 700 pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.c) c_int { 701 @setRuntimeSafety(false); 702 703 var index: usize = 0; 704 while (index != n) : (index += 1) { 705 if (vl[index] != vr[index]) { 706 return 1; 707 } 708 } 709 710 return 0; 711 } 712 713 test "bcmp" { 714 const base_arr = &[_]u8{ 1, 1, 1 }; 715 const arr1 = &[_]u8{ 1, 1, 1 }; 716 const arr2 = &[_]u8{ 1, 0, 1 }; 717 const arr3 = &[_]u8{ 1, 2, 1 }; 718 719 try std.testing.expect(bcmp(base_arr[0..], arr1[0..], base_arr.len) == 0); 720 try std.testing.expect(bcmp(base_arr[0..], arr2[0..], base_arr.len) != 0); 721 try std.testing.expect(bcmp(base_arr[0..], arr3[0..], base_arr.len) != 0); 722 } 723 724 test { 725 _ = @import("compiler_rt/negsi2_test.zig"); 726 _ = @import("compiler_rt/negdi2_test.zig"); 727 _ = @import("compiler_rt/negti2_test.zig"); 728 } 729