| author | |
| committer | |
| log | 74442f35030a9c4f4ff65db01a18e8fb2f2a1ecf |
| tree | 0a3417d662326ce757cc8d89ca7e19498ead9207 |
| parent | 33cf6ef621114daad63d14067b6ff374e664d410 |
| parent | 1d4dbf8d3c891346e6dc978764e8bce9c85ad044 |
| signature |
204 files changed, 7587 insertions(+), 6205 deletions(-)
CMakeLists.txt+113-10| ... | ... | @@ -480,8 +480,15 @@ set(ZIG_STAGE2_SOURCES |
| 480 | 480 | "${CMAKE_SOURCE_DIR}/lib/std/sort.zig" |
| 481 | 481 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt.zig" |
| 482 | 482 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/absv.zig" |
| 483 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addXf3.zig" | |
| 483 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/absvdi2.zig" | |
| 484 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/absvsi2.zig" | |
| 485 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/absvti2.zig" | |
| 486 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/adddf3.zig" | |
| 487 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addf3.zig" | |
| 484 | 488 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addo.zig" |
| 489 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addsf3.zig" | |
| 490 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addtf3.zig" | |
| 491 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addxf3.zig" | |
| 485 | 492 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/arm.zig" |
| 486 | 493 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/atomics.zig" |
| 487 | 494 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/aulldiv.zig" |
| ... | ... | @@ -490,7 +497,12 @@ set(ZIG_STAGE2_SOURCES |
| 490 | 497 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/ceil.zig" |
| 491 | 498 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/clear_cache.zig" |
| 492 | 499 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmp.zig" |
| 493 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/compareXf2.zig" | |
| 500 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmpdf2.zig" | |
| 501 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmpsf2.zig" | |
| 502 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmptf2.zig" | |
| 503 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmpxf2.zig" | |
| 504 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/common.zig" | |
| 505 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/comparef.zig" | |
| 494 | 506 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cos.zig" |
| 495 | 507 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/count0bits.zig" |
| 496 | 508 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/divdf3.zig" |
| ... | ... | @@ -501,25 +513,101 @@ set(ZIG_STAGE2_SOURCES |
| 501 | 513 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/emutls.zig" |
| 502 | 514 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/exp.zig" |
| 503 | 515 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/exp2.zig" |
| 504 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendXfYf2.zig" | |
| 505 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extend_f80.zig" | |
| 516 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extenddftf2.zig" | |
| 517 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extenddfxf2.zig" | |
| 518 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendf.zig" | |
| 519 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendhfsf2.zig" | |
| 520 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendhftf2.zig" | |
| 521 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendhfxf2.zig" | |
| 522 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendsfdf2.zig" | |
| 523 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendsftf2.zig" | |
| 524 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendsfxf2.zig" | |
| 525 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendxftf2.zig" | |
| 506 | 526 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fabs.zig" |
| 507 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixXfYi.zig" | |
| 508 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatXiYf.zig" | |
| 527 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixdfdi.zig" | |
| 528 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixdfsi.zig" | |
| 529 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixdfti.zig" | |
| 530 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixhfdi.zig" | |
| 531 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixhfsi.zig" | |
| 532 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixhfti.zig" | |
| 533 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixsfdi.zig" | |
| 534 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixsfsi.zig" | |
| 535 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixsfti.zig" | |
| 536 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixtfdi.zig" | |
| 537 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixtfsi.zig" | |
| 538 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixtfti.zig" | |
| 539 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsdfdi.zig" | |
| 540 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsdfsi.zig" | |
| 541 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsdfti.zig" | |
| 542 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunshfdi.zig" | |
| 543 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunshfsi.zig" | |
| 544 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunshfti.zig" | |
| 545 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunssfdi.zig" | |
| 546 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunssfsi.zig" | |
| 547 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunssfti.zig" | |
| 548 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunstfdi.zig" | |
| 549 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunstfsi.zig" | |
| 550 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunstfti.zig" | |
| 551 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsxfdi.zig" | |
| 552 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsxfsi.zig" | |
| 553 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsxfti.zig" | |
| 554 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixxfdi.zig" | |
| 555 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixxfsi.zig" | |
| 556 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixxfti.zig" | |
| 557 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/float_to_int.zig" | |
| 558 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdidf.zig" | |
| 559 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdihf.zig" | |
| 560 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdisf.zig" | |
| 561 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatditf.zig" | |
| 562 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdixf.zig" | |
| 563 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsidf.zig" | |
| 564 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsihf.zig" | |
| 565 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsisf.zig" | |
| 566 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsitf.zig" | |
| 567 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsixf.zig" | |
| 568 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattidf.zig" | |
| 569 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattihf.zig" | |
| 570 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattisf.zig" | |
| 571 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattitf.zig" | |
| 572 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattixf.zig" | |
| 573 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundidf.zig" | |
| 574 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundihf.zig" | |
| 575 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundisf.zig" | |
| 576 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunditf.zig" | |
| 577 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundixf.zig" | |
| 578 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsidf.zig" | |
| 579 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsihf.zig" | |
| 580 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsisf.zig" | |
| 581 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsitf.zig" | |
| 582 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsixf.zig" | |
| 583 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntidf.zig" | |
| 584 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntihf.zig" | |
| 585 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntisf.zig" | |
| 586 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntitf.zig" | |
| 587 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntixf.zig" | |
| 509 | 588 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floor.zig" |
| 510 | 589 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fma.zig" |
| 511 | 590 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fmax.zig" |
| 512 | 591 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fmin.zig" |
| 513 | 592 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fmod.zig" |
| 593 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/gedf2.zig" | |
| 594 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/gesf2.zig" | |
| 595 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/getf2.zig" | |
| 596 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/gexf2.zig" | |
| 514 | 597 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/int.zig" |
| 598 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/int_to_float.zig" | |
| 515 | 599 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log.zig" |
| 516 | 600 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log10.zig" |
| 517 | 601 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log2.zig" |
| 518 | 602 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/modti3.zig" |
| 519 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulXf3.zig" | |
| 603 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/muldf3.zig" | |
| 520 | 604 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/muldi3.zig" |
| 605 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulf3.zig" | |
| 521 | 606 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulo.zig" |
| 607 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulsf3.zig" | |
| 608 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/multf3.zig" | |
| 522 | 609 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/multi3.zig" |
| 610 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulxf3.zig" | |
| 523 | 611 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negXf2.zig" |
| 524 | 612 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negXi2.zig" |
| 525 | 613 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negv.zig" |
| ... | ... | @@ -533,19 +621,34 @@ set(ZIG_STAGE2_SOURCES |
| 533 | 621 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/shift.zig" |
| 534 | 622 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sin.zig" |
| 535 | 623 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sincos.zig" |
| 536 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sparc.zig" | |
| 537 | 624 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sqrt.zig" |
| 538 | 625 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/stack_probe.zig" |
| 626 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subdf3.zig" | |
| 539 | 627 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subo.zig" |
| 628 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subsf3.zig" | |
| 629 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subtf3.zig" | |
| 630 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subxf3.zig" | |
| 540 | 631 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/tan.zig" |
| 541 | 632 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trig.zig" |
| 542 | 633 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunc.zig" |
| 543 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncXfYf2.zig" | |
| 544 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunc_f80.zig" | |
| 634 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncdfhf2.zig" | |
| 635 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncdfsf2.zig" | |
| 636 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncf.zig" | |
| 637 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncsfhf2.zig" | |
| 638 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunctfdf2.zig" | |
| 639 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunctfhf2.zig" | |
| 640 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunctfsf2.zig" | |
| 641 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunctfxf2.zig" | |
| 642 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncxfdf2.zig" | |
| 643 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncxfhf2.zig" | |
| 644 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncxfsf2.zig" | |
| 545 | 645 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivmod.zig" |
| 546 | 646 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivmodti4.zig" |
| 547 | 647 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivti3.zig" |
| 548 | 648 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/umodti3.zig" |
| 649 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/unorddf2.zig" | |
| 650 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/unordsf2.zig" | |
| 651 | "${CMAKE_SOURCE_DIR}/lib/compiler_rt/unordtf2.zig" | |
| 549 | 652 | "${CMAKE_SOURCE_DIR}/lib/std/start.zig" |
| 550 | 653 | "${CMAKE_SOURCE_DIR}/lib/std/std.zig" |
| 551 | 654 | "${CMAKE_SOURCE_DIR}/lib/std/target.zig" |
ci/azure/macos_script+1-1| ... | ... | @@ -75,7 +75,7 @@ release/bin/zig build test-translate-c -Denable-macos-sdk |
| 75 | 75 | release/bin/zig build test-run-translated-c -Denable-macos-sdk |
| 76 | 76 | release/bin/zig build docs -Denable-macos-sdk |
| 77 | 77 | release/bin/zig build test-fmt -Denable-macos-sdk |
| 78 | release/bin/zig build test-cases -Denable-macos-sdk | |
| 78 | release/bin/zig build test-cases -Denable-macos-sdk -Dsingle-threaded | |
| 79 | 79 | |
| 80 | 80 | if [ "${BUILD_REASON}" != "PullRequest" ]; then |
| 81 | 81 | mv ../LICENSE release/ |
lib/compiler_rt.zig+177-880| ... | ... | @@ -1,885 +1,182 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const is_test = builtin.is_test; | |
| 4 | const os_tag = builtin.os.tag; | |
| 5 | const arch = builtin.cpu.arch; | |
| 6 | const abi = builtin.abi; | |
| 7 | ||
| 8 | const is_gnu = abi.isGnu(); | |
| 9 | const is_mingw = os_tag == .windows and is_gnu; | |
| 10 | const is_darwin = std.Target.Os.Tag.isDarwin(os_tag); | |
| 11 | const is_ppc = arch.isPPC() or arch.isPPC64(); | |
| 12 | ||
| 13 | const linkage = if (is_test) | |
| 14 | std.builtin.GlobalLinkage.Internal | |
| 15 | else | |
| 16 | std.builtin.GlobalLinkage.Weak; | |
| 17 | ||
| 18 | const strong_linkage = if (is_test) | |
| 19 | std.builtin.GlobalLinkage.Internal | |
| 20 | else | |
| 21 | std.builtin.GlobalLinkage.Strong; | |
| 1 | pub const panic = @import("compiler_rt/common.zig").panic; | |
| 22 | 2 | |
| 23 | 3 | comptime { |
| 24 | // These files do their own comptime exporting logic. | |
| 25 | 4 | _ = @import("compiler_rt/atomics.zig"); |
| 26 | if (builtin.zig_backend != .stage2_llvm) { // TODO | |
| 27 | _ = @import("compiler_rt/clear_cache.zig").clear_cache; | |
| 28 | } | |
| 29 | ||
| 30 | const __extenddftf2 = @import("compiler_rt/extendXfYf2.zig").__extenddftf2; | |
| 31 | @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage }); | |
| 32 | const __extendsftf2 = @import("compiler_rt/extendXfYf2.zig").__extendsftf2; | |
| 33 | @export(__extendsftf2, .{ .name = "__extendsftf2", .linkage = linkage }); | |
| 34 | const __extendhfsf2 = @import("compiler_rt/extendXfYf2.zig").__extendhfsf2; | |
| 35 | @export(__extendhfsf2, .{ .name = "__extendhfsf2", .linkage = linkage }); | |
| 36 | const __extendhftf2 = @import("compiler_rt/extendXfYf2.zig").__extendhftf2; | |
| 37 | @export(__extendhftf2, .{ .name = "__extendhftf2", .linkage = linkage }); | |
| 38 | ||
| 39 | const __extendhfxf2 = @import("compiler_rt/extend_f80.zig").__extendhfxf2; | |
| 40 | @export(__extendhfxf2, .{ .name = "__extendhfxf2", .linkage = linkage }); | |
| 41 | const __extendsfxf2 = @import("compiler_rt/extend_f80.zig").__extendsfxf2; | |
| 42 | @export(__extendsfxf2, .{ .name = "__extendsfxf2", .linkage = linkage }); | |
| 43 | const __extenddfxf2 = @import("compiler_rt/extend_f80.zig").__extenddfxf2; | |
| 44 | @export(__extenddfxf2, .{ .name = "__extenddfxf2", .linkage = linkage }); | |
| 45 | const __extendxftf2 = @import("compiler_rt/extend_f80.zig").__extendxftf2; | |
| 46 | @export(__extendxftf2, .{ .name = "__extendxftf2", .linkage = linkage }); | |
| 47 | ||
| 48 | const __lesf2 = @import("compiler_rt/compareXf2.zig").__lesf2; | |
| 49 | @export(__lesf2, .{ .name = "__lesf2", .linkage = linkage }); | |
| 50 | const __ledf2 = @import("compiler_rt/compareXf2.zig").__ledf2; | |
| 51 | @export(__ledf2, .{ .name = "__ledf2", .linkage = linkage }); | |
| 52 | const __letf2 = @import("compiler_rt/compareXf2.zig").__letf2; | |
| 53 | @export(__letf2, .{ .name = "__letf2", .linkage = linkage }); | |
| 54 | const __lexf2 = @import("compiler_rt/compareXf2.zig").__lexf2; | |
| 55 | @export(__lexf2, .{ .name = "__lexf2", .linkage = linkage }); | |
| 56 | ||
| 57 | const __gesf2 = @import("compiler_rt/compareXf2.zig").__gesf2; | |
| 58 | @export(__gesf2, .{ .name = "__gesf2", .linkage = linkage }); | |
| 59 | const __gedf2 = @import("compiler_rt/compareXf2.zig").__gedf2; | |
| 60 | @export(__gedf2, .{ .name = "__gedf2", .linkage = linkage }); | |
| 61 | const __getf2 = @import("compiler_rt/compareXf2.zig").__getf2; | |
| 62 | @export(__getf2, .{ .name = "__getf2", .linkage = linkage }); | |
| 63 | const __gexf2 = @import("compiler_rt/compareXf2.zig").__gexf2; | |
| 64 | @export(__gexf2, .{ .name = "__gexf2", .linkage = linkage }); | |
| 65 | ||
| 66 | const __eqsf2 = @import("compiler_rt/compareXf2.zig").__eqsf2; | |
| 67 | @export(__eqsf2, .{ .name = "__eqsf2", .linkage = linkage }); | |
| 68 | const __eqdf2 = @import("compiler_rt/compareXf2.zig").__eqdf2; | |
| 69 | @export(__eqdf2, .{ .name = "__eqdf2", .linkage = linkage }); | |
| 70 | const __eqxf2 = @import("compiler_rt/compareXf2.zig").__eqxf2; | |
| 71 | @export(__eqxf2, .{ .name = "__eqxf2", .linkage = linkage }); | |
| 72 | ||
| 73 | const __ltsf2 = @import("compiler_rt/compareXf2.zig").__ltsf2; | |
| 74 | @export(__ltsf2, .{ .name = "__ltsf2", .linkage = linkage }); | |
| 75 | const __ltdf2 = @import("compiler_rt/compareXf2.zig").__ltdf2; | |
| 76 | @export(__ltdf2, .{ .name = "__ltdf2", .linkage = linkage }); | |
| 77 | const __ltxf2 = @import("compiler_rt/compareXf2.zig").__ltxf2; | |
| 78 | @export(__ltxf2, .{ .name = "__ltxf2", .linkage = linkage }); | |
| 79 | ||
| 80 | const __nesf2 = @import("compiler_rt/compareXf2.zig").__nesf2; | |
| 81 | @export(__nesf2, .{ .name = "__nesf2", .linkage = linkage }); | |
| 82 | const __nedf2 = @import("compiler_rt/compareXf2.zig").__nedf2; | |
| 83 | @export(__nedf2, .{ .name = "__nedf2", .linkage = linkage }); | |
| 84 | const __nexf2 = @import("compiler_rt/compareXf2.zig").__nexf2; | |
| 85 | @export(__nexf2, .{ .name = "__nexf2", .linkage = linkage }); | |
| 86 | ||
| 87 | const __gtsf2 = @import("compiler_rt/compareXf2.zig").__gtsf2; | |
| 88 | @export(__gtsf2, .{ .name = "__gtsf2", .linkage = linkage }); | |
| 89 | const __gtdf2 = @import("compiler_rt/compareXf2.zig").__gtdf2; | |
| 90 | @export(__gtdf2, .{ .name = "__gtdf2", .linkage = linkage }); | |
| 91 | const __gtxf2 = @import("compiler_rt/compareXf2.zig").__gtxf2; | |
| 92 | @export(__gtxf2, .{ .name = "__gtxf2", .linkage = linkage }); | |
| 93 | ||
| 94 | if (!is_test) { | |
| 95 | @export(__lesf2, .{ .name = "__cmpsf2", .linkage = linkage }); | |
| 96 | @export(__ledf2, .{ .name = "__cmpdf2", .linkage = linkage }); | |
| 97 | @export(__letf2, .{ .name = "__cmptf2", .linkage = linkage }); | |
| 98 | @export(__letf2, .{ .name = "__eqtf2", .linkage = linkage }); | |
| 99 | @export(__letf2, .{ .name = "__lttf2", .linkage = linkage }); | |
| 100 | @export(__getf2, .{ .name = "__gttf2", .linkage = linkage }); | |
| 101 | @export(__letf2, .{ .name = "__netf2", .linkage = linkage }); | |
| 102 | @export(__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage }); | |
| 103 | } | |
| 104 | ||
| 105 | if (builtin.os.tag == .windows) { | |
| 106 | // Default stack-probe functions emitted by LLVM | |
| 107 | if (is_mingw) { | |
| 108 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | |
| 109 | @export(_chkstk, .{ .name = "_alloca", .linkage = strong_linkage }); | |
| 110 | const ___chkstk_ms = @import("compiler_rt/stack_probe.zig").___chkstk_ms; | |
| 111 | @export(___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = strong_linkage }); | |
| 112 | } else if (!builtin.link_libc) { | |
| 113 | // This symbols are otherwise exported by MSVCRT.lib | |
| 114 | const _chkstk = @import("compiler_rt/stack_probe.zig")._chkstk; | |
| 115 | @export(_chkstk, .{ .name = "_chkstk", .linkage = strong_linkage }); | |
| 116 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | |
| 117 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | |
| 118 | } | |
| 119 | ||
| 120 | switch (arch) { | |
| 121 | .i386 => { | |
| 122 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; | |
| 123 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); | |
| 124 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | |
| 125 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | |
| 126 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; | |
| 127 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); | |
| 128 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | |
| 129 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | |
| 130 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | |
| 131 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | |
| 132 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | |
| 133 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | |
| 134 | }, | |
| 135 | .x86_64 => { | |
| 136 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | |
| 137 | // that LLVM expects compiler-rt to have. | |
| 138 | const __divti3_windows_x86_64 = @import("compiler_rt/divti3.zig").__divti3_windows_x86_64; | |
| 139 | @export(__divti3_windows_x86_64, .{ .name = "__divti3", .linkage = linkage }); | |
| 140 | const __modti3_windows_x86_64 = @import("compiler_rt/modti3.zig").__modti3_windows_x86_64; | |
| 141 | @export(__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = linkage }); | |
| 142 | const __multi3_windows_x86_64 = @import("compiler_rt/multi3.zig").__multi3_windows_x86_64; | |
| 143 | @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = linkage }); | |
| 144 | const __udivti3_windows_x86_64 = @import("compiler_rt/udivti3.zig").__udivti3_windows_x86_64; | |
| 145 | @export(__udivti3_windows_x86_64, .{ .name = "__udivti3", .linkage = linkage }); | |
| 146 | const __udivmodti4_windows_x86_64 = @import("compiler_rt/udivmodti4.zig").__udivmodti4_windows_x86_64; | |
| 147 | @export(__udivmodti4_windows_x86_64, .{ .name = "__udivmodti4", .linkage = linkage }); | |
| 148 | const __umodti3_windows_x86_64 = @import("compiler_rt/umodti3.zig").__umodti3_windows_x86_64; | |
| 149 | @export(__umodti3_windows_x86_64, .{ .name = "__umodti3", .linkage = linkage }); | |
| 150 | }, | |
| 151 | else => {}, | |
| 152 | } | |
| 153 | if (arch.isAARCH64()) { | |
| 154 | const __chkstk = @import("compiler_rt/stack_probe.zig").__chkstk; | |
| 155 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | |
| 156 | const __divti3_windows = @import("compiler_rt/divti3.zig").__divti3; | |
| 157 | @export(__divti3_windows, .{ .name = "__divti3", .linkage = linkage }); | |
| 158 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | |
| 159 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | |
| 160 | const __udivti3_windows = @import("compiler_rt/udivti3.zig").__udivti3; | |
| 161 | @export(__udivti3_windows, .{ .name = "__udivti3", .linkage = linkage }); | |
| 162 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | |
| 163 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | |
| 164 | } | |
| 165 | } else { | |
| 166 | const __divti3 = @import("compiler_rt/divti3.zig").__divti3; | |
| 167 | @export(__divti3, .{ .name = "__divti3", .linkage = linkage }); | |
| 168 | const __modti3 = @import("compiler_rt/modti3.zig").__modti3; | |
| 169 | @export(__modti3, .{ .name = "__modti3", .linkage = linkage }); | |
| 170 | const __multi3 = @import("compiler_rt/multi3.zig").__multi3; | |
| 171 | @export(__multi3, .{ .name = "__multi3", .linkage = linkage }); | |
| 172 | const __udivti3 = @import("compiler_rt/udivti3.zig").__udivti3; | |
| 173 | @export(__udivti3, .{ .name = "__udivti3", .linkage = linkage }); | |
| 174 | const __udivmodti4 = @import("compiler_rt/udivmodti4.zig").__udivmodti4; | |
| 175 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = linkage }); | |
| 176 | const __umodti3 = @import("compiler_rt/umodti3.zig").__umodti3; | |
| 177 | @export(__umodti3, .{ .name = "__umodti3", .linkage = linkage }); | |
| 178 | } | |
| 179 | ||
| 180 | const __truncdfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfhf2; | |
| 181 | @export(__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage }); | |
| 182 | const __trunctfhf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfhf2; | |
| 183 | @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage }); | |
| 184 | const __trunctfdf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfdf2; | |
| 185 | @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage }); | |
| 186 | const __trunctfsf2 = @import("compiler_rt/truncXfYf2.zig").__trunctfsf2; | |
| 187 | @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage }); | |
| 188 | ||
| 189 | const __truncdfsf2 = @import("compiler_rt/truncXfYf2.zig").__truncdfsf2; | |
| 190 | @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage }); | |
| 191 | ||
| 192 | const __truncxfhf2 = @import("compiler_rt/trunc_f80.zig").__truncxfhf2; | |
| 193 | @export(__truncxfhf2, .{ .name = "__truncxfhf2", .linkage = linkage }); | |
| 194 | const __truncxfsf2 = @import("compiler_rt/trunc_f80.zig").__truncxfsf2; | |
| 195 | @export(__truncxfsf2, .{ .name = "__truncxfsf2", .linkage = linkage }); | |
| 196 | const __truncxfdf2 = @import("compiler_rt/trunc_f80.zig").__truncxfdf2; | |
| 197 | @export(__truncxfdf2, .{ .name = "__truncxfdf2", .linkage = linkage }); | |
| 198 | const __trunctfxf2 = @import("compiler_rt/trunc_f80.zig").__trunctfxf2; | |
| 199 | @export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = linkage }); | |
| 200 | ||
| 201 | switch (arch) { | |
| 202 | .i386, | |
| 203 | .x86_64, | |
| 204 | => { | |
| 205 | const zig_probe_stack = @import("compiler_rt/stack_probe.zig").zig_probe_stack; | |
| 206 | @export(zig_probe_stack, .{ | |
| 207 | .name = "__zig_probe_stack", | |
| 208 | .linkage = linkage, | |
| 209 | }); | |
| 210 | }, | |
| 211 | else => {}, | |
| 212 | } | |
| 213 | ||
| 214 | const __unordsf2 = @import("compiler_rt/compareXf2.zig").__unordsf2; | |
| 215 | @export(__unordsf2, .{ .name = "__unordsf2", .linkage = linkage }); | |
| 216 | const __unorddf2 = @import("compiler_rt/compareXf2.zig").__unorddf2; | |
| 217 | @export(__unorddf2, .{ .name = "__unorddf2", .linkage = linkage }); | |
| 218 | const __unordtf2 = @import("compiler_rt/compareXf2.zig").__unordtf2; | |
| 219 | @export(__unordtf2, .{ .name = "__unordtf2", .linkage = linkage }); | |
| 220 | ||
| 221 | const __addsf3 = @import("compiler_rt/addXf3.zig").__addsf3; | |
| 222 | @export(__addsf3, .{ .name = "__addsf3", .linkage = linkage }); | |
| 223 | const __adddf3 = @import("compiler_rt/addXf3.zig").__adddf3; | |
| 224 | @export(__adddf3, .{ .name = "__adddf3", .linkage = linkage }); | |
| 225 | const __addxf3 = @import("compiler_rt/addXf3.zig").__addxf3; | |
| 226 | @export(__addxf3, .{ .name = "__addxf3", .linkage = linkage }); | |
| 227 | const __addtf3 = @import("compiler_rt/addXf3.zig").__addtf3; | |
| 228 | @export(__addtf3, .{ .name = "__addtf3", .linkage = linkage }); | |
| 229 | ||
| 230 | const __subsf3 = @import("compiler_rt/addXf3.zig").__subsf3; | |
| 231 | @export(__subsf3, .{ .name = "__subsf3", .linkage = linkage }); | |
| 232 | const __subdf3 = @import("compiler_rt/addXf3.zig").__subdf3; | |
| 233 | @export(__subdf3, .{ .name = "__subdf3", .linkage = linkage }); | |
| 234 | const __subxf3 = @import("compiler_rt/addXf3.zig").__subxf3; | |
| 235 | @export(__subxf3, .{ .name = "__subxf3", .linkage = linkage }); | |
| 236 | const __subtf3 = @import("compiler_rt/addXf3.zig").__subtf3; | |
| 237 | @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage }); | |
| 238 | ||
| 239 | const __mulsf3 = @import("compiler_rt/mulXf3.zig").__mulsf3; | |
| 240 | @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage }); | |
| 241 | const __muldf3 = @import("compiler_rt/mulXf3.zig").__muldf3; | |
| 242 | @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage }); | |
| 243 | const __mulxf3 = @import("compiler_rt/mulXf3.zig").__mulxf3; | |
| 244 | @export(__mulxf3, .{ .name = "__mulxf3", .linkage = linkage }); | |
| 245 | const __multf3 = @import("compiler_rt/mulXf3.zig").__multf3; | |
| 246 | @export(__multf3, .{ .name = "__multf3", .linkage = linkage }); | |
| 247 | ||
| 248 | const __divsf3 = @import("compiler_rt/divsf3.zig").__divsf3; | |
| 249 | @export(__divsf3, .{ .name = "__divsf3", .linkage = linkage }); | |
| 250 | const __divdf3 = @import("compiler_rt/divdf3.zig").__divdf3; | |
| 251 | @export(__divdf3, .{ .name = "__divdf3", .linkage = linkage }); | |
| 252 | const __divxf3 = @import("compiler_rt/divxf3.zig").__divxf3; | |
| 253 | @export(__divxf3, .{ .name = "__divxf3", .linkage = linkage }); | |
| 254 | const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3; | |
| 255 | @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage }); | |
| 256 | ||
| 257 | // Integer Bit operations | |
| 258 | const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2; | |
| 259 | @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage }); | |
| 260 | const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2; | |
| 261 | @export(__clzdi2, .{ .name = "__clzdi2", .linkage = linkage }); | |
| 262 | const __clzti2 = @import("compiler_rt/count0bits.zig").__clzti2; | |
| 263 | @export(__clzti2, .{ .name = "__clzti2", .linkage = linkage }); | |
| 264 | const __ctzsi2 = @import("compiler_rt/count0bits.zig").__ctzsi2; | |
| 265 | @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = linkage }); | |
| 266 | const __ctzdi2 = @import("compiler_rt/count0bits.zig").__ctzdi2; | |
| 267 | @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = linkage }); | |
| 268 | const __ctzti2 = @import("compiler_rt/count0bits.zig").__ctzti2; | |
| 269 | @export(__ctzti2, .{ .name = "__ctzti2", .linkage = linkage }); | |
| 270 | const __ffssi2 = @import("compiler_rt/count0bits.zig").__ffssi2; | |
| 271 | @export(__ffssi2, .{ .name = "__ffssi2", .linkage = linkage }); | |
| 272 | const __ffsdi2 = @import("compiler_rt/count0bits.zig").__ffsdi2; | |
| 273 | @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage }); | |
| 274 | const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2; | |
| 275 | @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage }); | |
| 276 | const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2; | |
| 277 | @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage }); | |
| 278 | const __paritydi2 = @import("compiler_rt/parity.zig").__paritydi2; | |
| 279 | @export(__paritydi2, .{ .name = "__paritydi2", .linkage = linkage }); | |
| 280 | const __parityti2 = @import("compiler_rt/parity.zig").__parityti2; | |
| 281 | @export(__parityti2, .{ .name = "__parityti2", .linkage = linkage }); | |
| 282 | const __popcountsi2 = @import("compiler_rt/popcount.zig").__popcountsi2; | |
| 283 | @export(__popcountsi2, .{ .name = "__popcountsi2", .linkage = linkage }); | |
| 284 | const __popcountdi2 = @import("compiler_rt/popcount.zig").__popcountdi2; | |
| 285 | @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage }); | |
| 286 | const __popcountti2 = @import("compiler_rt/popcount.zig").__popcountti2; | |
| 287 | @export(__popcountti2, .{ .name = "__popcountti2", .linkage = linkage }); | |
| 288 | const __bswapsi2 = @import("compiler_rt/bswap.zig").__bswapsi2; | |
| 289 | @export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = linkage }); | |
| 290 | const __bswapdi2 = @import("compiler_rt/bswap.zig").__bswapdi2; | |
| 291 | @export(__bswapdi2, .{ .name = "__bswapdi2", .linkage = linkage }); | |
| 292 | const __bswapti2 = @import("compiler_rt/bswap.zig").__bswapti2; | |
| 293 | @export(__bswapti2, .{ .name = "__bswapti2", .linkage = linkage }); | |
| 294 | ||
| 295 | // Integral -> Float Conversion | |
| 296 | ||
| 297 | // Conversion to f32 | |
| 298 | const __floatsisf = @import("compiler_rt/floatXiYf.zig").__floatsisf; | |
| 299 | @export(__floatsisf, .{ .name = "__floatsisf", .linkage = linkage }); | |
| 300 | const __floatunsisf = @import("compiler_rt/floatXiYf.zig").__floatunsisf; | |
| 301 | @export(__floatunsisf, .{ .name = "__floatunsisf", .linkage = linkage }); | |
| 302 | ||
| 303 | const __floatundisf = @import("compiler_rt/floatXiYf.zig").__floatundisf; | |
| 304 | @export(__floatundisf, .{ .name = "__floatundisf", .linkage = linkage }); | |
| 305 | const __floatdisf = @import("compiler_rt/floatXiYf.zig").__floatdisf; | |
| 306 | @export(__floatdisf, .{ .name = "__floatdisf", .linkage = linkage }); | |
| 307 | ||
| 308 | const __floattisf = @import("compiler_rt/floatXiYf.zig").__floattisf; | |
| 309 | @export(__floattisf, .{ .name = "__floattisf", .linkage = linkage }); | |
| 310 | const __floatuntisf = @import("compiler_rt/floatXiYf.zig").__floatuntisf; | |
| 311 | @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = linkage }); | |
| 312 | ||
| 313 | // Conversion to f64 | |
| 314 | const __floatsidf = @import("compiler_rt/floatXiYf.zig").__floatsidf; | |
| 315 | @export(__floatsidf, .{ .name = "__floatsidf", .linkage = linkage }); | |
| 316 | const __floatunsidf = @import("compiler_rt/floatXiYf.zig").__floatunsidf; | |
| 317 | @export(__floatunsidf, .{ .name = "__floatunsidf", .linkage = linkage }); | |
| 318 | ||
| 319 | const __floatdidf = @import("compiler_rt/floatXiYf.zig").__floatdidf; | |
| 320 | @export(__floatdidf, .{ .name = "__floatdidf", .linkage = linkage }); | |
| 321 | const __floatundidf = @import("compiler_rt/floatXiYf.zig").__floatundidf; | |
| 322 | @export(__floatundidf, .{ .name = "__floatundidf", .linkage = linkage }); | |
| 323 | ||
| 324 | const __floattidf = @import("compiler_rt/floatXiYf.zig").__floattidf; | |
| 325 | @export(__floattidf, .{ .name = "__floattidf", .linkage = linkage }); | |
| 326 | const __floatuntidf = @import("compiler_rt/floatXiYf.zig").__floatuntidf; | |
| 327 | @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = linkage }); | |
| 328 | ||
| 329 | // Conversion to f80 | |
| 330 | const __floatsixf = @import("compiler_rt/floatXiYf.zig").__floatsixf; | |
| 331 | @export(__floatsixf, .{ .name = "__floatsixf", .linkage = linkage }); | |
| 332 | const __floatunsixf = @import("compiler_rt/floatXiYf.zig").__floatunsixf; | |
| 333 | @export(__floatunsixf, .{ .name = "__floatunsixf", .linkage = linkage }); | |
| 334 | ||
| 335 | const __floatdixf = @import("compiler_rt/floatXiYf.zig").__floatdixf; | |
| 336 | @export(__floatdixf, .{ .name = "__floatdixf", .linkage = linkage }); | |
| 337 | const __floatundixf = @import("compiler_rt/floatXiYf.zig").__floatundixf; | |
| 338 | @export(__floatundixf, .{ .name = "__floatundixf", .linkage = linkage }); | |
| 339 | ||
| 340 | const __floattixf = @import("compiler_rt/floatXiYf.zig").__floattixf; | |
| 341 | @export(__floattixf, .{ .name = "__floattixf", .linkage = linkage }); | |
| 342 | const __floatuntixf = @import("compiler_rt/floatXiYf.zig").__floatuntixf; | |
| 343 | @export(__floatuntixf, .{ .name = "__floatuntixf", .linkage = linkage }); | |
| 344 | ||
| 345 | // Conversion to f128 | |
| 346 | const __floatsitf = @import("compiler_rt/floatXiYf.zig").__floatsitf; | |
| 347 | @export(__floatsitf, .{ .name = "__floatsitf", .linkage = linkage }); | |
| 348 | const __floatunsitf = @import("compiler_rt/floatXiYf.zig").__floatunsitf; | |
| 349 | @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = linkage }); | |
| 350 | ||
| 351 | const __floatditf = @import("compiler_rt/floatXiYf.zig").__floatditf; | |
| 352 | @export(__floatditf, .{ .name = "__floatditf", .linkage = linkage }); | |
| 353 | const __floatunditf = @import("compiler_rt/floatXiYf.zig").__floatunditf; | |
| 354 | @export(__floatunditf, .{ .name = "__floatunditf", .linkage = linkage }); | |
| 355 | ||
| 356 | const __floattitf = @import("compiler_rt/floatXiYf.zig").__floattitf; | |
| 357 | @export(__floattitf, .{ .name = "__floattitf", .linkage = linkage }); | |
| 358 | const __floatuntitf = @import("compiler_rt/floatXiYf.zig").__floatuntitf; | |
| 359 | @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = linkage }); | |
| 360 | ||
| 361 | // Float -> Integral Conversion | |
| 362 | ||
| 363 | // Conversion from f32 | |
| 364 | const __fixsfsi = @import("compiler_rt/fixXfYi.zig").__fixsfsi; | |
| 365 | @export(__fixsfsi, .{ .name = "__fixsfsi", .linkage = linkage }); | |
| 366 | const __fixunssfsi = @import("compiler_rt/fixXfYi.zig").__fixunssfsi; | |
| 367 | @export(__fixunssfsi, .{ .name = "__fixunssfsi", .linkage = linkage }); | |
| 368 | ||
| 369 | const __fixsfdi = @import("compiler_rt/fixXfYi.zig").__fixsfdi; | |
| 370 | @export(__fixsfdi, .{ .name = "__fixsfdi", .linkage = linkage }); | |
| 371 | const __fixunssfdi = @import("compiler_rt/fixXfYi.zig").__fixunssfdi; | |
| 372 | @export(__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = linkage }); | |
| 373 | ||
| 374 | const __fixsfti = @import("compiler_rt/fixXfYi.zig").__fixsfti; | |
| 375 | @export(__fixsfti, .{ .name = "__fixsfti", .linkage = linkage }); | |
| 376 | const __fixunssfti = @import("compiler_rt/fixXfYi.zig").__fixunssfti; | |
| 377 | @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = linkage }); | |
| 378 | ||
| 379 | // Conversion from f64 | |
| 380 | const __fixdfsi = @import("compiler_rt/fixXfYi.zig").__fixdfsi; | |
| 381 | @export(__fixdfsi, .{ .name = "__fixdfsi", .linkage = linkage }); | |
| 382 | const __fixunsdfsi = @import("compiler_rt/fixXfYi.zig").__fixunsdfsi; | |
| 383 | @export(__fixunsdfsi, .{ .name = "__fixunsdfsi", .linkage = linkage }); | |
| 384 | ||
| 385 | const __fixdfdi = @import("compiler_rt/fixXfYi.zig").__fixdfdi; | |
| 386 | @export(__fixdfdi, .{ .name = "__fixdfdi", .linkage = linkage }); | |
| 387 | const __fixunsdfdi = @import("compiler_rt/fixXfYi.zig").__fixunsdfdi; | |
| 388 | @export(__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = linkage }); | |
| 389 | ||
| 390 | const __fixdfti = @import("compiler_rt/fixXfYi.zig").__fixdfti; | |
| 391 | @export(__fixdfti, .{ .name = "__fixdfti", .linkage = linkage }); | |
| 392 | const __fixunsdfti = @import("compiler_rt/fixXfYi.zig").__fixunsdfti; | |
| 393 | @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = linkage }); | |
| 394 | ||
| 395 | // Conversion from f80 | |
| 396 | const __fixxfsi = @import("compiler_rt/fixXfYi.zig").__fixxfsi; | |
| 397 | @export(__fixxfsi, .{ .name = "__fixxfsi", .linkage = linkage }); | |
| 398 | const __fixunsxfsi = @import("compiler_rt/fixXfYi.zig").__fixunsxfsi; | |
| 399 | @export(__fixunsxfsi, .{ .name = "__fixunsxfsi", .linkage = linkage }); | |
| 400 | ||
| 401 | const __fixxfdi = @import("compiler_rt/fixXfYi.zig").__fixxfdi; | |
| 402 | @export(__fixxfdi, .{ .name = "__fixxfdi", .linkage = linkage }); | |
| 403 | const __fixunsxfdi = @import("compiler_rt/fixXfYi.zig").__fixunsxfdi; | |
| 404 | @export(__fixunsxfdi, .{ .name = "__fixunsxfdi", .linkage = linkage }); | |
| 405 | ||
| 406 | const __fixxfti = @import("compiler_rt/fixXfYi.zig").__fixxfti; | |
| 407 | @export(__fixxfti, .{ .name = "__fixxfti", .linkage = linkage }); | |
| 408 | const __fixunsxfti = @import("compiler_rt/fixXfYi.zig").__fixunsxfti; | |
| 409 | @export(__fixunsxfti, .{ .name = "__fixunsxfti", .linkage = linkage }); | |
| 410 | ||
| 411 | // Conversion from f128 | |
| 412 | const __fixtfsi = @import("compiler_rt/fixXfYi.zig").__fixtfsi; | |
| 413 | @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = linkage }); | |
| 414 | const __fixunstfsi = @import("compiler_rt/fixXfYi.zig").__fixunstfsi; | |
| 415 | @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = linkage }); | |
| 416 | ||
| 417 | const __fixtfdi = @import("compiler_rt/fixXfYi.zig").__fixtfdi; | |
| 418 | @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = linkage }); | |
| 419 | const __fixunstfdi = @import("compiler_rt/fixXfYi.zig").__fixunstfdi; | |
| 420 | @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = linkage }); | |
| 421 | ||
| 422 | const __fixtfti = @import("compiler_rt/fixXfYi.zig").__fixtfti; | |
| 423 | @export(__fixtfti, .{ .name = "__fixtfti", .linkage = linkage }); | |
| 424 | const __fixunstfti = @import("compiler_rt/fixXfYi.zig").__fixunstfti; | |
| 425 | @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = linkage }); | |
| 426 | ||
| 427 | const __udivmoddi4 = @import("compiler_rt/int.zig").__udivmoddi4; | |
| 428 | @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = linkage }); | |
| 429 | ||
| 430 | const __truncsfhf2 = @import("compiler_rt/truncXfYf2.zig").__truncsfhf2; | |
| 431 | @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage }); | |
| 432 | if (!is_test) { | |
| 433 | @export(__truncsfhf2, .{ .name = "__gnu_f2h_ieee", .linkage = linkage }); | |
| 434 | } | |
| 435 | const __extendsfdf2 = @import("compiler_rt/extendXfYf2.zig").__extendsfdf2; | |
| 436 | @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage }); | |
| 437 | ||
| 438 | if (is_darwin) { | |
| 439 | const __isPlatformVersionAtLeast = @import("compiler_rt/os_version_check.zig").__isPlatformVersionAtLeast; | |
| 440 | @export(__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = linkage }); | |
| 441 | } | |
| 442 | ||
| 443 | // Integer Arithmetic | |
| 444 | const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3; | |
| 445 | @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage }); | |
| 446 | const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3; | |
| 447 | @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage }); | |
| 448 | const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3; | |
| 449 | @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage }); | |
| 450 | const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3; | |
| 451 | @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage }); | |
| 452 | const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3; | |
| 453 | @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage }); | |
| 454 | const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3; | |
| 455 | @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage }); | |
| 456 | const __negsi2 = @import("compiler_rt/negXi2.zig").__negsi2; | |
| 457 | @export(__negsi2, .{ .name = "__negsi2", .linkage = linkage }); | |
| 458 | const __negdi2 = @import("compiler_rt/negXi2.zig").__negdi2; | |
| 459 | @export(__negdi2, .{ .name = "__negdi2", .linkage = linkage }); | |
| 460 | const __negti2 = @import("compiler_rt/negXi2.zig").__negti2; | |
| 461 | @export(__negti2, .{ .name = "__negti2", .linkage = linkage }); | |
| 462 | ||
| 463 | const __mulsi3 = @import("compiler_rt/int.zig").__mulsi3; | |
| 464 | @export(__mulsi3, .{ .name = "__mulsi3", .linkage = linkage }); | |
| 465 | const __muldi3 = @import("compiler_rt/muldi3.zig").__muldi3; | |
| 466 | @export(__muldi3, .{ .name = "__muldi3", .linkage = linkage }); | |
| 467 | const __divmoddi4 = @import("compiler_rt/int.zig").__divmoddi4; | |
| 468 | @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = linkage }); | |
| 469 | const __divsi3 = @import("compiler_rt/int.zig").__divsi3; | |
| 470 | @export(__divsi3, .{ .name = "__divsi3", .linkage = linkage }); | |
| 471 | const __divdi3 = @import("compiler_rt/int.zig").__divdi3; | |
| 472 | @export(__divdi3, .{ .name = "__divdi3", .linkage = linkage }); | |
| 473 | const __udivsi3 = @import("compiler_rt/int.zig").__udivsi3; | |
| 474 | @export(__udivsi3, .{ .name = "__udivsi3", .linkage = linkage }); | |
| 475 | const __udivdi3 = @import("compiler_rt/int.zig").__udivdi3; | |
| 476 | @export(__udivdi3, .{ .name = "__udivdi3", .linkage = linkage }); | |
| 477 | const __modsi3 = @import("compiler_rt/int.zig").__modsi3; | |
| 478 | @export(__modsi3, .{ .name = "__modsi3", .linkage = linkage }); | |
| 479 | const __moddi3 = @import("compiler_rt/int.zig").__moddi3; | |
| 480 | @export(__moddi3, .{ .name = "__moddi3", .linkage = linkage }); | |
| 481 | const __umodsi3 = @import("compiler_rt/int.zig").__umodsi3; | |
| 482 | @export(__umodsi3, .{ .name = "__umodsi3", .linkage = linkage }); | |
| 483 | const __umoddi3 = @import("compiler_rt/int.zig").__umoddi3; | |
| 484 | @export(__umoddi3, .{ .name = "__umoddi3", .linkage = linkage }); | |
| 485 | const __divmodsi4 = @import("compiler_rt/int.zig").__divmodsi4; | |
| 486 | @export(__divmodsi4, .{ .name = "__divmodsi4", .linkage = linkage }); | |
| 487 | const __udivmodsi4 = @import("compiler_rt/int.zig").__udivmodsi4; | |
| 488 | @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage }); | |
| 489 | ||
| 490 | // Integer Arithmetic with trapping overflow | |
| 491 | const __absvsi2 = @import("compiler_rt/absv.zig").__absvsi2; | |
| 492 | @export(__absvsi2, .{ .name = "__absvsi2", .linkage = linkage }); | |
| 493 | const __absvdi2 = @import("compiler_rt/absv.zig").__absvdi2; | |
| 494 | @export(__absvdi2, .{ .name = "__absvdi2", .linkage = linkage }); | |
| 495 | const __absvti2 = @import("compiler_rt/absv.zig").__absvti2; | |
| 496 | @export(__absvti2, .{ .name = "__absvti2", .linkage = linkage }); | |
| 497 | const __negvsi2 = @import("compiler_rt/negv.zig").__negvsi2; | |
| 498 | @export(__negvsi2, .{ .name = "__negvsi2", .linkage = linkage }); | |
| 499 | const __negvdi2 = @import("compiler_rt/negv.zig").__negvdi2; | |
| 500 | @export(__negvdi2, .{ .name = "__negvdi2", .linkage = linkage }); | |
| 501 | const __negvti2 = @import("compiler_rt/negv.zig").__negvti2; | |
| 502 | @export(__negvti2, .{ .name = "__negvti2", .linkage = linkage }); | |
| 503 | ||
| 504 | // Integer arithmetic which returns if overflow | |
| 505 | const __addosi4 = @import("compiler_rt/addo.zig").__addosi4; | |
| 506 | @export(__addosi4, .{ .name = "__addosi4", .linkage = linkage }); | |
| 507 | const __addodi4 = @import("compiler_rt/addo.zig").__addodi4; | |
| 508 | @export(__addodi4, .{ .name = "__addodi4", .linkage = linkage }); | |
| 509 | const __addoti4 = @import("compiler_rt/addo.zig").__addoti4; | |
| 510 | @export(__addoti4, .{ .name = "__addoti4", .linkage = linkage }); | |
| 511 | const __subosi4 = @import("compiler_rt/subo.zig").__subosi4; | |
| 512 | @export(__subosi4, .{ .name = "__subosi4", .linkage = linkage }); | |
| 513 | const __subodi4 = @import("compiler_rt/subo.zig").__subodi4; | |
| 514 | @export(__subodi4, .{ .name = "__subodi4", .linkage = linkage }); | |
| 515 | const __suboti4 = @import("compiler_rt/subo.zig").__suboti4; | |
| 516 | @export(__suboti4, .{ .name = "__suboti4", .linkage = linkage }); | |
| 517 | const __mulosi4 = @import("compiler_rt/mulo.zig").__mulosi4; | |
| 518 | @export(__mulosi4, .{ .name = "__mulosi4", .linkage = linkage }); | |
| 519 | const __mulodi4 = @import("compiler_rt/mulo.zig").__mulodi4; | |
| 520 | @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); | |
| 521 | const __muloti4 = @import("compiler_rt/mulo.zig").__muloti4; | |
| 522 | @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage }); | |
| 523 | ||
| 524 | // Integer Comparison | |
| 525 | // (a < b) => 0 | |
| 526 | // (a == b) => 1 | |
| 527 | // (a > b) => 2 | |
| 528 | const __cmpsi2 = @import("compiler_rt/cmp.zig").__cmpsi2; | |
| 529 | @export(__cmpsi2, .{ .name = "__cmpsi2", .linkage = linkage }); | |
| 530 | const __cmpdi2 = @import("compiler_rt/cmp.zig").__cmpdi2; | |
| 531 | @export(__cmpdi2, .{ .name = "__cmpdi2", .linkage = linkage }); | |
| 532 | const __cmpti2 = @import("compiler_rt/cmp.zig").__cmpti2; | |
| 533 | @export(__cmpti2, .{ .name = "__cmpti2", .linkage = linkage }); | |
| 534 | const __ucmpsi2 = @import("compiler_rt/cmp.zig").__ucmpsi2; | |
| 535 | @export(__ucmpsi2, .{ .name = "__ucmpsi2", .linkage = linkage }); | |
| 536 | const __ucmpdi2 = @import("compiler_rt/cmp.zig").__ucmpdi2; | |
| 537 | @export(__ucmpdi2, .{ .name = "__ucmpdi2", .linkage = linkage }); | |
| 538 | const __ucmpti2 = @import("compiler_rt/cmp.zig").__ucmpti2; | |
| 539 | @export(__ucmpti2, .{ .name = "__ucmpti2", .linkage = linkage }); | |
| 540 | ||
| 541 | // missing: Floating point raised to integer power | |
| 542 | ||
| 543 | // missing: Complex arithmetic | |
| 544 | // (a + ib) * (c + id) | |
| 545 | // (a + ib) / (c + id) | |
| 546 | ||
| 547 | const __negsf2 = @import("compiler_rt/negXf2.zig").__negsf2; | |
| 548 | @export(__negsf2, .{ .name = "__negsf2", .linkage = linkage }); | |
| 549 | const __negdf2 = @import("compiler_rt/negXf2.zig").__negdf2; | |
| 550 | @export(__negdf2, .{ .name = "__negdf2", .linkage = linkage }); | |
| 551 | ||
| 552 | if (builtin.link_libc and os_tag == .openbsd) { | |
| 553 | const __emutls_get_address = @import("compiler_rt/emutls.zig").__emutls_get_address; | |
| 554 | @export(__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = linkage }); | |
| 555 | } | |
| 556 | ||
| 557 | if ((arch.isARM() or arch.isThumb()) and !is_test) { | |
| 558 | const __aeabi_unwind_cpp_pr0 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr0; | |
| 559 | @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = linkage }); | |
| 560 | const __aeabi_unwind_cpp_pr1 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr1; | |
| 561 | @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = linkage }); | |
| 562 | const __aeabi_unwind_cpp_pr2 = @import("compiler_rt/arm.zig").__aeabi_unwind_cpp_pr2; | |
| 563 | @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = linkage }); | |
| 564 | ||
| 565 | @export(__muldi3, .{ .name = "__aeabi_lmul", .linkage = linkage }); | |
| 566 | ||
| 567 | const __aeabi_ldivmod = @import("compiler_rt/arm.zig").__aeabi_ldivmod; | |
| 568 | @export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = linkage }); | |
| 569 | const __aeabi_uldivmod = @import("compiler_rt/arm.zig").__aeabi_uldivmod; | |
| 570 | @export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = linkage }); | |
| 571 | ||
| 572 | @export(__divsi3, .{ .name = "__aeabi_idiv", .linkage = linkage }); | |
| 573 | const __aeabi_idivmod = @import("compiler_rt/arm.zig").__aeabi_idivmod; | |
| 574 | @export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = linkage }); | |
| 575 | @export(__udivsi3, .{ .name = "__aeabi_uidiv", .linkage = linkage }); | |
| 576 | const __aeabi_uidivmod = @import("compiler_rt/arm.zig").__aeabi_uidivmod; | |
| 577 | @export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = linkage }); | |
| 578 | ||
| 579 | const __aeabi_memcpy = @import("compiler_rt/arm.zig").__aeabi_memcpy; | |
| 580 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = linkage }); | |
| 581 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy4", .linkage = linkage }); | |
| 582 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy8", .linkage = linkage }); | |
| 583 | ||
| 584 | const __aeabi_memmove = @import("compiler_rt/arm.zig").__aeabi_memmove; | |
| 585 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = linkage }); | |
| 586 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove4", .linkage = linkage }); | |
| 587 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove8", .linkage = linkage }); | |
| 588 | ||
| 589 | const __aeabi_memset = @import("compiler_rt/arm.zig").__aeabi_memset; | |
| 590 | @export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = linkage }); | |
| 591 | @export(__aeabi_memset, .{ .name = "__aeabi_memset4", .linkage = linkage }); | |
| 592 | @export(__aeabi_memset, .{ .name = "__aeabi_memset8", .linkage = linkage }); | |
| 593 | ||
| 594 | const __aeabi_memclr = @import("compiler_rt/arm.zig").__aeabi_memclr; | |
| 595 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = linkage }); | |
| 596 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage }); | |
| 597 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage }); | |
| 598 | ||
| 599 | if (os_tag == .linux) { | |
| 600 | const __aeabi_read_tp = @import("compiler_rt/arm.zig").__aeabi_read_tp; | |
| 601 | @export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage }); | |
| 602 | } | |
| 603 | ||
| 604 | const __aeabi_f2d = @import("compiler_rt/extendXfYf2.zig").__aeabi_f2d; | |
| 605 | @export(__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage }); | |
| 606 | const __aeabi_i2d = @import("compiler_rt/floatXiYf.zig").__aeabi_i2d; | |
| 607 | @export(__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage }); | |
| 608 | const __aeabi_l2d = @import("compiler_rt/floatXiYf.zig").__aeabi_l2d; | |
| 609 | @export(__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = linkage }); | |
| 610 | const __aeabi_l2f = @import("compiler_rt/floatXiYf.zig").__aeabi_l2f; | |
| 611 | @export(__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = linkage }); | |
| 612 | const __aeabi_ui2d = @import("compiler_rt/floatXiYf.zig").__aeabi_ui2d; | |
| 613 | @export(__aeabi_ui2d, .{ .name = "__aeabi_ui2d", .linkage = linkage }); | |
| 614 | const __aeabi_ul2d = @import("compiler_rt/floatXiYf.zig").__aeabi_ul2d; | |
| 615 | @export(__aeabi_ul2d, .{ .name = "__aeabi_ul2d", .linkage = linkage }); | |
| 616 | const __aeabi_ui2f = @import("compiler_rt/floatXiYf.zig").__aeabi_ui2f; | |
| 617 | @export(__aeabi_ui2f, .{ .name = "__aeabi_ui2f", .linkage = linkage }); | |
| 618 | const __aeabi_ul2f = @import("compiler_rt/floatXiYf.zig").__aeabi_ul2f; | |
| 619 | @export(__aeabi_ul2f, .{ .name = "__aeabi_ul2f", .linkage = linkage }); | |
| 620 | ||
| 621 | const __aeabi_fneg = @import("compiler_rt/negXf2.zig").__aeabi_fneg; | |
| 622 | @export(__aeabi_fneg, .{ .name = "__aeabi_fneg", .linkage = linkage }); | |
| 623 | const __aeabi_dneg = @import("compiler_rt/negXf2.zig").__aeabi_dneg; | |
| 624 | @export(__aeabi_dneg, .{ .name = "__aeabi_dneg", .linkage = linkage }); | |
| 625 | ||
| 626 | const __aeabi_fmul = @import("compiler_rt/mulXf3.zig").__aeabi_fmul; | |
| 627 | @export(__aeabi_fmul, .{ .name = "__aeabi_fmul", .linkage = linkage }); | |
| 628 | const __aeabi_dmul = @import("compiler_rt/mulXf3.zig").__aeabi_dmul; | |
| 629 | @export(__aeabi_dmul, .{ .name = "__aeabi_dmul", .linkage = linkage }); | |
| 630 | ||
| 631 | const __aeabi_d2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2h; | |
| 632 | @export(__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = linkage }); | |
| 633 | ||
| 634 | const __aeabi_f2ulz = @import("compiler_rt/fixXfYi.zig").__aeabi_f2ulz; | |
| 635 | @export(__aeabi_f2ulz, .{ .name = "__aeabi_f2ulz", .linkage = linkage }); | |
| 636 | const __aeabi_d2ulz = @import("compiler_rt/fixXfYi.zig").__aeabi_d2ulz; | |
| 637 | @export(__aeabi_d2ulz, .{ .name = "__aeabi_d2ulz", .linkage = linkage }); | |
| 638 | ||
| 639 | const __aeabi_f2lz = @import("compiler_rt/fixXfYi.zig").__aeabi_f2lz; | |
| 640 | @export(__aeabi_f2lz, .{ .name = "__aeabi_f2lz", .linkage = linkage }); | |
| 641 | const __aeabi_d2lz = @import("compiler_rt/fixXfYi.zig").__aeabi_d2lz; | |
| 642 | @export(__aeabi_d2lz, .{ .name = "__aeabi_d2lz", .linkage = linkage }); | |
| 643 | ||
| 644 | const __aeabi_d2uiz = @import("compiler_rt/fixXfYi.zig").__aeabi_d2uiz; | |
| 645 | @export(__aeabi_d2uiz, .{ .name = "__aeabi_d2uiz", .linkage = linkage }); | |
| 646 | ||
| 647 | const __aeabi_h2f = @import("compiler_rt/extendXfYf2.zig").__aeabi_h2f; | |
| 648 | @export(__aeabi_h2f, .{ .name = "__aeabi_h2f", .linkage = linkage }); | |
| 649 | const __aeabi_f2h = @import("compiler_rt/truncXfYf2.zig").__aeabi_f2h; | |
| 650 | @export(__aeabi_f2h, .{ .name = "__aeabi_f2h", .linkage = linkage }); | |
| 651 | ||
| 652 | const __aeabi_i2f = @import("compiler_rt/floatXiYf.zig").__aeabi_i2f; | |
| 653 | @export(__aeabi_i2f, .{ .name = "__aeabi_i2f", .linkage = linkage }); | |
| 654 | const __aeabi_d2f = @import("compiler_rt/truncXfYf2.zig").__aeabi_d2f; | |
| 655 | @export(__aeabi_d2f, .{ .name = "__aeabi_d2f", .linkage = linkage }); | |
| 656 | ||
| 657 | const __aeabi_fadd = @import("compiler_rt/addXf3.zig").__aeabi_fadd; | |
| 658 | @export(__aeabi_fadd, .{ .name = "__aeabi_fadd", .linkage = linkage }); | |
| 659 | const __aeabi_dadd = @import("compiler_rt/addXf3.zig").__aeabi_dadd; | |
| 660 | @export(__aeabi_dadd, .{ .name = "__aeabi_dadd", .linkage = linkage }); | |
| 661 | const __aeabi_fsub = @import("compiler_rt/addXf3.zig").__aeabi_fsub; | |
| 662 | @export(__aeabi_fsub, .{ .name = "__aeabi_fsub", .linkage = linkage }); | |
| 663 | const __aeabi_dsub = @import("compiler_rt/addXf3.zig").__aeabi_dsub; | |
| 664 | @export(__aeabi_dsub, .{ .name = "__aeabi_dsub", .linkage = linkage }); | |
| 665 | ||
| 666 | const __aeabi_f2uiz = @import("compiler_rt/fixXfYi.zig").__aeabi_f2uiz; | |
| 667 | @export(__aeabi_f2uiz, .{ .name = "__aeabi_f2uiz", .linkage = linkage }); | |
| 668 | ||
| 669 | const __aeabi_f2iz = @import("compiler_rt/fixXfYi.zig").__aeabi_f2iz; | |
| 670 | @export(__aeabi_f2iz, .{ .name = "__aeabi_f2iz", .linkage = linkage }); | |
| 671 | const __aeabi_d2iz = @import("compiler_rt/fixXfYi.zig").__aeabi_d2iz; | |
| 672 | @export(__aeabi_d2iz, .{ .name = "__aeabi_d2iz", .linkage = linkage }); | |
| 673 | ||
| 674 | const __aeabi_fdiv = @import("compiler_rt/divsf3.zig").__aeabi_fdiv; | |
| 675 | @export(__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = linkage }); | |
| 676 | const __aeabi_ddiv = @import("compiler_rt/divdf3.zig").__aeabi_ddiv; | |
| 677 | @export(__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = linkage }); | |
| 678 | ||
| 679 | const __aeabi_llsl = @import("compiler_rt/shift.zig").__aeabi_llsl; | |
| 680 | @export(__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = linkage }); | |
| 681 | const __aeabi_lasr = @import("compiler_rt/shift.zig").__aeabi_lasr; | |
| 682 | @export(__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = linkage }); | |
| 683 | const __aeabi_llsr = @import("compiler_rt/shift.zig").__aeabi_llsr; | |
| 684 | @export(__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = linkage }); | |
| 685 | ||
| 686 | const __aeabi_fcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpeq; | |
| 687 | @export(__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage }); | |
| 688 | const __aeabi_fcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmplt; | |
| 689 | @export(__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage }); | |
| 690 | const __aeabi_fcmple = @import("compiler_rt/compareXf2.zig").__aeabi_fcmple; | |
| 691 | @export(__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage }); | |
| 692 | const __aeabi_fcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpge; | |
| 693 | @export(__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage }); | |
| 694 | const __aeabi_fcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpgt; | |
| 695 | @export(__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage }); | |
| 696 | const __aeabi_fcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_fcmpun; | |
| 697 | @export(__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage }); | |
| 698 | ||
| 699 | const __aeabi_dcmpeq = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpeq; | |
| 700 | @export(__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage }); | |
| 701 | const __aeabi_dcmplt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmplt; | |
| 702 | @export(__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage }); | |
| 703 | const __aeabi_dcmple = @import("compiler_rt/compareXf2.zig").__aeabi_dcmple; | |
| 704 | @export(__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage }); | |
| 705 | const __aeabi_dcmpge = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpge; | |
| 706 | @export(__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage }); | |
| 707 | const __aeabi_dcmpgt = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpgt; | |
| 708 | @export(__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage }); | |
| 709 | const __aeabi_dcmpun = @import("compiler_rt/compareXf2.zig").__aeabi_dcmpun; | |
| 710 | @export(__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage }); | |
| 711 | } | |
| 712 | ||
| 713 | if (arch == .i386 and abi == .msvc) { | |
| 714 | // Don't let LLVM apply the stdcall name mangling on those MSVC builtins | |
| 715 | const _alldiv = @import("compiler_rt/aulldiv.zig")._alldiv; | |
| 716 | @export(_alldiv, .{ .name = "\x01__alldiv", .linkage = strong_linkage }); | |
| 717 | const _aulldiv = @import("compiler_rt/aulldiv.zig")._aulldiv; | |
| 718 | @export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = strong_linkage }); | |
| 719 | const _allrem = @import("compiler_rt/aullrem.zig")._allrem; | |
| 720 | @export(_allrem, .{ .name = "\x01__allrem", .linkage = strong_linkage }); | |
| 721 | const _aullrem = @import("compiler_rt/aullrem.zig")._aullrem; | |
| 722 | @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage }); | |
| 723 | } | |
| 724 | ||
| 725 | mathExport("ceil", @import("./compiler_rt/ceil.zig")); | |
| 726 | mathExport("cos", @import("./compiler_rt/cos.zig")); | |
| 727 | mathExport("exp", @import("./compiler_rt/exp.zig")); | |
| 728 | mathExport("exp2", @import("./compiler_rt/exp2.zig")); | |
| 729 | mathExport("fabs", @import("./compiler_rt/fabs.zig")); | |
| 730 | mathExport("floor", @import("./compiler_rt/floor.zig")); | |
| 731 | mathExport("fma", @import("./compiler_rt/fma.zig")); | |
| 732 | mathExport("fmax", @import("./compiler_rt/fmax.zig")); | |
| 733 | mathExport("fmin", @import("./compiler_rt/fmin.zig")); | |
| 734 | mathExport("fmod", @import("./compiler_rt/fmod.zig")); | |
| 735 | mathExport("log", @import("./compiler_rt/log.zig")); | |
| 736 | mathExport("log10", @import("./compiler_rt/log10.zig")); | |
| 737 | mathExport("log2", @import("./compiler_rt/log2.zig")); | |
| 738 | mathExport("round", @import("./compiler_rt/round.zig")); | |
| 739 | mathExport("sin", @import("./compiler_rt/sin.zig")); | |
| 740 | mathExport("sincos", @import("./compiler_rt/sincos.zig")); | |
| 741 | mathExport("sqrt", @import("./compiler_rt/sqrt.zig")); | |
| 742 | mathExport("tan", @import("./compiler_rt/tan.zig")); | |
| 743 | mathExport("trunc", @import("./compiler_rt/trunc.zig")); | |
| 744 | ||
| 745 | if (arch.isSPARC()) { | |
| 746 | // SPARC systems use a different naming scheme | |
| 747 | const _Qp_add = @import("compiler_rt/sparc.zig")._Qp_add; | |
| 748 | @export(_Qp_add, .{ .name = "_Qp_add", .linkage = linkage }); | |
| 749 | const _Qp_div = @import("compiler_rt/sparc.zig")._Qp_div; | |
| 750 | @export(_Qp_div, .{ .name = "_Qp_div", .linkage = linkage }); | |
| 751 | const _Qp_mul = @import("compiler_rt/sparc.zig")._Qp_mul; | |
| 752 | @export(_Qp_mul, .{ .name = "_Qp_mul", .linkage = linkage }); | |
| 753 | const _Qp_sub = @import("compiler_rt/sparc.zig")._Qp_sub; | |
| 754 | @export(_Qp_sub, .{ .name = "_Qp_sub", .linkage = linkage }); | |
| 755 | ||
| 756 | const _Qp_cmp = @import("compiler_rt/sparc.zig")._Qp_cmp; | |
| 757 | @export(_Qp_cmp, .{ .name = "_Qp_cmp", .linkage = linkage }); | |
| 758 | const _Qp_feq = @import("compiler_rt/sparc.zig")._Qp_feq; | |
| 759 | @export(_Qp_feq, .{ .name = "_Qp_feq", .linkage = linkage }); | |
| 760 | const _Qp_fne = @import("compiler_rt/sparc.zig")._Qp_fne; | |
| 761 | @export(_Qp_fne, .{ .name = "_Qp_fne", .linkage = linkage }); | |
| 762 | const _Qp_flt = @import("compiler_rt/sparc.zig")._Qp_flt; | |
| 763 | @export(_Qp_flt, .{ .name = "_Qp_flt", .linkage = linkage }); | |
| 764 | const _Qp_fle = @import("compiler_rt/sparc.zig")._Qp_fle; | |
| 765 | @export(_Qp_fle, .{ .name = "_Qp_fle", .linkage = linkage }); | |
| 766 | const _Qp_fgt = @import("compiler_rt/sparc.zig")._Qp_fgt; | |
| 767 | @export(_Qp_fgt, .{ .name = "_Qp_fgt", .linkage = linkage }); | |
| 768 | const _Qp_fge = @import("compiler_rt/sparc.zig")._Qp_fge; | |
| 769 | @export(_Qp_fge, .{ .name = "_Qp_fge", .linkage = linkage }); | |
| 770 | ||
| 771 | const _Qp_itoq = @import("compiler_rt/sparc.zig")._Qp_itoq; | |
| 772 | @export(_Qp_itoq, .{ .name = "_Qp_itoq", .linkage = linkage }); | |
| 773 | const _Qp_uitoq = @import("compiler_rt/sparc.zig")._Qp_uitoq; | |
| 774 | @export(_Qp_uitoq, .{ .name = "_Qp_uitoq", .linkage = linkage }); | |
| 775 | const _Qp_xtoq = @import("compiler_rt/sparc.zig")._Qp_xtoq; | |
| 776 | @export(_Qp_xtoq, .{ .name = "_Qp_xtoq", .linkage = linkage }); | |
| 777 | const _Qp_uxtoq = @import("compiler_rt/sparc.zig")._Qp_uxtoq; | |
| 778 | @export(_Qp_uxtoq, .{ .name = "_Qp_uxtoq", .linkage = linkage }); | |
| 779 | const _Qp_stoq = @import("compiler_rt/sparc.zig")._Qp_stoq; | |
| 780 | @export(_Qp_stoq, .{ .name = "_Qp_stoq", .linkage = linkage }); | |
| 781 | const _Qp_dtoq = @import("compiler_rt/sparc.zig")._Qp_dtoq; | |
| 782 | @export(_Qp_dtoq, .{ .name = "_Qp_dtoq", .linkage = linkage }); | |
| 783 | const _Qp_qtoi = @import("compiler_rt/sparc.zig")._Qp_qtoi; | |
| 784 | @export(_Qp_qtoi, .{ .name = "_Qp_qtoi", .linkage = linkage }); | |
| 785 | const _Qp_qtoui = @import("compiler_rt/sparc.zig")._Qp_qtoui; | |
| 786 | @export(_Qp_qtoui, .{ .name = "_Qp_qtoui", .linkage = linkage }); | |
| 787 | const _Qp_qtox = @import("compiler_rt/sparc.zig")._Qp_qtox; | |
| 788 | @export(_Qp_qtox, .{ .name = "_Qp_qtox", .linkage = linkage }); | |
| 789 | const _Qp_qtoux = @import("compiler_rt/sparc.zig")._Qp_qtoux; | |
| 790 | @export(_Qp_qtoux, .{ .name = "_Qp_qtoux", .linkage = linkage }); | |
| 791 | const _Qp_qtos = @import("compiler_rt/sparc.zig")._Qp_qtos; | |
| 792 | @export(_Qp_qtos, .{ .name = "_Qp_qtos", .linkage = linkage }); | |
| 793 | const _Qp_qtod = @import("compiler_rt/sparc.zig")._Qp_qtod; | |
| 794 | @export(_Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage }); | |
| 795 | } | |
| 796 | ||
| 797 | if (is_ppc and !is_test) { | |
| 798 | @export(__addtf3, .{ .name = "__addkf3", .linkage = linkage }); | |
| 799 | @export(__subtf3, .{ .name = "__subkf3", .linkage = linkage }); | |
| 800 | @export(__multf3, .{ .name = "__mulkf3", .linkage = linkage }); | |
| 801 | @export(__divtf3, .{ .name = "__divkf3", .linkage = linkage }); | |
| 802 | @export(__extendsftf2, .{ .name = "__extendsfkf2", .linkage = linkage }); | |
| 803 | @export(__extenddftf2, .{ .name = "__extenddfkf2", .linkage = linkage }); | |
| 804 | @export(__trunctfsf2, .{ .name = "__trunckfsf2", .linkage = linkage }); | |
| 805 | @export(__trunctfdf2, .{ .name = "__trunckfdf2", .linkage = linkage }); | |
| 806 | @export(__fixtfdi, .{ .name = "__fixkfdi", .linkage = linkage }); | |
| 807 | @export(__fixtfsi, .{ .name = "__fixkfsi", .linkage = linkage }); | |
| 808 | @export(__fixunstfsi, .{ .name = "__fixunskfsi", .linkage = linkage }); | |
| 809 | @export(__fixunstfdi, .{ .name = "__fixunskfdi", .linkage = linkage }); | |
| 810 | @export(__floatsitf, .{ .name = "__floatsikf", .linkage = linkage }); | |
| 811 | @export(__floatditf, .{ .name = "__floatdikf", .linkage = linkage }); | |
| 812 | @export(__floatunditf, .{ .name = "__floatundikf", .linkage = linkage }); | |
| 813 | @export(__floatunsitf, .{ .name = "__floatunsikf", .linkage = linkage }); | |
| 814 | @export(__floatuntitf, .{ .name = "__floatuntikf", .linkage = linkage }); | |
| 815 | ||
| 816 | @export(__letf2, .{ .name = "__eqkf2", .linkage = linkage }); | |
| 817 | @export(__letf2, .{ .name = "__nekf2", .linkage = linkage }); | |
| 818 | @export(__getf2, .{ .name = "__gekf2", .linkage = linkage }); | |
| 819 | @export(__letf2, .{ .name = "__ltkf2", .linkage = linkage }); | |
| 820 | @export(__letf2, .{ .name = "__lekf2", .linkage = linkage }); | |
| 821 | @export(__getf2, .{ .name = "__gtkf2", .linkage = linkage }); | |
| 822 | @export(__unordtf2, .{ .name = "__unordkf2", .linkage = linkage }); | |
| 823 | } | |
| 824 | } | |
| 825 | ||
| 826 | inline fn mathExport(double_name: []const u8, comptime import: type) void { | |
| 827 | const half_name = "__" ++ double_name ++ "h"; | |
| 828 | const half_fn = @field(import, half_name); | |
| 829 | const float_name = double_name ++ "f"; | |
| 830 | const float_fn = @field(import, float_name); | |
| 831 | const double_fn = @field(import, double_name); | |
| 832 | const long_double_name = double_name ++ "l"; | |
| 833 | const xf80_name = "__" ++ double_name ++ "x"; | |
| 834 | const xf80_fn = @field(import, xf80_name); | |
| 835 | const quad_name = double_name ++ "q"; | |
| 836 | const quad_fn = @field(import, quad_name); | |
| 837 | ||
| 838 | @export(half_fn, .{ .name = half_name, .linkage = linkage }); | |
| 839 | @export(float_fn, .{ .name = float_name, .linkage = linkage }); | |
| 840 | @export(double_fn, .{ .name = double_name, .linkage = linkage }); | |
| 841 | @export(xf80_fn, .{ .name = xf80_name, .linkage = linkage }); | |
| 842 | @export(quad_fn, .{ .name = quad_name, .linkage = linkage }); | |
| 843 | ||
| 844 | if (is_test) return; | |
| 845 | ||
| 846 | const pairs = .{ | |
| 847 | .{ f16, half_fn }, | |
| 848 | .{ f32, float_fn }, | |
| 849 | .{ f64, double_fn }, | |
| 850 | .{ f80, xf80_fn }, | |
| 851 | .{ f128, quad_fn }, | |
| 852 | }; | |
| 853 | ||
| 854 | if (builtin.os.tag == .windows) { | |
| 855 | // Weak aliases don't work on Windows, so we have to provide the 'l' variants | |
| 856 | // as additional function definitions that jump to the real definition. | |
| 857 | const long_double_fn = @field(import, long_double_name); | |
| 858 | @export(long_double_fn, .{ .name = long_double_name, .linkage = linkage }); | |
| 859 | } else { | |
| 860 | inline for (pairs) |pair| { | |
| 861 | const F = pair[0]; | |
| 862 | const func = pair[1]; | |
| 863 | if (builtin.target.longDoubleIs(F)) { | |
| 864 | @export(func, .{ .name = long_double_name, .linkage = linkage }); | |
| 865 | } | |
| 866 | } | |
| 867 | } | |
| 868 | ||
| 869 | if (is_ppc) { | |
| 870 | // LLVM PPC backend lowers f128 ops with the suffix `f128` instead of `l`. | |
| 871 | @export(quad_fn, .{ .name = double_name ++ "f128", .linkage = linkage }); | |
| 872 | } | |
| 873 | } | |
| 874 | 5 | |
| 875 | // Avoid dragging in the runtime safety mechanisms into this .o file, | |
| 876 | // unless we're trying to test this file. | |
| 877 | pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn { | |
| 878 | _ = error_return_trace; | |
| 879 | @setCold(true); | |
| 880 | if (is_test) { | |
| 881 | std.debug.panic("{s}", .{msg}); | |
| 882 | } else { | |
| 883 | unreachable; | |
| 884 | } | |
| 6 | _ = @import("compiler_rt/addf3.zig"); | |
| 7 | _ = @import("compiler_rt/addsf3.zig"); | |
| 8 | _ = @import("compiler_rt/addtf3.zig"); | |
| 9 | _ = @import("compiler_rt/addxf3.zig"); | |
| 10 | _ = @import("compiler_rt/subdf3.zig"); | |
| 11 | _ = @import("compiler_rt/subsf3.zig"); | |
| 12 | _ = @import("compiler_rt/subtf3.zig"); | |
| 13 | _ = @import("compiler_rt/subxf3.zig"); | |
| 14 | ||
| 15 | _ = @import("compiler_rt/mulf3.zig"); | |
| 16 | _ = @import("compiler_rt/muldf3.zig"); | |
| 17 | _ = @import("compiler_rt/mulsf3.zig"); | |
| 18 | _ = @import("compiler_rt/multf3.zig"); | |
| 19 | _ = @import("compiler_rt/mulxf3.zig"); | |
| 20 | ||
| 21 | _ = @import("compiler_rt/comparef.zig"); | |
| 22 | _ = @import("compiler_rt/cmpsf2.zig"); | |
| 23 | _ = @import("compiler_rt/cmpdf2.zig"); | |
| 24 | _ = @import("compiler_rt/cmptf2.zig"); | |
| 25 | _ = @import("compiler_rt/cmpxf2.zig"); | |
| 26 | _ = @import("compiler_rt/gesf2.zig"); | |
| 27 | _ = @import("compiler_rt/gedf2.zig"); | |
| 28 | _ = @import("compiler_rt/getf2.zig"); | |
| 29 | _ = @import("compiler_rt/gexf2.zig"); | |
| 30 | _ = @import("compiler_rt/unordsf2.zig"); | |
| 31 | _ = @import("compiler_rt/unorddf2.zig"); | |
| 32 | _ = @import("compiler_rt/unordtf2.zig"); | |
| 33 | ||
| 34 | _ = @import("compiler_rt/extendf.zig"); | |
| 35 | _ = @import("compiler_rt/extenddftf2.zig"); | |
| 36 | _ = @import("compiler_rt/extenddfxf2.zig"); | |
| 37 | _ = @import("compiler_rt/extendhfsf2.zig"); | |
| 38 | _ = @import("compiler_rt/extendhftf2.zig"); | |
| 39 | _ = @import("compiler_rt/extendhfxf2.zig"); | |
| 40 | _ = @import("compiler_rt/extendsfdf2.zig"); | |
| 41 | _ = @import("compiler_rt/extendsftf2.zig"); | |
| 42 | _ = @import("compiler_rt/extendsfxf2.zig"); | |
| 43 | _ = @import("compiler_rt/extendxftf2.zig"); | |
| 44 | ||
| 45 | _ = @import("compiler_rt/truncf.zig"); | |
| 46 | _ = @import("compiler_rt/truncsfhf2.zig"); | |
| 47 | _ = @import("compiler_rt/truncdfhf2.zig"); | |
| 48 | _ = @import("compiler_rt/truncdfsf2.zig"); | |
| 49 | _ = @import("compiler_rt/trunctfhf2.zig"); | |
| 50 | _ = @import("compiler_rt/trunctfsf2.zig"); | |
| 51 | _ = @import("compiler_rt/trunctfdf2.zig"); | |
| 52 | _ = @import("compiler_rt/trunctfxf2.zig"); | |
| 53 | _ = @import("compiler_rt/truncxfhf2.zig"); | |
| 54 | _ = @import("compiler_rt/truncxfsf2.zig"); | |
| 55 | _ = @import("compiler_rt/truncxfdf2.zig"); | |
| 56 | ||
| 57 | _ = @import("compiler_rt/divtf3.zig"); | |
| 58 | _ = @import("compiler_rt/divsf3.zig"); | |
| 59 | _ = @import("compiler_rt/divdf3.zig"); | |
| 60 | _ = @import("compiler_rt/divxf3.zig"); | |
| 61 | _ = @import("compiler_rt/sin.zig"); | |
| 62 | _ = @import("compiler_rt/cos.zig"); | |
| 63 | _ = @import("compiler_rt/sincos.zig"); | |
| 64 | _ = @import("compiler_rt/ceil.zig"); | |
| 65 | _ = @import("compiler_rt/exp.zig"); | |
| 66 | _ = @import("compiler_rt/exp2.zig"); | |
| 67 | _ = @import("compiler_rt/fabs.zig"); | |
| 68 | _ = @import("compiler_rt/floor.zig"); | |
| 69 | _ = @import("compiler_rt/fma.zig"); | |
| 70 | _ = @import("compiler_rt/fmax.zig"); | |
| 71 | _ = @import("compiler_rt/fmin.zig"); | |
| 72 | _ = @import("compiler_rt/fmod.zig"); | |
| 73 | _ = @import("compiler_rt/log.zig"); | |
| 74 | _ = @import("compiler_rt/log10.zig"); | |
| 75 | _ = @import("compiler_rt/log2.zig"); | |
| 76 | _ = @import("compiler_rt/round.zig"); | |
| 77 | _ = @import("compiler_rt/sqrt.zig"); | |
| 78 | _ = @import("compiler_rt/tan.zig"); | |
| 79 | _ = @import("compiler_rt/trunc.zig"); | |
| 80 | _ = @import("compiler_rt/stack_probe.zig"); | |
| 81 | _ = @import("compiler_rt/divti3.zig"); | |
| 82 | _ = @import("compiler_rt/modti3.zig"); | |
| 83 | _ = @import("compiler_rt/multi3.zig"); | |
| 84 | _ = @import("compiler_rt/udivti3.zig"); | |
| 85 | _ = @import("compiler_rt/udivmodti4.zig"); | |
| 86 | _ = @import("compiler_rt/umodti3.zig"); | |
| 87 | ||
| 88 | _ = @import("compiler_rt/int_to_float.zig"); | |
| 89 | _ = @import("compiler_rt/floatsihf.zig"); | |
| 90 | _ = @import("compiler_rt/floatsisf.zig"); | |
| 91 | _ = @import("compiler_rt/floatsidf.zig"); | |
| 92 | _ = @import("compiler_rt/floatsitf.zig"); | |
| 93 | _ = @import("compiler_rt/floatsixf.zig"); | |
| 94 | _ = @import("compiler_rt/floatdihf.zig"); | |
| 95 | _ = @import("compiler_rt/floatdisf.zig"); | |
| 96 | _ = @import("compiler_rt/floatdidf.zig"); | |
| 97 | _ = @import("compiler_rt/floatditf.zig"); | |
| 98 | _ = @import("compiler_rt/floatdixf.zig"); | |
| 99 | _ = @import("compiler_rt/floattihf.zig"); | |
| 100 | _ = @import("compiler_rt/floattisf.zig"); | |
| 101 | _ = @import("compiler_rt/floattidf.zig"); | |
| 102 | _ = @import("compiler_rt/floattitf.zig"); | |
| 103 | _ = @import("compiler_rt/floattixf.zig"); | |
| 104 | _ = @import("compiler_rt/floatundihf.zig"); | |
| 105 | _ = @import("compiler_rt/floatundisf.zig"); | |
| 106 | _ = @import("compiler_rt/floatundidf.zig"); | |
| 107 | _ = @import("compiler_rt/floatunditf.zig"); | |
| 108 | _ = @import("compiler_rt/floatundixf.zig"); | |
| 109 | _ = @import("compiler_rt/floatunsihf.zig"); | |
| 110 | _ = @import("compiler_rt/floatunsisf.zig"); | |
| 111 | _ = @import("compiler_rt/floatunsidf.zig"); | |
| 112 | _ = @import("compiler_rt/floatunsitf.zig"); | |
| 113 | _ = @import("compiler_rt/floatunsixf.zig"); | |
| 114 | _ = @import("compiler_rt/floatuntihf.zig"); | |
| 115 | _ = @import("compiler_rt/floatuntisf.zig"); | |
| 116 | _ = @import("compiler_rt/floatuntidf.zig"); | |
| 117 | _ = @import("compiler_rt/floatuntitf.zig"); | |
| 118 | _ = @import("compiler_rt/floatuntixf.zig"); | |
| 119 | ||
| 120 | _ = @import("compiler_rt/float_to_int.zig"); | |
| 121 | _ = @import("compiler_rt/fixhfsi.zig"); | |
| 122 | _ = @import("compiler_rt/fixhfdi.zig"); | |
| 123 | _ = @import("compiler_rt/fixhfti.zig"); | |
| 124 | _ = @import("compiler_rt/fixsfsi.zig"); | |
| 125 | _ = @import("compiler_rt/fixsfdi.zig"); | |
| 126 | _ = @import("compiler_rt/fixsfti.zig"); | |
| 127 | _ = @import("compiler_rt/fixdfsi.zig"); | |
| 128 | _ = @import("compiler_rt/fixdfdi.zig"); | |
| 129 | _ = @import("compiler_rt/fixdfti.zig"); | |
| 130 | _ = @import("compiler_rt/fixtfsi.zig"); | |
| 131 | _ = @import("compiler_rt/fixtfdi.zig"); | |
| 132 | _ = @import("compiler_rt/fixtfti.zig"); | |
| 133 | _ = @import("compiler_rt/fixxfsi.zig"); | |
| 134 | _ = @import("compiler_rt/fixxfdi.zig"); | |
| 135 | _ = @import("compiler_rt/fixxfti.zig"); | |
| 136 | _ = @import("compiler_rt/fixunshfsi.zig"); | |
| 137 | _ = @import("compiler_rt/fixunshfdi.zig"); | |
| 138 | _ = @import("compiler_rt/fixunshfti.zig"); | |
| 139 | _ = @import("compiler_rt/fixunssfsi.zig"); | |
| 140 | _ = @import("compiler_rt/fixunssfdi.zig"); | |
| 141 | _ = @import("compiler_rt/fixunssfti.zig"); | |
| 142 | _ = @import("compiler_rt/fixunsdfsi.zig"); | |
| 143 | _ = @import("compiler_rt/fixunsdfdi.zig"); | |
| 144 | _ = @import("compiler_rt/fixunsdfti.zig"); | |
| 145 | _ = @import("compiler_rt/fixunstfsi.zig"); | |
| 146 | _ = @import("compiler_rt/fixunstfdi.zig"); | |
| 147 | _ = @import("compiler_rt/fixunstfti.zig"); | |
| 148 | _ = @import("compiler_rt/fixunsxfsi.zig"); | |
| 149 | _ = @import("compiler_rt/fixunsxfdi.zig"); | |
| 150 | _ = @import("compiler_rt/fixunsxfti.zig"); | |
| 151 | ||
| 152 | _ = @import("compiler_rt/count0bits.zig"); | |
| 153 | _ = @import("compiler_rt/parity.zig"); | |
| 154 | _ = @import("compiler_rt/popcount.zig"); | |
| 155 | _ = @import("compiler_rt/bswap.zig"); | |
| 156 | _ = @import("compiler_rt/int.zig"); | |
| 157 | _ = @import("compiler_rt/shift.zig"); | |
| 158 | ||
| 159 | _ = @import("compiler_rt/negXi2.zig"); | |
| 160 | ||
| 161 | _ = @import("compiler_rt/muldi3.zig"); | |
| 162 | ||
| 163 | _ = @import("compiler_rt/absv.zig"); | |
| 164 | _ = @import("compiler_rt/absvsi2.zig"); | |
| 165 | _ = @import("compiler_rt/absvdi2.zig"); | |
| 166 | _ = @import("compiler_rt/absvti2.zig"); | |
| 167 | ||
| 168 | _ = @import("compiler_rt/negv.zig"); | |
| 169 | _ = @import("compiler_rt/addo.zig"); | |
| 170 | _ = @import("compiler_rt/subo.zig"); | |
| 171 | _ = @import("compiler_rt/mulo.zig"); | |
| 172 | _ = @import("compiler_rt/cmp.zig"); | |
| 173 | ||
| 174 | _ = @import("compiler_rt/negXf2.zig"); | |
| 175 | ||
| 176 | _ = @import("compiler_rt/os_version_check.zig"); | |
| 177 | _ = @import("compiler_rt/emutls.zig"); | |
| 178 | _ = @import("compiler_rt/arm.zig"); | |
| 179 | _ = @import("compiler_rt/aulldiv.zig"); | |
| 180 | _ = @import("compiler_rt/aullrem.zig"); | |
| 181 | _ = @import("compiler_rt/clear_cache.zig"); | |
| 885 | 182 | } |
lib/compiler_rt/absv.zig+3-17| ... | ... | @@ -1,8 +1,6 @@ |
| 1 | // absv - absolute oVerflow | |
| 2 | // * @panic, if value can not be represented | |
| 3 | // - absvXi4_generic for unoptimized version | |
| 4 | ||
| 5 | inline fn absvXi(comptime ST: type, a: ST) ST { | |
| 1 | /// absv - absolute oVerflow | |
| 2 | /// * @panic if value can not be represented | |
| 3 | pub inline fn absv(comptime ST: type, a: ST) ST { | |
| 6 | 4 | const UT = switch (ST) { |
| 7 | 5 | i32 => u32, |
| 8 | 6 | i64 => u64, |
| ... | ... | @@ -21,18 +19,6 @@ inline fn absvXi(comptime ST: type, a: ST) ST { |
| 21 | 19 | return x; |
| 22 | 20 | } |
| 23 | 21 | |
| 24 | pub fn __absvsi2(a: i32) callconv(.C) i32 { | |
| 25 | return absvXi(i32, a); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn __absvdi2(a: i64) callconv(.C) i64 { | |
| 29 | return absvXi(i64, a); | |
| 30 | } | |
| 31 | ||
| 32 | pub fn __absvti2(a: i128) callconv(.C) i128 { | |
| 33 | return absvXi(i128, a); | |
| 34 | } | |
| 35 | ||
| 36 | 22 | test { |
| 37 | 23 | _ = @import("absvsi2_test.zig"); |
| 38 | 24 | _ = @import("absvdi2_test.zig"); |
lib/compiler_rt/absvdi2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const absv = @import("./absv.zig").absv; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__absvdi2, .{ .name = "__absvdi2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __absvdi2(a: i64) callconv(.C) i64 { | |
| 11 | return absv(i64, a); | |
| 12 | } |
lib/compiler_rt/absvdi2_test.zig+3-2| ... | ... | @@ -1,8 +1,9 @@ |
| 1 | const absv = @import("absv.zig"); | |
| 2 | 1 | const testing = @import("std").testing; |
| 3 | 2 | |
| 3 | const __absvdi2 = @import("absvdi2.zig").__absvdi2; | |
| 4 | ||
| 4 | 5 | fn test__absvdi2(a: i64, expected: i64) !void { |
| 5 | var result = absv.__absvdi2(a); | |
| 6 | var result = __absvdi2(a); | |
| 6 | 7 | try testing.expectEqual(expected, result); |
| 7 | 8 | } |
| 8 | 9 |
lib/compiler_rt/absvsi2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const absv = @import("./absv.zig").absv; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__absvsi2, .{ .name = "__absvsi2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __absvsi2(a: i32) callconv(.C) i32 { | |
| 11 | return absv(i32, a); | |
| 12 | } |
lib/compiler_rt/absvsi2_test.zig+3-2| ... | ... | @@ -1,8 +1,9 @@ |
| 1 | const absv = @import("absv.zig"); | |
| 2 | 1 | const testing = @import("std").testing; |
| 3 | 2 | |
| 3 | const __absvsi2 = @import("absvsi2.zig").__absvsi2; | |
| 4 | ||
| 4 | 5 | fn test__absvsi2(a: i32, expected: i32) !void { |
| 5 | var result = absv.__absvsi2(a); | |
| 6 | var result = __absvsi2(a); | |
| 6 | 7 | try testing.expectEqual(expected, result); |
| 7 | 8 | } |
| 8 | 9 |
lib/compiler_rt/absvti2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const absv = @import("./absv.zig").absv; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__absvti2, .{ .name = "__absvti2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __absvti2(a: i128) callconv(.C) i128 { | |
| 11 | return absv(i128, a); | |
| 12 | } |
lib/compiler_rt/absvti2_test.zig+3-2| ... | ... | @@ -1,8 +1,9 @@ |
| 1 | const absv = @import("absv.zig"); | |
| 2 | 1 | const testing = @import("std").testing; |
| 3 | 2 | |
| 3 | const __absvti2 = @import("absvti2.zig").__absvti2; | |
| 4 | ||
| 4 | 5 | fn test__absvti2(a: i128, expected: i128) !void { |
| 5 | var result = absv.__absvti2(a); | |
| 6 | var result = __absvti2(a); | |
| 6 | 7 | try testing.expectEqual(expected, result); |
| 7 | 8 | } |
| 8 | 9 |
lib/compiler_rt/addXf3.zig deleted-244| ... | ... | @@ -1,244 +0,0 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc | |
| 4 | ||
| 5 | const std = @import("std"); | |
| 6 | const math = std.math; | |
| 7 | const builtin = @import("builtin"); | |
| 8 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 9 | ||
| 10 | pub fn __addsf3(a: f32, b: f32) callconv(.C) f32 { | |
| 11 | return addXf3(f32, a, b); | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __adddf3(a: f64, b: f64) callconv(.C) f64 { | |
| 15 | return addXf3(f64, a, b); | |
| 16 | } | |
| 17 | ||
| 18 | pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 { | |
| 19 | return addXf3(f80, a, b); | |
| 20 | } | |
| 21 | ||
| 22 | pub fn __subxf3(a: f80, b: f80) callconv(.C) f80 { | |
| 23 | var b_rep = std.math.break_f80(b); | |
| 24 | b_rep.exp ^= 0x8000; | |
| 25 | return __addxf3(a, std.math.make_f80(b_rep)); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn __addtf3(a: f128, b: f128) callconv(.C) f128 { | |
| 29 | return addXf3(f128, a, b); | |
| 30 | } | |
| 31 | ||
| 32 | pub fn __subsf3(a: f32, b: f32) callconv(.C) f32 { | |
| 33 | const neg_b = @bitCast(f32, @bitCast(u32, b) ^ (@as(u32, 1) << 31)); | |
| 34 | return addXf3(f32, a, neg_b); | |
| 35 | } | |
| 36 | ||
| 37 | pub fn __subdf3(a: f64, b: f64) callconv(.C) f64 { | |
| 38 | const neg_b = @bitCast(f64, @bitCast(u64, b) ^ (@as(u64, 1) << 63)); | |
| 39 | return addXf3(f64, a, neg_b); | |
| 40 | } | |
| 41 | ||
| 42 | pub fn __subtf3(a: f128, b: f128) callconv(.C) f128 { | |
| 43 | const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (@as(u128, 1) << 127)); | |
| 44 | return addXf3(f128, a, neg_b); | |
| 45 | } | |
| 46 | ||
| 47 | pub fn __aeabi_fadd(a: f32, b: f32) callconv(.AAPCS) f32 { | |
| 48 | @setRuntimeSafety(false); | |
| 49 | return @call(.{ .modifier = .always_inline }, __addsf3, .{ a, b }); | |
| 50 | } | |
| 51 | ||
| 52 | pub fn __aeabi_dadd(a: f64, b: f64) callconv(.AAPCS) f64 { | |
| 53 | @setRuntimeSafety(false); | |
| 54 | return @call(.{ .modifier = .always_inline }, __adddf3, .{ a, b }); | |
| 55 | } | |
| 56 | ||
| 57 | pub fn __aeabi_fsub(a: f32, b: f32) callconv(.AAPCS) f32 { | |
| 58 | @setRuntimeSafety(false); | |
| 59 | return @call(.{ .modifier = .always_inline }, __subsf3, .{ a, b }); | |
| 60 | } | |
| 61 | ||
| 62 | pub fn __aeabi_dsub(a: f64, b: f64) callconv(.AAPCS) f64 { | |
| 63 | @setRuntimeSafety(false); | |
| 64 | return @call(.{ .modifier = .always_inline }, __subdf3, .{ a, b }); | |
| 65 | } | |
| 66 | ||
| 67 | // TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154 | |
| 68 | fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T).Float.bits)) i32 { | |
| 69 | const bits = @typeInfo(T).Float.bits; | |
| 70 | const Z = std.meta.Int(.unsigned, bits); | |
| 71 | const S = std.meta.Int(.unsigned, bits - @clz(Z, @as(Z, bits) - 1)); | |
| 72 | const fractionalBits = math.floatFractionalBits(T); | |
| 73 | const integerBit = @as(Z, 1) << fractionalBits; | |
| 74 | ||
| 75 | const shift = @clz(std.meta.Int(.unsigned, bits), significand.*) - @clz(Z, integerBit); | |
| 76 | significand.* <<= @intCast(S, shift); | |
| 77 | return @as(i32, 1) - shift; | |
| 78 | } | |
| 79 | ||
| 80 | // TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154 | |
| 81 | fn addXf3(comptime T: type, a: T, b: T) T { | |
| 82 | const bits = @typeInfo(T).Float.bits; | |
| 83 | const Z = std.meta.Int(.unsigned, bits); | |
| 84 | const S = std.meta.Int(.unsigned, bits - @clz(Z, @as(Z, bits) - 1)); | |
| 85 | ||
| 86 | const typeWidth = bits; | |
| 87 | const significandBits = math.floatMantissaBits(T); | |
| 88 | const fractionalBits = math.floatFractionalBits(T); | |
| 89 | const exponentBits = math.floatExponentBits(T); | |
| 90 | ||
| 91 | const signBit = (@as(Z, 1) << (significandBits + exponentBits)); | |
| 92 | const maxExponent = ((1 << exponentBits) - 1); | |
| 93 | ||
| 94 | const integerBit = (@as(Z, 1) << fractionalBits); | |
| 95 | const quietBit = integerBit >> 1; | |
| 96 | const significandMask = (@as(Z, 1) << significandBits) - 1; | |
| 97 | ||
| 98 | const absMask = signBit - 1; | |
| 99 | const qnanRep = @bitCast(Z, math.nan(T)) | quietBit; | |
| 100 | ||
| 101 | var aRep = @bitCast(Z, a); | |
| 102 | var bRep = @bitCast(Z, b); | |
| 103 | const aAbs = aRep & absMask; | |
| 104 | const bAbs = bRep & absMask; | |
| 105 | ||
| 106 | const infRep = @bitCast(Z, math.inf(T)); | |
| 107 | ||
| 108 | // Detect if a or b is zero, infinity, or NaN. | |
| 109 | if (aAbs -% @as(Z, 1) >= infRep - @as(Z, 1) or | |
| 110 | bAbs -% @as(Z, 1) >= infRep - @as(Z, 1)) | |
| 111 | { | |
| 112 | // NaN + anything = qNaN | |
| 113 | if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit); | |
| 114 | // anything + NaN = qNaN | |
| 115 | if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit); | |
| 116 | ||
| 117 | if (aAbs == infRep) { | |
| 118 | // +/-infinity + -/+infinity = qNaN | |
| 119 | if ((@bitCast(Z, a) ^ @bitCast(Z, b)) == signBit) { | |
| 120 | return @bitCast(T, qnanRep); | |
| 121 | } | |
| 122 | // +/-infinity + anything remaining = +/- infinity | |
| 123 | else { | |
| 124 | return a; | |
| 125 | } | |
| 126 | } | |
| 127 | ||
| 128 | // anything remaining + +/-infinity = +/-infinity | |
| 129 | if (bAbs == infRep) return b; | |
| 130 | ||
| 131 | // zero + anything = anything | |
| 132 | if (aAbs == 0) { | |
| 133 | // but we need to get the sign right for zero + zero | |
| 134 | if (bAbs == 0) { | |
| 135 | return @bitCast(T, @bitCast(Z, a) & @bitCast(Z, b)); | |
| 136 | } else { | |
| 137 | return b; | |
| 138 | } | |
| 139 | } | |
| 140 | ||
| 141 | // anything + zero = anything | |
| 142 | if (bAbs == 0) return a; | |
| 143 | } | |
| 144 | ||
| 145 | // Swap a and b if necessary so that a has the larger absolute value. | |
| 146 | if (bAbs > aAbs) { | |
| 147 | const temp = aRep; | |
| 148 | aRep = bRep; | |
| 149 | bRep = temp; | |
| 150 | } | |
| 151 | ||
| 152 | // Extract the exponent and significand from the (possibly swapped) a and b. | |
| 153 | var aExponent = @intCast(i32, (aRep >> significandBits) & maxExponent); | |
| 154 | var bExponent = @intCast(i32, (bRep >> significandBits) & maxExponent); | |
| 155 | var aSignificand = aRep & significandMask; | |
| 156 | var bSignificand = bRep & significandMask; | |
| 157 | ||
| 158 | // Normalize any denormals, and adjust the exponent accordingly. | |
| 159 | if (aExponent == 0) aExponent = normalize(T, &aSignificand); | |
| 160 | if (bExponent == 0) bExponent = normalize(T, &bSignificand); | |
| 161 | ||
| 162 | // The sign of the result is the sign of the larger operand, a. If they | |
| 163 | // have opposite signs, we are performing a subtraction; otherwise addition. | |
| 164 | const resultSign = aRep & signBit; | |
| 165 | const subtraction = (aRep ^ bRep) & signBit != 0; | |
| 166 | ||
| 167 | // Shift the significands to give us round, guard and sticky, and or in the | |
| 168 | // implicit significand bit. (If we fell through from the denormal path it | |
| 169 | // was already set by normalize( ), but setting it twice won't hurt | |
| 170 | // anything.) | |
| 171 | aSignificand = (aSignificand | integerBit) << 3; | |
| 172 | bSignificand = (bSignificand | integerBit) << 3; | |
| 173 | ||
| 174 | // Shift the significand of b by the difference in exponents, with a sticky | |
| 175 | // bottom bit to get rounding correct. | |
| 176 | const @"align" = @intCast(u32, aExponent - bExponent); | |
| 177 | if (@"align" != 0) { | |
| 178 | if (@"align" < typeWidth) { | |
| 179 | const sticky = if (bSignificand << @intCast(S, typeWidth - @"align") != 0) @as(Z, 1) else 0; | |
| 180 | bSignificand = (bSignificand >> @truncate(S, @"align")) | sticky; | |
| 181 | } else { | |
| 182 | bSignificand = 1; // sticky; b is known to be non-zero. | |
| 183 | } | |
| 184 | } | |
| 185 | if (subtraction) { | |
| 186 | aSignificand -= bSignificand; | |
| 187 | // If a == -b, return +zero. | |
| 188 | if (aSignificand == 0) return @bitCast(T, @as(Z, 0)); | |
| 189 | ||
| 190 | // If partial cancellation occured, we need to left-shift the result | |
| 191 | // and adjust the exponent: | |
| 192 | if (aSignificand < integerBit << 3) { | |
| 193 | const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(std.meta.Int(.unsigned, bits), integerBit << 3)); | |
| 194 | aSignificand <<= @intCast(S, shift); | |
| 195 | aExponent -= shift; | |
| 196 | } | |
| 197 | } else { // addition | |
| 198 | aSignificand += bSignificand; | |
| 199 | ||
| 200 | // If the addition carried up, we need to right-shift the result and | |
| 201 | // adjust the exponent: | |
| 202 | if (aSignificand & (integerBit << 4) != 0) { | |
| 203 | const sticky = aSignificand & 1; | |
| 204 | aSignificand = aSignificand >> 1 | sticky; | |
| 205 | aExponent += 1; | |
| 206 | } | |
| 207 | } | |
| 208 | ||
| 209 | // If we have overflowed the type, return +/- infinity: | |
| 210 | if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign); | |
| 211 | ||
| 212 | if (aExponent <= 0) { | |
| 213 | // Result is denormal; the exponent and round/sticky bits are zero. | |
| 214 | // All we need to do is shift the significand and apply the correct sign. | |
| 215 | aSignificand >>= @intCast(S, 4 - aExponent); | |
| 216 | return @bitCast(T, resultSign | aSignificand); | |
| 217 | } | |
| 218 | ||
| 219 | // Low three bits are round, guard, and sticky. | |
| 220 | const roundGuardSticky = aSignificand & 0x7; | |
| 221 | ||
| 222 | // Shift the significand into place, and mask off the integer bit, if it's implicit. | |
| 223 | var result = (aSignificand >> 3) & significandMask; | |
| 224 | ||
| 225 | // Insert the exponent and sign. | |
| 226 | result |= @intCast(Z, aExponent) << significandBits; | |
| 227 | result |= resultSign; | |
| 228 | ||
| 229 | // Final rounding. The result may overflow to infinity, but that is the | |
| 230 | // correct result in that case. | |
| 231 | if (roundGuardSticky > 0x4) result += 1; | |
| 232 | if (roundGuardSticky == 0x4) result += result & 1; | |
| 233 | ||
| 234 | // Restore any explicit integer bit, if it was rounded off | |
| 235 | if (significandBits != fractionalBits) { | |
| 236 | if ((result >> significandBits) != 0) result |= integerBit; | |
| 237 | } | |
| 238 | ||
| 239 | return @bitCast(T, result); | |
| 240 | } | |
| 241 | ||
| 242 | test { | |
| 243 | _ = @import("addXf3_test.zig"); | |
| 244 | } |
lib/compiler_rt/addXf3_test.zig deleted-157| ... | ... | @@ -1,157 +0,0 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c | |
| 4 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/subtf3_test.c | |
| 5 | ||
| 6 | const std = @import("std"); | |
| 7 | const math = std.math; | |
| 8 | const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64); | |
| 9 | ||
| 10 | const __addtf3 = @import("addXf3.zig").__addtf3; | |
| 11 | ||
| 12 | fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { | |
| 13 | const x = __addtf3(a, b); | |
| 14 | ||
| 15 | const rep = @bitCast(u128, x); | |
| 16 | const hi = @intCast(u64, rep >> 64); | |
| 17 | const lo = @truncate(u64, rep); | |
| 18 | ||
| 19 | if (hi == expected_hi and lo == expected_lo) { | |
| 20 | return; | |
| 21 | } | |
| 22 | // test other possible NaN representation (signal NaN) | |
| 23 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 24 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 25 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 26 | { | |
| 27 | return; | |
| 28 | } | |
| 29 | } | |
| 30 | ||
| 31 | return error.TestFailed; | |
| 32 | } | |
| 33 | ||
| 34 | test "addtf3" { | |
| 35 | try test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 36 | ||
| 37 | // NaN + any = NaN | |
| 38 | try test__addtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 39 | ||
| 40 | // inf + inf = inf | |
| 41 | try test__addtf3(math.inf(f128), math.inf(f128), 0x7fff000000000000, 0x0); | |
| 42 | ||
| 43 | // inf + any = inf | |
| 44 | try test__addtf3(math.inf(f128), 0x1.2335653452436234723489432abcdefp+5, 0x7fff000000000000, 0x0); | |
| 45 | ||
| 46 | // any + any | |
| 47 | try test__addtf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x40042afc95c8b579, 0x61e58dd6c51eb77c); | |
| 48 | try test__addtf3(0x1.edcba52449872455634654321fp-1, 0x1.23456734245345543849abcdefp+5, 0x40042afc95c8b579, 0x61e58dd6c51eb77c); | |
| 49 | } | |
| 50 | ||
| 51 | const __subtf3 = @import("addXf3.zig").__subtf3; | |
| 52 | ||
| 53 | fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { | |
| 54 | const x = __subtf3(a, b); | |
| 55 | ||
| 56 | const rep = @bitCast(u128, x); | |
| 57 | const hi = @intCast(u64, rep >> 64); | |
| 58 | const lo = @truncate(u64, rep); | |
| 59 | ||
| 60 | if (hi == expected_hi and lo == expected_lo) { | |
| 61 | return; | |
| 62 | } | |
| 63 | // test other possible NaN representation (signal NaN) | |
| 64 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 65 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 66 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 67 | { | |
| 68 | return; | |
| 69 | } | |
| 70 | } | |
| 71 | ||
| 72 | return error.TestFailed; | |
| 73 | } | |
| 74 | ||
| 75 | test "subtf3" { | |
| 76 | // qNaN - any = qNaN | |
| 77 | try test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 78 | ||
| 79 | // NaN + any = NaN | |
| 80 | try test__subtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 81 | ||
| 82 | // inf - any = inf | |
| 83 | try test__subtf3(math.inf(f128), 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); | |
| 84 | ||
| 85 | // any + any | |
| 86 | try test__subtf3(0x1.234567829a3bcdef5678ade36734p+5, 0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x40041b8af1915166, 0xa44a7bca780a166c); | |
| 87 | try test__subtf3(0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x1.234567829a3bcdef5678ade36734p+5, 0xc0041b8af1915166, 0xa44a7bca780a166c); | |
| 88 | } | |
| 89 | ||
| 90 | const __addxf3 = @import("addXf3.zig").__addxf3; | |
| 91 | const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1))); | |
| 92 | ||
| 93 | fn test__addxf3(a: f80, b: f80, expected: u80) !void { | |
| 94 | const x = __addxf3(a, b); | |
| 95 | const rep = @bitCast(u80, x); | |
| 96 | ||
| 97 | if (rep == expected) | |
| 98 | return; | |
| 99 | ||
| 100 | if (math.isNan(@bitCast(f80, expected)) and math.isNan(x)) | |
| 101 | return; // We don't currently test NaN payload propagation | |
| 102 | ||
| 103 | return error.TestFailed; | |
| 104 | } | |
| 105 | ||
| 106 | test "addxf3" { | |
| 107 | // NaN + any = NaN | |
| 108 | try test__addxf3(qnan80, 0x1.23456789abcdefp+5, @bitCast(u80, qnan80)); | |
| 109 | try test__addxf3(@bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), 0x1.23456789abcdefp+5, @bitCast(u80, qnan80)); | |
| 110 | ||
| 111 | // any + NaN = NaN | |
| 112 | try test__addxf3(0x1.23456789abcdefp+5, qnan80, @bitCast(u80, qnan80)); | |
| 113 | try test__addxf3(0x1.23456789abcdefp+5, @bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), @bitCast(u80, qnan80)); | |
| 114 | ||
| 115 | // NaN + inf = NaN | |
| 116 | try test__addxf3(qnan80, math.inf(f80), @bitCast(u80, qnan80)); | |
| 117 | ||
| 118 | // inf + NaN = NaN | |
| 119 | try test__addxf3(math.inf(f80), qnan80, @bitCast(u80, qnan80)); | |
| 120 | ||
| 121 | // inf + inf = inf | |
| 122 | try test__addxf3(math.inf(f80), math.inf(f80), @bitCast(u80, math.inf(f80))); | |
| 123 | ||
| 124 | // inf + -inf = NaN | |
| 125 | try test__addxf3(math.inf(f80), -math.inf(f80), @bitCast(u80, qnan80)); | |
| 126 | ||
| 127 | // -inf + inf = NaN | |
| 128 | try test__addxf3(-math.inf(f80), math.inf(f80), @bitCast(u80, qnan80)); | |
| 129 | ||
| 130 | // inf + any = inf | |
| 131 | try test__addxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @bitCast(u80, math.inf(f80))); | |
| 132 | ||
| 133 | // any + inf = inf | |
| 134 | try test__addxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @bitCast(u80, math.inf(f80))); | |
| 135 | ||
| 136 | // any + any | |
| 137 | try test__addxf3(0x1.23456789abcdp+5, 0x1.dcba987654321p+5, 0x4005_BFFFFFFFFFFFC400); | |
| 138 | try test__addxf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x4004_957E_4AE4_5ABC_B0F3); | |
| 139 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.0p-63, 0x3FFF_FFFFFFFFFFFFFFFF); // exact | |
| 140 | try test__addxf3(0x1.ffff_ffff_ffff_fffep+0, 0x0.0p0, 0x3FFF_FFFFFFFFFFFFFFFF); // exact | |
| 141 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.4p-63, 0x3FFF_FFFFFFFFFFFFFFFF); // round down | |
| 142 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.8p-63, 0x4000_8000000000000000); // round up to even | |
| 143 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.cp-63, 0x4000_8000000000000000); // round up | |
| 144 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x2.0p-63, 0x4000_8000000000000000); // exact | |
| 145 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x2.1p-63, 0x4000_8000000000000000); // round down | |
| 146 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x3.0p-63, 0x4000_8000000000000000); // round down to even | |
| 147 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x3.1p-63, 0x4000_8000000000000001); // round up | |
| 148 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x4.0p-63, 0x4000_8000000000000001); // exact | |
| 149 | ||
| 150 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.0p-63, 0x3FFF_8800000000000000); // exact | |
| 151 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.7p-63, 0x3FFF_8800000000000000); // round down | |
| 152 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.8p-63, 0x3FFF_8800000000000000); // round down to even | |
| 153 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.9p-63, 0x3FFF_8800000000000001); // round up | |
| 154 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x2.0p-63, 0x3FFF_8800000000000001); // exact | |
| 155 | try test__addxf3(0x0.ffff_ffff_ffff_fffcp-16382, 0x0.0000_0000_0000_0002p-16382, 0x0000_7FFFFFFFFFFFFFFF); // exact | |
| 156 | try test__addxf3(0x0.1fff_ffff_ffff_fffcp-16382, 0x0.0000_0000_0000_0002p-16382, 0x0000_0FFFFFFFFFFFFFFF); // exact | |
| 157 | } |
lib/compiler_rt/adddf3.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const addf3 = @import("./addf3.zig").addf3; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_dadd, .{ .name = "__aeabi_dadd", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__adddf3, .{ .name = "__adddf3", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | fn __adddf3(a: f64, b: f64) callconv(.C) f64 { | |
| 15 | return addf3(f64, a, b); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_dadd(a: f64, b: f64) callconv(.AAPCS) f64 { | |
| 19 | return addf3(f64, a, b); | |
| 20 | } |
lib/compiler_rt/addf3.zig created+172| ... | ... | @@ -0,0 +1,172 @@ |
| 1 | const std = @import("std"); | |
| 2 | const math = std.math; | |
| 3 | const common = @import("./common.zig"); | |
| 4 | const normalize = common.normalize; | |
| 5 | ||
| 6 | /// Ported from: | |
| 7 | /// | |
| 8 | /// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc | |
| 9 | pub inline fn addf3(comptime T: type, a: T, b: T) T { | |
| 10 | const bits = @typeInfo(T).Float.bits; | |
| 11 | const Z = std.meta.Int(.unsigned, bits); | |
| 12 | const S = std.meta.Int(.unsigned, bits - @clz(Z, @as(Z, bits) - 1)); | |
| 13 | ||
| 14 | const typeWidth = bits; | |
| 15 | const significandBits = math.floatMantissaBits(T); | |
| 16 | const fractionalBits = math.floatFractionalBits(T); | |
| 17 | const exponentBits = math.floatExponentBits(T); | |
| 18 | ||
| 19 | const signBit = (@as(Z, 1) << (significandBits + exponentBits)); | |
| 20 | const maxExponent = ((1 << exponentBits) - 1); | |
| 21 | ||
| 22 | const integerBit = (@as(Z, 1) << fractionalBits); | |
| 23 | const quietBit = integerBit >> 1; | |
| 24 | const significandMask = (@as(Z, 1) << significandBits) - 1; | |
| 25 | ||
| 26 | const absMask = signBit - 1; | |
| 27 | const qnanRep = @bitCast(Z, math.nan(T)) | quietBit; | |
| 28 | ||
| 29 | var aRep = @bitCast(Z, a); | |
| 30 | var bRep = @bitCast(Z, b); | |
| 31 | const aAbs = aRep & absMask; | |
| 32 | const bAbs = bRep & absMask; | |
| 33 | ||
| 34 | const infRep = @bitCast(Z, math.inf(T)); | |
| 35 | ||
| 36 | // Detect if a or b is zero, infinity, or NaN. | |
| 37 | if (aAbs -% @as(Z, 1) >= infRep - @as(Z, 1) or | |
| 38 | bAbs -% @as(Z, 1) >= infRep - @as(Z, 1)) | |
| 39 | { | |
| 40 | // NaN + anything = qNaN | |
| 41 | if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit); | |
| 42 | // anything + NaN = qNaN | |
| 43 | if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit); | |
| 44 | ||
| 45 | if (aAbs == infRep) { | |
| 46 | // +/-infinity + -/+infinity = qNaN | |
| 47 | if ((@bitCast(Z, a) ^ @bitCast(Z, b)) == signBit) { | |
| 48 | return @bitCast(T, qnanRep); | |
| 49 | } | |
| 50 | // +/-infinity + anything remaining = +/- infinity | |
| 51 | else { | |
| 52 | return a; | |
| 53 | } | |
| 54 | } | |
| 55 | ||
| 56 | // anything remaining + +/-infinity = +/-infinity | |
| 57 | if (bAbs == infRep) return b; | |
| 58 | ||
| 59 | // zero + anything = anything | |
| 60 | if (aAbs == 0) { | |
| 61 | // but we need to get the sign right for zero + zero | |
| 62 | if (bAbs == 0) { | |
| 63 | return @bitCast(T, @bitCast(Z, a) & @bitCast(Z, b)); | |
| 64 | } else { | |
| 65 | return b; | |
| 66 | } | |
| 67 | } | |
| 68 | ||
| 69 | // anything + zero = anything | |
| 70 | if (bAbs == 0) return a; | |
| 71 | } | |
| 72 | ||
| 73 | // Swap a and b if necessary so that a has the larger absolute value. | |
| 74 | if (bAbs > aAbs) { | |
| 75 | const temp = aRep; | |
| 76 | aRep = bRep; | |
| 77 | bRep = temp; | |
| 78 | } | |
| 79 | ||
| 80 | // Extract the exponent and significand from the (possibly swapped) a and b. | |
| 81 | var aExponent = @intCast(i32, (aRep >> significandBits) & maxExponent); | |
| 82 | var bExponent = @intCast(i32, (bRep >> significandBits) & maxExponent); | |
| 83 | var aSignificand = aRep & significandMask; | |
| 84 | var bSignificand = bRep & significandMask; | |
| 85 | ||
| 86 | // Normalize any denormals, and adjust the exponent accordingly. | |
| 87 | if (aExponent == 0) aExponent = normalize(T, &aSignificand); | |
| 88 | if (bExponent == 0) bExponent = normalize(T, &bSignificand); | |
| 89 | ||
| 90 | // The sign of the result is the sign of the larger operand, a. If they | |
| 91 | // have opposite signs, we are performing a subtraction; otherwise addition. | |
| 92 | const resultSign = aRep & signBit; | |
| 93 | const subtraction = (aRep ^ bRep) & signBit != 0; | |
| 94 | ||
| 95 | // Shift the significands to give us round, guard and sticky, and or in the | |
| 96 | // implicit significand bit. (If we fell through from the denormal path it | |
| 97 | // was already set by normalize( ), but setting it twice won't hurt | |
| 98 | // anything.) | |
| 99 | aSignificand = (aSignificand | integerBit) << 3; | |
| 100 | bSignificand = (bSignificand | integerBit) << 3; | |
| 101 | ||
| 102 | // Shift the significand of b by the difference in exponents, with a sticky | |
| 103 | // bottom bit to get rounding correct. | |
| 104 | const @"align" = @intCast(u32, aExponent - bExponent); | |
| 105 | if (@"align" != 0) { | |
| 106 | if (@"align" < typeWidth) { | |
| 107 | const sticky = if (bSignificand << @intCast(S, typeWidth - @"align") != 0) @as(Z, 1) else 0; | |
| 108 | bSignificand = (bSignificand >> @truncate(S, @"align")) | sticky; | |
| 109 | } else { | |
| 110 | bSignificand = 1; // sticky; b is known to be non-zero. | |
| 111 | } | |
| 112 | } | |
| 113 | if (subtraction) { | |
| 114 | aSignificand -= bSignificand; | |
| 115 | // If a == -b, return +zero. | |
| 116 | if (aSignificand == 0) return @bitCast(T, @as(Z, 0)); | |
| 117 | ||
| 118 | // If partial cancellation occured, we need to left-shift the result | |
| 119 | // and adjust the exponent: | |
| 120 | if (aSignificand < integerBit << 3) { | |
| 121 | const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(std.meta.Int(.unsigned, bits), integerBit << 3)); | |
| 122 | aSignificand <<= @intCast(S, shift); | |
| 123 | aExponent -= shift; | |
| 124 | } | |
| 125 | } else { // addition | |
| 126 | aSignificand += bSignificand; | |
| 127 | ||
| 128 | // If the addition carried up, we need to right-shift the result and | |
| 129 | // adjust the exponent: | |
| 130 | if (aSignificand & (integerBit << 4) != 0) { | |
| 131 | const sticky = aSignificand & 1; | |
| 132 | aSignificand = aSignificand >> 1 | sticky; | |
| 133 | aExponent += 1; | |
| 134 | } | |
| 135 | } | |
| 136 | ||
| 137 | // If we have overflowed the type, return +/- infinity: | |
| 138 | if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign); | |
| 139 | ||
| 140 | if (aExponent <= 0) { | |
| 141 | // Result is denormal; the exponent and round/sticky bits are zero. | |
| 142 | // All we need to do is shift the significand and apply the correct sign. | |
| 143 | aSignificand >>= @intCast(S, 4 - aExponent); | |
| 144 | return @bitCast(T, resultSign | aSignificand); | |
| 145 | } | |
| 146 | ||
| 147 | // Low three bits are round, guard, and sticky. | |
| 148 | const roundGuardSticky = aSignificand & 0x7; | |
| 149 | ||
| 150 | // Shift the significand into place, and mask off the integer bit, if it's implicit. | |
| 151 | var result = (aSignificand >> 3) & significandMask; | |
| 152 | ||
| 153 | // Insert the exponent and sign. | |
| 154 | result |= @intCast(Z, aExponent) << significandBits; | |
| 155 | result |= resultSign; | |
| 156 | ||
| 157 | // Final rounding. The result may overflow to infinity, but that is the | |
| 158 | // correct result in that case. | |
| 159 | if (roundGuardSticky > 0x4) result += 1; | |
| 160 | if (roundGuardSticky == 0x4) result += result & 1; | |
| 161 | ||
| 162 | // Restore any explicit integer bit, if it was rounded off | |
| 163 | if (significandBits != fractionalBits) { | |
| 164 | if ((result >> significandBits) != 0) result |= integerBit; | |
| 165 | } | |
| 166 | ||
| 167 | return @bitCast(T, result); | |
| 168 | } | |
| 169 | ||
| 170 | test { | |
| 171 | _ = @import("addf3_test.zig"); | |
| 172 | } |
lib/compiler_rt/addf3_test.zig created+156| ... | ... | @@ -0,0 +1,156 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/addtf3_test.c | |
| 4 | // https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/test/builtins/Unit/subtf3_test.c | |
| 5 | ||
| 6 | const std = @import("std"); | |
| 7 | const math = std.math; | |
| 8 | const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64); | |
| 9 | ||
| 10 | const __addtf3 = @import("addtf3.zig").__addtf3; | |
| 11 | const __addxf3 = @import("addxf3.zig").__addxf3; | |
| 12 | const __subtf3 = @import("subtf3.zig").__subtf3; | |
| 13 | ||
| 14 | fn test__addtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { | |
| 15 | const x = __addtf3(a, b); | |
| 16 | ||
| 17 | const rep = @bitCast(u128, x); | |
| 18 | const hi = @intCast(u64, rep >> 64); | |
| 19 | const lo = @truncate(u64, rep); | |
| 20 | ||
| 21 | if (hi == expected_hi and lo == expected_lo) { | |
| 22 | return; | |
| 23 | } | |
| 24 | // test other possible NaN representation (signal NaN) | |
| 25 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 26 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 27 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 28 | { | |
| 29 | return; | |
| 30 | } | |
| 31 | } | |
| 32 | ||
| 33 | return error.TestFailed; | |
| 34 | } | |
| 35 | ||
| 36 | test "addtf3" { | |
| 37 | try test__addtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 38 | ||
| 39 | // NaN + any = NaN | |
| 40 | try test__addtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 41 | ||
| 42 | // inf + inf = inf | |
| 43 | try test__addtf3(math.inf(f128), math.inf(f128), 0x7fff000000000000, 0x0); | |
| 44 | ||
| 45 | // inf + any = inf | |
| 46 | try test__addtf3(math.inf(f128), 0x1.2335653452436234723489432abcdefp+5, 0x7fff000000000000, 0x0); | |
| 47 | ||
| 48 | // any + any | |
| 49 | try test__addtf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x40042afc95c8b579, 0x61e58dd6c51eb77c); | |
| 50 | try test__addtf3(0x1.edcba52449872455634654321fp-1, 0x1.23456734245345543849abcdefp+5, 0x40042afc95c8b579, 0x61e58dd6c51eb77c); | |
| 51 | } | |
| 52 | ||
| 53 | fn test__subtf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { | |
| 54 | const x = __subtf3(a, b); | |
| 55 | ||
| 56 | const rep = @bitCast(u128, x); | |
| 57 | const hi = @intCast(u64, rep >> 64); | |
| 58 | const lo = @truncate(u64, rep); | |
| 59 | ||
| 60 | if (hi == expected_hi and lo == expected_lo) { | |
| 61 | return; | |
| 62 | } | |
| 63 | // test other possible NaN representation (signal NaN) | |
| 64 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 65 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 66 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 67 | { | |
| 68 | return; | |
| 69 | } | |
| 70 | } | |
| 71 | ||
| 72 | return error.TestFailed; | |
| 73 | } | |
| 74 | ||
| 75 | test "subtf3" { | |
| 76 | // qNaN - any = qNaN | |
| 77 | try test__subtf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 78 | ||
| 79 | // NaN + any = NaN | |
| 80 | try test__subtf3(@bitCast(f128, (@as(u128, 0x7fff000000000000) << 64) | @as(u128, 0x800030000000)), 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 81 | ||
| 82 | // inf - any = inf | |
| 83 | try test__subtf3(math.inf(f128), 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); | |
| 84 | ||
| 85 | // any + any | |
| 86 | try test__subtf3(0x1.234567829a3bcdef5678ade36734p+5, 0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x40041b8af1915166, 0xa44a7bca780a166c); | |
| 87 | try test__subtf3(0x1.ee9d7c52354a6936ab8d7654321fp-1, 0x1.234567829a3bcdef5678ade36734p+5, 0xc0041b8af1915166, 0xa44a7bca780a166c); | |
| 88 | } | |
| 89 | ||
| 90 | const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1))); | |
| 91 | ||
| 92 | fn test__addxf3(a: f80, b: f80, expected: u80) !void { | |
| 93 | const x = __addxf3(a, b); | |
| 94 | const rep = @bitCast(u80, x); | |
| 95 | ||
| 96 | if (rep == expected) | |
| 97 | return; | |
| 98 | ||
| 99 | if (math.isNan(@bitCast(f80, expected)) and math.isNan(x)) | |
| 100 | return; // We don't currently test NaN payload propagation | |
| 101 | ||
| 102 | return error.TestFailed; | |
| 103 | } | |
| 104 | ||
| 105 | test "addxf3" { | |
| 106 | // NaN + any = NaN | |
| 107 | try test__addxf3(qnan80, 0x1.23456789abcdefp+5, @bitCast(u80, qnan80)); | |
| 108 | try test__addxf3(@bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), 0x1.23456789abcdefp+5, @bitCast(u80, qnan80)); | |
| 109 | ||
| 110 | // any + NaN = NaN | |
| 111 | try test__addxf3(0x1.23456789abcdefp+5, qnan80, @bitCast(u80, qnan80)); | |
| 112 | try test__addxf3(0x1.23456789abcdefp+5, @bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), @bitCast(u80, qnan80)); | |
| 113 | ||
| 114 | // NaN + inf = NaN | |
| 115 | try test__addxf3(qnan80, math.inf(f80), @bitCast(u80, qnan80)); | |
| 116 | ||
| 117 | // inf + NaN = NaN | |
| 118 | try test__addxf3(math.inf(f80), qnan80, @bitCast(u80, qnan80)); | |
| 119 | ||
| 120 | // inf + inf = inf | |
| 121 | try test__addxf3(math.inf(f80), math.inf(f80), @bitCast(u80, math.inf(f80))); | |
| 122 | ||
| 123 | // inf + -inf = NaN | |
| 124 | try test__addxf3(math.inf(f80), -math.inf(f80), @bitCast(u80, qnan80)); | |
| 125 | ||
| 126 | // -inf + inf = NaN | |
| 127 | try test__addxf3(-math.inf(f80), math.inf(f80), @bitCast(u80, qnan80)); | |
| 128 | ||
| 129 | // inf + any = inf | |
| 130 | try test__addxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @bitCast(u80, math.inf(f80))); | |
| 131 | ||
| 132 | // any + inf = inf | |
| 133 | try test__addxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @bitCast(u80, math.inf(f80))); | |
| 134 | ||
| 135 | // any + any | |
| 136 | try test__addxf3(0x1.23456789abcdp+5, 0x1.dcba987654321p+5, 0x4005_BFFFFFFFFFFFC400); | |
| 137 | try test__addxf3(0x1.23456734245345543849abcdefp+5, 0x1.edcba52449872455634654321fp-1, 0x4004_957E_4AE4_5ABC_B0F3); | |
| 138 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.0p-63, 0x3FFF_FFFFFFFFFFFFFFFF); // exact | |
| 139 | try test__addxf3(0x1.ffff_ffff_ffff_fffep+0, 0x0.0p0, 0x3FFF_FFFFFFFFFFFFFFFF); // exact | |
| 140 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.4p-63, 0x3FFF_FFFFFFFFFFFFFFFF); // round down | |
| 141 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.8p-63, 0x4000_8000000000000000); // round up to even | |
| 142 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x1.cp-63, 0x4000_8000000000000000); // round up | |
| 143 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x2.0p-63, 0x4000_8000000000000000); // exact | |
| 144 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x2.1p-63, 0x4000_8000000000000000); // round down | |
| 145 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x3.0p-63, 0x4000_8000000000000000); // round down to even | |
| 146 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x3.1p-63, 0x4000_8000000000000001); // round up | |
| 147 | try test__addxf3(0x1.ffff_ffff_ffff_fffcp+0, 0x4.0p-63, 0x4000_8000000000000001); // exact | |
| 148 | ||
| 149 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.0p-63, 0x3FFF_8800000000000000); // exact | |
| 150 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.7p-63, 0x3FFF_8800000000000000); // round down | |
| 151 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.8p-63, 0x3FFF_8800000000000000); // round down to even | |
| 152 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x1.9p-63, 0x3FFF_8800000000000001); // round up | |
| 153 | try test__addxf3(0x1.0fff_ffff_ffff_fffep+0, 0x2.0p-63, 0x3FFF_8800000000000001); // exact | |
| 154 | try test__addxf3(0x0.ffff_ffff_ffff_fffcp-16382, 0x0.0000_0000_0000_0002p-16382, 0x0000_7FFFFFFFFFFFFFFF); // exact | |
| 155 | try test__addxf3(0x0.1fff_ffff_ffff_fffcp-16382, 0x0.0000_0000_0000_0002p-16382, 0x0000_0FFFFFFFFFFFFFFF); // exact | |
| 156 | } |
lib/compiler_rt/addo.zig+10| ... | ... | @@ -1,4 +1,14 @@ |
| 1 | const std = @import("std"); | |
| 1 | 2 | const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | |
| 4 | const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak; | |
| 5 | pub const panic = @import("common.zig").panic; | |
| 6 | ||
| 7 | comptime { | |
| 8 | @export(__addosi4, .{ .name = "__addosi4", .linkage = linkage }); | |
| 9 | @export(__addodi4, .{ .name = "__addodi4", .linkage = linkage }); | |
| 10 | @export(__addoti4, .{ .name = "__addoti4", .linkage = linkage }); | |
| 11 | } | |
| 2 | 12 | |
| 3 | 13 | // addo - add overflow |
| 4 | 14 | // * return a+%b. |
lib/compiler_rt/addsf3.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const addf3 = @import("./addf3.zig").addf3; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_fadd, .{ .name = "__aeabi_fadd", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__addsf3, .{ .name = "__addsf3", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | fn __addsf3(a: f32, b: f32) callconv(.C) f32 { | |
| 15 | return addf3(f32, a, b); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_fadd(a: f32, b: f32) callconv(.AAPCS) f32 { | |
| 19 | return addf3(f32, a, b); | |
| 20 | } |
lib/compiler_rt/addtf3.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const addf3 = @import("./addf3.zig").addf3; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__addkf3, .{ .name = "__addkf3", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_add, .{ .name = "_Qp_add", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__addtf3, .{ .name = "__addtf3", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __addtf3(a: f128, b: f128) callconv(.C) f128 { | |
| 17 | return addf3(f128, a, b); | |
| 18 | } | |
| 19 | ||
| 20 | fn __addkf3(a: f128, b: f128) callconv(.C) f128 { | |
| 21 | return addf3(f128, a, b); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.C) void { | |
| 25 | c.* = addf3(f128, a.*, b.*); | |
| 26 | } |
lib/compiler_rt/addxf3.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const addf3 = @import("./addf3.zig").addf3; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__addxf3, .{ .name = "__addxf3", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 { | |
| 11 | return addf3(f80, a, b); | |
| 12 | } |
lib/compiler_rt/arm.zig+76-3| ... | ... | @@ -1,5 +1,46 @@ |
| 1 | 1 | // ARM specific builtins |
| 2 | const std = @import("std"); | |
| 2 | 3 | const builtin = @import("builtin"); |
| 4 | const arch = builtin.cpu.arch; | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | if (!builtin.is_test) { | |
| 11 | if (arch.isARM() or arch.isThumb()) { | |
| 12 | @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = common.linkage }); | |
| 13 | @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = common.linkage }); | |
| 14 | @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = common.linkage }); | |
| 15 | ||
| 16 | @export(__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = common.linkage }); | |
| 17 | @export(__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = common.linkage }); | |
| 18 | ||
| 19 | @export(__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = common.linkage }); | |
| 20 | @export(__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = common.linkage }); | |
| 21 | ||
| 22 | @export(__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = common.linkage }); | |
| 23 | @export(__aeabi_memcpy4, .{ .name = "__aeabi_memcpy4", .linkage = common.linkage }); | |
| 24 | @export(__aeabi_memcpy8, .{ .name = "__aeabi_memcpy8", .linkage = common.linkage }); | |
| 25 | ||
| 26 | @export(__aeabi_memmove, .{ .name = "__aeabi_memmove", .linkage = common.linkage }); | |
| 27 | @export(__aeabi_memmove4, .{ .name = "__aeabi_memmove4", .linkage = common.linkage }); | |
| 28 | @export(__aeabi_memmove8, .{ .name = "__aeabi_memmove8", .linkage = common.linkage }); | |
| 29 | ||
| 30 | @export(__aeabi_memset, .{ .name = "__aeabi_memset", .linkage = common.linkage }); | |
| 31 | @export(__aeabi_memset4, .{ .name = "__aeabi_memset4", .linkage = common.linkage }); | |
| 32 | @export(__aeabi_memset8, .{ .name = "__aeabi_memset8", .linkage = common.linkage }); | |
| 33 | ||
| 34 | @export(__aeabi_memclr, .{ .name = "__aeabi_memclr", .linkage = common.linkage }); | |
| 35 | @export(__aeabi_memclr4, .{ .name = "__aeabi_memclr4", .linkage = common.linkage }); | |
| 36 | @export(__aeabi_memclr8, .{ .name = "__aeabi_memclr8", .linkage = common.linkage }); | |
| 37 | ||
| 38 | if (builtin.os.tag == .linux) { | |
| 39 | @export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = common.linkage }); | |
| 40 | } | |
| 41 | } | |
| 42 | } | |
| 43 | } | |
| 3 | 44 | |
| 4 | 45 | const __divmodsi4 = @import("int.zig").__divmodsi4; |
| 5 | 46 | const __udivmodsi4 = @import("int.zig").__udivmodsi4; |
| ... | ... | @@ -14,11 +55,27 @@ pub fn __aeabi_memcpy(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { |
| 14 | 55 | @setRuntimeSafety(false); |
| 15 | 56 | _ = memcpy(dest, src, n); |
| 16 | 57 | } |
| 58 | pub fn __aeabi_memcpy4(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { | |
| 59 | @setRuntimeSafety(false); | |
| 60 | _ = memcpy(dest, src, n); | |
| 61 | } | |
| 62 | pub fn __aeabi_memcpy8(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { | |
| 63 | @setRuntimeSafety(false); | |
| 64 | _ = memcpy(dest, src, n); | |
| 65 | } | |
| 17 | 66 | |
| 18 | 67 | pub fn __aeabi_memmove(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { |
| 19 | 68 | @setRuntimeSafety(false); |
| 20 | 69 | _ = memmove(dest, src, n); |
| 21 | 70 | } |
| 71 | pub fn __aeabi_memmove4(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { | |
| 72 | @setRuntimeSafety(false); | |
| 73 | _ = memmove(dest, src, n); | |
| 74 | } | |
| 75 | pub fn __aeabi_memmove8(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void { | |
| 76 | @setRuntimeSafety(false); | |
| 77 | _ = memmove(dest, src, n); | |
| 78 | } | |
| 22 | 79 | |
| 23 | 80 | pub fn __aeabi_memset(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void { |
| 24 | 81 | @setRuntimeSafety(false); |
| ... | ... | @@ -26,16 +83,32 @@ pub fn __aeabi_memset(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void { |
| 26 | 83 | // two arguments swapped |
| 27 | 84 | _ = memset(dest, c, n); |
| 28 | 85 | } |
| 86 | pub fn __aeabi_memset4(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void { | |
| 87 | @setRuntimeSafety(false); | |
| 88 | _ = memset(dest, c, n); | |
| 89 | } | |
| 90 | pub fn __aeabi_memset8(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void { | |
| 91 | @setRuntimeSafety(false); | |
| 92 | _ = memset(dest, c, n); | |
| 93 | } | |
| 29 | 94 | |
| 30 | 95 | pub fn __aeabi_memclr(dest: [*]u8, n: usize) callconv(.AAPCS) void { |
| 31 | 96 | @setRuntimeSafety(false); |
| 32 | 97 | _ = memset(dest, 0, n); |
| 33 | 98 | } |
| 99 | pub fn __aeabi_memclr4(dest: [*]u8, n: usize) callconv(.AAPCS) void { | |
| 100 | @setRuntimeSafety(false); | |
| 101 | _ = memset(dest, 0, n); | |
| 102 | } | |
| 103 | pub fn __aeabi_memclr8(dest: [*]u8, n: usize) callconv(.AAPCS) void { | |
| 104 | @setRuntimeSafety(false); | |
| 105 | _ = memset(dest, 0, n); | |
| 106 | } | |
| 34 | 107 | |
| 35 | 108 | // Dummy functions to avoid errors during the linking phase |
| 36 | pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void {} | |
| 37 | pub fn __aeabi_unwind_cpp_pr1() callconv(.C) void {} | |
| 38 | pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void {} | |
| 109 | pub fn __aeabi_unwind_cpp_pr0() callconv(.AAPCS) void {} | |
| 110 | pub fn __aeabi_unwind_cpp_pr1() callconv(.AAPCS) void {} | |
| 111 | pub fn __aeabi_unwind_cpp_pr2() callconv(.AAPCS) void {} | |
| 39 | 112 | |
| 40 | 113 | // This function can only clobber r0 according to the ABI |
| 41 | 114 | pub fn __aeabi_read_tp() callconv(.Naked) void { |
lib/compiler_rt/atomics.zig+1-1| ... | ... | @@ -2,8 +2,8 @@ const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const cpu = builtin.cpu; |
| 4 | 4 | const arch = cpu.arch; |
| 5 | ||
| 6 | 5 | const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak; |
| 6 | pub const panic = @import("common.zig").panic; | |
| 7 | 7 | |
| 8 | 8 | // This parameter is true iff the target architecture supports the bare minimum |
| 9 | 9 | // to implement the atomic load/store intrinsics. |
lib/compiler_rt/aulldiv.zig+14-1| ... | ... | @@ -1,7 +1,20 @@ |
| 1 | const std = @import("std"); | |
| 1 | 2 | const builtin = @import("builtin"); |
| 3 | const arch = builtin.cpu.arch; | |
| 4 | const abi = builtin.abi; | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | if (arch == .i386 and abi == .msvc) { | |
| 11 | // Don't let LLVM apply the stdcall name mangling on those MSVC builtins | |
| 12 | @export(_alldiv, .{ .name = "\x01__alldiv", .linkage = common.linkage }); | |
| 13 | @export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = common.linkage }); | |
| 14 | } | |
| 15 | } | |
| 2 | 16 | |
| 3 | 17 | pub fn _alldiv(a: i64, b: i64) callconv(.Stdcall) i64 { |
| 4 | @setRuntimeSafety(builtin.is_test); | |
| 5 | 18 | const s_a = a >> (64 - 1); |
| 6 | 19 | const s_b = b >> (64 - 1); |
| 7 | 20 |
lib/compiler_rt/aullrem.zig+14-1| ... | ... | @@ -1,7 +1,20 @@ |
| 1 | const std = @import("std"); | |
| 1 | 2 | const builtin = @import("builtin"); |
| 3 | const arch = builtin.cpu.arch; | |
| 4 | const abi = builtin.abi; | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | if (arch == .i386 and abi == .msvc) { | |
| 11 | // Don't let LLVM apply the stdcall name mangling on those MSVC builtins | |
| 12 | @export(_allrem, .{ .name = "\x01__allrem", .linkage = common.linkage }); | |
| 13 | @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = common.linkage }); | |
| 14 | } | |
| 15 | } | |
| 2 | 16 | |
| 3 | 17 | pub fn _allrem(a: i64, b: i64) callconv(.Stdcall) i64 { |
| 4 | @setRuntimeSafety(builtin.is_test); | |
| 5 | 18 | const s_a = a >> (64 - 1); |
| 6 | 19 | const s_b = b >> (64 - 1); |
| 7 | 20 |
lib/compiler_rt/bswap.zig+9-1| ... | ... | @@ -1,5 +1,14 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const common = @import("common.zig"); | |
| 4 | ||
| 5 | pub const panic = common.panic; | |
| 6 | ||
| 7 | comptime { | |
| 8 | @export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = common.linkage }); | |
| 9 | @export(__bswapdi2, .{ .name = "__bswapdi2", .linkage = common.linkage }); | |
| 10 | @export(__bswapti2, .{ .name = "__bswapti2", .linkage = common.linkage }); | |
| 11 | } | |
| 3 | 12 | |
| 4 | 13 | // bswap - byteswap |
| 5 | 14 | // - bswapXi2 for unoptimized big and little endian |
| ... | ... | @@ -12,7 +21,6 @@ const builtin = @import("builtin"); |
| 12 | 21 | // 00 00 00 ff << 3*8 (rightmost byte) |
| 13 | 22 | |
| 14 | 23 | inline fn bswapXi2(comptime T: type, a: T) T { |
| 15 | @setRuntimeSafety(builtin.is_test); | |
| 16 | 24 | switch (@bitSizeOf(T)) { |
| 17 | 25 | 32 => { |
| 18 | 26 | // zig fmt: off |
lib/compiler_rt/ceil.zig+20-5| ... | ... | @@ -1,12 +1,27 @@ |
| 1 | // Ported from musl, which is licensed under the MIT license: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c | |
| 1 | //! Ported from musl, which is MIT licensed. | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 9 | const arch = builtin.cpu.arch; | |
| 8 | 10 | const math = std.math; |
| 9 | 11 | const expect = std.testing.expect; |
| 12 | const common = @import("common.zig"); | |
| 13 | ||
| 14 | pub const panic = common.panic; | |
| 15 | ||
| 16 | comptime { | |
| 17 | @export(__ceilh, .{ .name = "__ceilh", .linkage = common.linkage }); | |
| 18 | @export(ceilf, .{ .name = "ceilf", .linkage = common.linkage }); | |
| 19 | @export(ceil, .{ .name = "ceil", .linkage = common.linkage }); | |
| 20 | @export(__ceilx, .{ .name = "__ceilx", .linkage = common.linkage }); | |
| 21 | const ceilq_sym_name = if (common.want_ppc_abi) "ceilf128" else "ceilq"; | |
| 22 | @export(ceilq, .{ .name = ceilq_sym_name, .linkage = common.linkage }); | |
| 23 | @export(ceill, .{ .name = "ceill", .linkage = common.linkage }); | |
| 24 | } | |
| 10 | 25 | |
| 11 | 26 | pub fn __ceilh(x: f16) callconv(.C) f16 { |
| 12 | 27 | // TODO: more efficient implementation |
lib/compiler_rt/clear_cache.zig+8-1| ... | ... | @@ -2,6 +2,7 @@ const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const arch = builtin.cpu.arch; |
| 4 | 4 | const os = builtin.os.tag; |
| 5 | pub const panic = @import("common.zig").panic; | |
| 5 | 6 | |
| 6 | 7 | // Ported from llvm-project d32170dbd5b0d54436537b6b75beaf44324e0c28 |
| 7 | 8 | |
| ... | ... | @@ -10,7 +11,13 @@ const os = builtin.os.tag; |
| 10 | 11 | // It is expected to invalidate the instruction cache for the |
| 11 | 12 | // specified range. |
| 12 | 13 | |
| 13 | pub fn clear_cache(start: usize, end: usize) callconv(.C) void { | |
| 14 | comptime { | |
| 15 | if (builtin.zig_backend != .stage2_llvm) { | |
| 16 | _ = clear_cache; | |
| 17 | } | |
| 18 | } | |
| 19 | ||
| 20 | fn clear_cache(start: usize, end: usize) callconv(.C) void { | |
| 14 | 21 | const x86 = switch (arch) { |
| 15 | 22 | .i386, .x86_64 => true, |
| 16 | 23 | else => false, |
lib/compiler_rt/cmp.zig+13-1| ... | ... | @@ -1,5 +1,18 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | |
| 4 | const common = @import("common.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | @export(__cmpsi2, .{ .name = "__cmpsi2", .linkage = common.linkage }); | |
| 10 | @export(__cmpdi2, .{ .name = "__cmpdi2", .linkage = common.linkage }); | |
| 11 | @export(__cmpti2, .{ .name = "__cmpti2", .linkage = common.linkage }); | |
| 12 | @export(__ucmpsi2, .{ .name = "__ucmpsi2", .linkage = common.linkage }); | |
| 13 | @export(__ucmpdi2, .{ .name = "__ucmpdi2", .linkage = common.linkage }); | |
| 14 | @export(__ucmpti2, .{ .name = "__ucmpti2", .linkage = common.linkage }); | |
| 15 | } | |
| 3 | 16 | |
| 4 | 17 | // cmp - signed compare |
| 5 | 18 | // - cmpXi2_generic for unoptimized little and big endian |
| ... | ... | @@ -12,7 +25,6 @@ const builtin = @import("builtin"); |
| 12 | 25 | // a > b => 2 |
| 13 | 26 | |
| 14 | 27 | inline fn XcmpXi2(comptime T: type, a: T, b: T) i32 { |
| 15 | @setRuntimeSafety(builtin.is_test); | |
| 16 | 28 | var cmp1: i32 = 0; |
| 17 | 29 | var cmp2: i32 = 0; |
| 18 | 30 | if (a > b) |
lib/compiler_rt/cmpdf2.zig created+68| ... | ... | @@ -0,0 +1,68 @@ |
| 1 | ///! The quoted behavior definitions are from | |
| 2 | ///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines | |
| 3 | const common = @import("./common.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | if (common.want_aeabi) { | |
| 10 | @export(__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = common.linkage }); | |
| 11 | @export(__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = common.linkage }); | |
| 12 | @export(__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = common.linkage }); | |
| 13 | } else { | |
| 14 | @export(__eqdf2, .{ .name = "__eqdf2", .linkage = common.linkage }); | |
| 15 | @export(__nedf2, .{ .name = "__nedf2", .linkage = common.linkage }); | |
| 16 | @export(__ledf2, .{ .name = "__ledf2", .linkage = common.linkage }); | |
| 17 | @export(__cmpdf2, .{ .name = "__cmpdf2", .linkage = common.linkage }); | |
| 18 | @export(__ltdf2, .{ .name = "__ltdf2", .linkage = common.linkage }); | |
| 19 | } | |
| 20 | } | |
| 21 | ||
| 22 | /// "These functions calculate a <=> b. That is, if a is less than b, they return -1; | |
| 23 | /// if a is greater than b, they return 1; and if a and b are equal they return 0. | |
| 24 | /// If either argument is NaN they return 1..." | |
| 25 | /// | |
| 26 | /// Note that this matches the definition of `__ledf2`, `__eqdf2`, `__nedf2`, `__cmpdf2`, | |
| 27 | /// and `__ltdf2`. | |
| 28 | fn __cmpdf2(a: f64, b: f64) callconv(.C) i32 { | |
| 29 | return @enumToInt(comparef.cmpf2(f64, comparef.LE, a, b)); | |
| 30 | } | |
| 31 | ||
| 32 | /// "These functions return a value less than or equal to zero if neither argument is NaN, | |
| 33 | /// and a is less than or equal to b." | |
| 34 | pub fn __ledf2(a: f64, b: f64) callconv(.C) i32 { | |
| 35 | return __cmpdf2(a, b); | |
| 36 | } | |
| 37 | ||
| 38 | /// "These functions return zero if neither argument is NaN, and a and b are equal." | |
| 39 | /// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined | |
| 40 | /// to have the same return value. | |
| 41 | pub fn __eqdf2(a: f64, b: f64) callconv(.C) i32 { | |
| 42 | return __cmpdf2(a, b); | |
| 43 | } | |
| 44 | ||
| 45 | /// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." | |
| 46 | /// Note that due to some kind of historical accident, __eqdf2 and __nedf2 are defined | |
| 47 | /// to have the same return value. | |
| 48 | pub fn __nedf2(a: f64, b: f64) callconv(.C) i32 { | |
| 49 | return __cmpdf2(a, b); | |
| 50 | } | |
| 51 | ||
| 52 | /// "These functions return a value less than zero if neither argument is NaN, and a | |
| 53 | /// is strictly less than b." | |
| 54 | pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 { | |
| 55 | return __cmpdf2(a, b); | |
| 56 | } | |
| 57 | ||
| 58 | fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 59 | return @boolToInt(comparef.cmpf2(f64, comparef.LE, a, b) == .Equal); | |
| 60 | } | |
| 61 | ||
| 62 | fn __aeabi_dcmplt(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 63 | return @boolToInt(comparef.cmpf2(f64, comparef.LE, a, b) == .Less); | |
| 64 | } | |
| 65 | ||
| 66 | fn __aeabi_dcmple(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 67 | return @boolToInt(comparef.cmpf2(f64, comparef.LE, a, b) != .Greater); | |
| 68 | } |
lib/compiler_rt/cmpsf2.zig created+68| ... | ... | @@ -0,0 +1,68 @@ |
| 1 | ///! The quoted behavior definitions are from | |
| 2 | ///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines | |
| 3 | const common = @import("./common.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | if (common.want_aeabi) { | |
| 10 | @export(__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = common.linkage }); | |
| 11 | @export(__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = common.linkage }); | |
| 12 | @export(__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = common.linkage }); | |
| 13 | } else { | |
| 14 | @export(__eqsf2, .{ .name = "__eqsf2", .linkage = common.linkage }); | |
| 15 | @export(__nesf2, .{ .name = "__nesf2", .linkage = common.linkage }); | |
| 16 | @export(__lesf2, .{ .name = "__lesf2", .linkage = common.linkage }); | |
| 17 | @export(__cmpsf2, .{ .name = "__cmpsf2", .linkage = common.linkage }); | |
| 18 | @export(__ltsf2, .{ .name = "__ltsf2", .linkage = common.linkage }); | |
| 19 | } | |
| 20 | } | |
| 21 | ||
| 22 | /// "These functions calculate a <=> b. That is, if a is less than b, they return -1; | |
| 23 | /// if a is greater than b, they return 1; and if a and b are equal they return 0. | |
| 24 | /// If either argument is NaN they return 1..." | |
| 25 | /// | |
| 26 | /// Note that this matches the definition of `__lesf2`, `__eqsf2`, `__nesf2`, `__cmpsf2`, | |
| 27 | /// and `__ltsf2`. | |
| 28 | fn __cmpsf2(a: f32, b: f32) callconv(.C) i32 { | |
| 29 | return @enumToInt(comparef.cmpf2(f32, comparef.LE, a, b)); | |
| 30 | } | |
| 31 | ||
| 32 | /// "These functions return a value less than or equal to zero if neither argument is NaN, | |
| 33 | /// and a is less than or equal to b." | |
| 34 | pub fn __lesf2(a: f32, b: f32) callconv(.C) i32 { | |
| 35 | return __cmpsf2(a, b); | |
| 36 | } | |
| 37 | ||
| 38 | /// "These functions return zero if neither argument is NaN, and a and b are equal." | |
| 39 | /// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined | |
| 40 | /// to have the same return value. | |
| 41 | pub fn __eqsf2(a: f32, b: f32) callconv(.C) i32 { | |
| 42 | return __cmpsf2(a, b); | |
| 43 | } | |
| 44 | ||
| 45 | /// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." | |
| 46 | /// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined | |
| 47 | /// to have the same return value. | |
| 48 | pub fn __nesf2(a: f32, b: f32) callconv(.C) i32 { | |
| 49 | return __cmpsf2(a, b); | |
| 50 | } | |
| 51 | ||
| 52 | /// "These functions return a value less than zero if neither argument is NaN, and a | |
| 53 | /// is strictly less than b." | |
| 54 | pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 { | |
| 55 | return __cmpsf2(a, b); | |
| 56 | } | |
| 57 | ||
| 58 | fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 59 | return @boolToInt(comparef.cmpf2(f32, comparef.LE, a, b) == .Equal); | |
| 60 | } | |
| 61 | ||
| 62 | fn __aeabi_fcmplt(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 63 | return @boolToInt(comparef.cmpf2(f32, comparef.LE, a, b) == .Less); | |
| 64 | } | |
| 65 | ||
| 66 | fn __aeabi_fcmple(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 67 | return @boolToInt(comparef.cmpf2(f32, comparef.LE, a, b) != .Greater); | |
| 68 | } |
lib/compiler_rt/cmptf2.zig created+122| ... | ... | @@ -0,0 +1,122 @@ |
| 1 | ///! The quoted behavior definitions are from | |
| 2 | ///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines | |
| 3 | const common = @import("./common.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | if (common.want_ppc_abi) { | |
| 10 | @export(__eqkf2, .{ .name = "__eqkf2", .linkage = common.linkage }); | |
| 11 | @export(__nekf2, .{ .name = "__nekf2", .linkage = common.linkage }); | |
| 12 | @export(__ltkf2, .{ .name = "__ltkf2", .linkage = common.linkage }); | |
| 13 | @export(__lekf2, .{ .name = "__lekf2", .linkage = common.linkage }); | |
| 14 | } else if (common.want_sparc_abi) { | |
| 15 | @export(_Qp_cmp, .{ .name = "_Qp_cmp", .linkage = common.linkage }); | |
| 16 | @export(_Qp_feq, .{ .name = "_Qp_feq", .linkage = common.linkage }); | |
| 17 | @export(_Qp_fne, .{ .name = "_Qp_fne", .linkage = common.linkage }); | |
| 18 | @export(_Qp_flt, .{ .name = "_Qp_flt", .linkage = common.linkage }); | |
| 19 | @export(_Qp_fle, .{ .name = "_Qp_fle", .linkage = common.linkage }); | |
| 20 | @export(_Qp_fgt, .{ .name = "_Qp_fgt", .linkage = common.linkage }); | |
| 21 | @export(_Qp_fge, .{ .name = "_Qp_fge", .linkage = common.linkage }); | |
| 22 | } else { | |
| 23 | @export(__eqtf2, .{ .name = "__eqtf2", .linkage = common.linkage }); | |
| 24 | @export(__netf2, .{ .name = "__netf2", .linkage = common.linkage }); | |
| 25 | @export(__letf2, .{ .name = "__letf2", .linkage = common.linkage }); | |
| 26 | @export(__cmptf2, .{ .name = "__cmptf2", .linkage = common.linkage }); | |
| 27 | @export(__lttf2, .{ .name = "__lttf2", .linkage = common.linkage }); | |
| 28 | } | |
| 29 | } | |
| 30 | ||
| 31 | /// "These functions calculate a <=> b. That is, if a is less than b, they return -1; | |
| 32 | /// if a is greater than b, they return 1; and if a and b are equal they return 0. | |
| 33 | /// If either argument is NaN they return 1..." | |
| 34 | /// | |
| 35 | /// Note that this matches the definition of `__letf2`, `__eqtf2`, `__netf2`, `__cmptf2`, | |
| 36 | /// and `__lttf2`. | |
| 37 | fn __cmptf2(a: f128, b: f128) callconv(.C) i32 { | |
| 38 | return @enumToInt(comparef.cmpf2(f128, comparef.LE, a, b)); | |
| 39 | } | |
| 40 | ||
| 41 | /// "These functions return a value less than or equal to zero if neither argument is NaN, | |
| 42 | /// and a is less than or equal to b." | |
| 43 | fn __letf2(a: f128, b: f128) callconv(.C) i32 { | |
| 44 | return __cmptf2(a, b); | |
| 45 | } | |
| 46 | ||
| 47 | /// "These functions return zero if neither argument is NaN, and a and b are equal." | |
| 48 | /// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined | |
| 49 | /// to have the same return value. | |
| 50 | fn __eqtf2(a: f128, b: f128) callconv(.C) i32 { | |
| 51 | return __cmptf2(a, b); | |
| 52 | } | |
| 53 | ||
| 54 | /// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." | |
| 55 | /// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined | |
| 56 | /// to have the same return value. | |
| 57 | fn __netf2(a: f128, b: f128) callconv(.C) i32 { | |
| 58 | return __cmptf2(a, b); | |
| 59 | } | |
| 60 | ||
| 61 | /// "These functions return a value less than zero if neither argument is NaN, and a | |
| 62 | /// is strictly less than b." | |
| 63 | fn __lttf2(a: f128, b: f128) callconv(.C) i32 { | |
| 64 | return __cmptf2(a, b); | |
| 65 | } | |
| 66 | ||
| 67 | fn __eqkf2(a: f128, b: f128) callconv(.C) i32 { | |
| 68 | return __cmptf2(a, b); | |
| 69 | } | |
| 70 | ||
| 71 | fn __nekf2(a: f128, b: f128) callconv(.C) i32 { | |
| 72 | return __cmptf2(a, b); | |
| 73 | } | |
| 74 | ||
| 75 | fn __ltkf2(a: f128, b: f128) callconv(.C) i32 { | |
| 76 | return __cmptf2(a, b); | |
| 77 | } | |
| 78 | ||
| 79 | fn __lekf2(a: f128, b: f128) callconv(.C) i32 { | |
| 80 | return __cmptf2(a, b); | |
| 81 | } | |
| 82 | ||
| 83 | const SparcFCMP = enum(i32) { | |
| 84 | Equal = 0, | |
| 85 | Less = 1, | |
| 86 | Greater = 2, | |
| 87 | Unordered = 3, | |
| 88 | }; | |
| 89 | ||
| 90 | fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.C) i32 { | |
| 91 | return @enumToInt(comparef.cmpf2(f128, SparcFCMP, a.*, b.*)); | |
| 92 | } | |
| 93 | ||
| 94 | fn _Qp_feq(a: *const f128, b: *const f128) callconv(.C) bool { | |
| 95 | return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) == .Equal; | |
| 96 | } | |
| 97 | ||
| 98 | fn _Qp_fne(a: *const f128, b: *const f128) callconv(.C) bool { | |
| 99 | return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) != .Equal; | |
| 100 | } | |
| 101 | ||
| 102 | fn _Qp_flt(a: *const f128, b: *const f128) callconv(.C) bool { | |
| 103 | return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) == .Less; | |
| 104 | } | |
| 105 | ||
| 106 | fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.C) bool { | |
| 107 | return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) == .Greater; | |
| 108 | } | |
| 109 | ||
| 110 | fn _Qp_fge(a: *const f128, b: *const f128) callconv(.C) bool { | |
| 111 | return switch (@intToEnum(SparcFCMP, _Qp_cmp(a, b))) { | |
| 112 | .Equal, .Greater => true, | |
| 113 | .Less, .Unordered => false, | |
| 114 | }; | |
| 115 | } | |
| 116 | ||
| 117 | fn _Qp_fle(a: *const f128, b: *const f128) callconv(.C) bool { | |
| 118 | return switch (@intToEnum(SparcFCMP, _Qp_cmp(a, b))) { | |
| 119 | .Equal, .Less => true, | |
| 120 | .Greater, .Unordered => false, | |
| 121 | }; | |
| 122 | } |
lib/compiler_rt/cmpxf2.zig created+50| ... | ... | @@ -0,0 +1,50 @@ |
| 1 | ///! The quoted behavior definitions are from | |
| 2 | ///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines | |
| 3 | const common = @import("./common.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | @export(__eqxf2, .{ .name = "__eqxf2", .linkage = common.linkage }); | |
| 10 | @export(__nexf2, .{ .name = "__nexf2", .linkage = common.linkage }); | |
| 11 | @export(__lexf2, .{ .name = "__lexf2", .linkage = common.linkage }); | |
| 12 | @export(__cmpxf2, .{ .name = "__cmpxf2", .linkage = common.linkage }); | |
| 13 | @export(__ltxf2, .{ .name = "__ltxf2", .linkage = common.linkage }); | |
| 14 | } | |
| 15 | ||
| 16 | /// "These functions calculate a <=> b. That is, if a is less than b, they return -1; | |
| 17 | /// if a is greater than b, they return 1; and if a and b are equal they return 0. | |
| 18 | /// If either argument is NaN they return 1..." | |
| 19 | /// | |
| 20 | /// Note that this matches the definition of `__lexf2`, `__eqxf2`, `__nexf2`, `__cmpxf2`, | |
| 21 | /// and `__ltxf2`. | |
| 22 | fn __cmpxf2(a: f80, b: f80) callconv(.C) i32 { | |
| 23 | return @enumToInt(comparef.cmp_f80(comparef.LE, a, b)); | |
| 24 | } | |
| 25 | ||
| 26 | /// "These functions return a value less than or equal to zero if neither argument is NaN, | |
| 27 | /// and a is less than or equal to b." | |
| 28 | fn __lexf2(a: f80, b: f80) callconv(.C) i32 { | |
| 29 | return __cmpxf2(a, b); | |
| 30 | } | |
| 31 | ||
| 32 | /// "These functions return zero if neither argument is NaN, and a and b are equal." | |
| 33 | /// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined | |
| 34 | /// to have the same return value. | |
| 35 | fn __eqxf2(a: f80, b: f80) callconv(.C) i32 { | |
| 36 | return __cmpxf2(a, b); | |
| 37 | } | |
| 38 | ||
| 39 | /// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." | |
| 40 | /// Note that due to some kind of historical accident, __eqxf2 and __nexf2 are defined | |
| 41 | /// to have the same return value. | |
| 42 | fn __nexf2(a: f80, b: f80) callconv(.C) i32 { | |
| 43 | return __cmpxf2(a, b); | |
| 44 | } | |
| 45 | ||
| 46 | /// "These functions return a value less than zero if neither argument is NaN, and a | |
| 47 | /// is strictly less than b." | |
| 48 | fn __ltxf2(a: f80, b: f80) callconv(.C) i32 { | |
| 49 | return __cmpxf2(a, b); | |
| 50 | } |
lib/compiler_rt/common.zig created+190| ... | ... | @@ -0,0 +1,190 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | ||
| 4 | pub const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak; | |
| 5 | pub const want_aeabi = switch (builtin.abi) { | |
| 6 | .eabi, | |
| 7 | .eabihf, | |
| 8 | .musleabi, | |
| 9 | .musleabihf, | |
| 10 | .gnueabi, | |
| 11 | .gnueabihf, | |
| 12 | => switch (builtin.cpu.arch) { | |
| 13 | .arm, .armeb, .thumb, .thumbeb => true, | |
| 14 | else => false, | |
| 15 | }, | |
| 16 | else => false, | |
| 17 | }; | |
| 18 | pub const want_ppc_abi = builtin.cpu.arch.isPPC() or builtin.cpu.arch.isPPC64(); | |
| 19 | ||
| 20 | /// This governs whether to use these symbol names for f16/f32 conversions | |
| 21 | /// rather than the standard names: | |
| 22 | /// * __gnu_f2h_ieee | |
| 23 | /// * __gnu_h2f_ieee | |
| 24 | /// Known correct configurations: | |
| 25 | /// x86_64-freestanding-none => true | |
| 26 | /// x86_64-linux-none => true | |
| 27 | /// x86_64-linux-gnu => true | |
| 28 | /// x86_64-linux-musl => true | |
| 29 | /// x86_64-linux-eabi => true | |
| 30 | /// arm-linux-musleabihf => true | |
| 31 | /// arm-linux-gnueabihf => true | |
| 32 | /// arm-linux-eabihf => false | |
| 33 | /// wasm32-wasi-musl => false | |
| 34 | /// wasm32-freestanding-none => false | |
| 35 | /// x86_64-windows-gnu => true | |
| 36 | /// x86_64-windows-msvc => true | |
| 37 | /// any-macos-any => false | |
| 38 | pub const gnu_f16_abi = switch (builtin.cpu.arch) { | |
| 39 | .wasm32, .wasm64 => false, | |
| 40 | ||
| 41 | .arm, .armeb, .thumb, .thumbeb => switch (builtin.abi) { | |
| 42 | .eabi, .eabihf => false, | |
| 43 | else => true, | |
| 44 | }, | |
| 45 | ||
| 46 | else => !builtin.os.tag.isDarwin(), | |
| 47 | }; | |
| 48 | ||
| 49 | pub const want_sparc_abi = builtin.cpu.arch.isSPARC(); | |
| 50 | ||
| 51 | // Avoid dragging in the runtime safety mechanisms into this .o file, | |
| 52 | // unless we're trying to test compiler-rt. | |
| 53 | pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn { | |
| 54 | _ = error_return_trace; | |
| 55 | if (builtin.is_test) { | |
| 56 | @setCold(true); | |
| 57 | std.debug.panic("{s}", .{msg}); | |
| 58 | } else { | |
| 59 | unreachable; | |
| 60 | } | |
| 61 | } | |
| 62 | ||
| 63 | /// AArch64 is the only ABI (at the moment) to support f16 arguments without the | |
| 64 | /// need for extending them to wider fp types. | |
| 65 | /// TODO remove this; do this type selection in the language rather than | |
| 66 | /// here in compiler-rt. | |
| 67 | pub const F16T = if (builtin.cpu.arch.isAARCH64()) f16 else u16; | |
| 68 | ||
| 69 | pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { | |
| 70 | switch (Z) { | |
| 71 | u16 => { | |
| 72 | // 16x16 --> 32 bit multiply | |
| 73 | const product = @as(u32, a) * @as(u32, b); | |
| 74 | hi.* = @intCast(u16, product >> 16); | |
| 75 | lo.* = @truncate(u16, product); | |
| 76 | }, | |
| 77 | u32 => { | |
| 78 | // 32x32 --> 64 bit multiply | |
| 79 | const product = @as(u64, a) * @as(u64, b); | |
| 80 | hi.* = @truncate(u32, product >> 32); | |
| 81 | lo.* = @truncate(u32, product); | |
| 82 | }, | |
| 83 | u64 => { | |
| 84 | const S = struct { | |
| 85 | fn loWord(x: u64) u64 { | |
| 86 | return @truncate(u32, x); | |
| 87 | } | |
| 88 | fn hiWord(x: u64) u64 { | |
| 89 | return @truncate(u32, x >> 32); | |
| 90 | } | |
| 91 | }; | |
| 92 | // 64x64 -> 128 wide multiply for platforms that don't have such an operation; | |
| 93 | // many 64-bit platforms have this operation, but they tend to have hardware | |
| 94 | // floating-point, so we don't bother with a special case for them here. | |
| 95 | // Each of the component 32x32 -> 64 products | |
| 96 | const plolo: u64 = S.loWord(a) * S.loWord(b); | |
| 97 | const plohi: u64 = S.loWord(a) * S.hiWord(b); | |
| 98 | const philo: u64 = S.hiWord(a) * S.loWord(b); | |
| 99 | const phihi: u64 = S.hiWord(a) * S.hiWord(b); | |
| 100 | // Sum terms that contribute to lo in a way that allows us to get the carry | |
| 101 | const r0: u64 = S.loWord(plolo); | |
| 102 | const r1: u64 = S.hiWord(plolo) +% S.loWord(plohi) +% S.loWord(philo); | |
| 103 | lo.* = r0 +% (r1 << 32); | |
| 104 | // Sum terms contributing to hi with the carry from lo | |
| 105 | hi.* = S.hiWord(plohi) +% S.hiWord(philo) +% S.hiWord(r1) +% phihi; | |
| 106 | }, | |
| 107 | u128 => { | |
| 108 | const Word_LoMask = @as(u64, 0x00000000ffffffff); | |
| 109 | const Word_HiMask = @as(u64, 0xffffffff00000000); | |
| 110 | const Word_FullMask = @as(u64, 0xffffffffffffffff); | |
| 111 | const S = struct { | |
| 112 | fn Word_1(x: u128) u64 { | |
| 113 | return @truncate(u32, x >> 96); | |
| 114 | } | |
| 115 | fn Word_2(x: u128) u64 { | |
| 116 | return @truncate(u32, x >> 64); | |
| 117 | } | |
| 118 | fn Word_3(x: u128) u64 { | |
| 119 | return @truncate(u32, x >> 32); | |
| 120 | } | |
| 121 | fn Word_4(x: u128) u64 { | |
| 122 | return @truncate(u32, x); | |
| 123 | } | |
| 124 | }; | |
| 125 | // 128x128 -> 256 wide multiply for platforms that don't have such an operation; | |
| 126 | // many 64-bit platforms have this operation, but they tend to have hardware | |
| 127 | // floating-point, so we don't bother with a special case for them here. | |
| 128 | ||
| 129 | const product11: u64 = S.Word_1(a) * S.Word_1(b); | |
| 130 | const product12: u64 = S.Word_1(a) * S.Word_2(b); | |
| 131 | const product13: u64 = S.Word_1(a) * S.Word_3(b); | |
| 132 | const product14: u64 = S.Word_1(a) * S.Word_4(b); | |
| 133 | const product21: u64 = S.Word_2(a) * S.Word_1(b); | |
| 134 | const product22: u64 = S.Word_2(a) * S.Word_2(b); | |
| 135 | const product23: u64 = S.Word_2(a) * S.Word_3(b); | |
| 136 | const product24: u64 = S.Word_2(a) * S.Word_4(b); | |
| 137 | const product31: u64 = S.Word_3(a) * S.Word_1(b); | |
| 138 | const product32: u64 = S.Word_3(a) * S.Word_2(b); | |
| 139 | const product33: u64 = S.Word_3(a) * S.Word_3(b); | |
| 140 | const product34: u64 = S.Word_3(a) * S.Word_4(b); | |
| 141 | const product41: u64 = S.Word_4(a) * S.Word_1(b); | |
| 142 | const product42: u64 = S.Word_4(a) * S.Word_2(b); | |
| 143 | const product43: u64 = S.Word_4(a) * S.Word_3(b); | |
| 144 | const product44: u64 = S.Word_4(a) * S.Word_4(b); | |
| 145 | ||
| 146 | const sum0: u128 = @as(u128, product44); | |
| 147 | const sum1: u128 = @as(u128, product34) +% | |
| 148 | @as(u128, product43); | |
| 149 | const sum2: u128 = @as(u128, product24) +% | |
| 150 | @as(u128, product33) +% | |
| 151 | @as(u128, product42); | |
| 152 | const sum3: u128 = @as(u128, product14) +% | |
| 153 | @as(u128, product23) +% | |
| 154 | @as(u128, product32) +% | |
| 155 | @as(u128, product41); | |
| 156 | const sum4: u128 = @as(u128, product13) +% | |
| 157 | @as(u128, product22) +% | |
| 158 | @as(u128, product31); | |
| 159 | const sum5: u128 = @as(u128, product12) +% | |
| 160 | @as(u128, product21); | |
| 161 | const sum6: u128 = @as(u128, product11); | |
| 162 | ||
| 163 | const r0: u128 = (sum0 & Word_FullMask) +% | |
| 164 | ((sum1 & Word_LoMask) << 32); | |
| 165 | const r1: u128 = (sum0 >> 64) +% | |
| 166 | ((sum1 >> 32) & Word_FullMask) +% | |
| 167 | (sum2 & Word_FullMask) +% | |
| 168 | ((sum3 << 32) & Word_HiMask); | |
| 169 | ||
| 170 | lo.* = r0 +% (r1 << 64); | |
| 171 | hi.* = (r1 >> 64) +% | |
| 172 | (sum1 >> 96) +% | |
| 173 | (sum2 >> 64) +% | |
| 174 | (sum3 >> 32) +% | |
| 175 | sum4 +% | |
| 176 | (sum5 << 32) +% | |
| 177 | (sum6 << 64); | |
| 178 | }, | |
| 179 | else => @compileError("unsupported"), | |
| 180 | } | |
| 181 | } | |
| 182 | ||
| 183 | pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T).Float.bits)) i32 { | |
| 184 | const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); | |
| 185 | const integerBit = @as(Z, 1) << std.math.floatFractionalBits(T); | |
| 186 | ||
| 187 | const shift = @clz(Z, significand.*) - @clz(Z, integerBit); | |
| 188 | significand.* <<= @intCast(std.math.Log2Int(Z), shift); | |
| 189 | return @as(i32, 1) - shift; | |
| 190 | } |
lib/compiler_rt/compareXf2.zig deleted-328| ... | ... | @@ -1,328 +0,0 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/comparesf2.c | |
| 4 | ||
| 5 | const std = @import("std"); | |
| 6 | const builtin = @import("builtin"); | |
| 7 | ||
| 8 | const LE = enum(i32) { | |
| 9 | Less = -1, | |
| 10 | Equal = 0, | |
| 11 | Greater = 1, | |
| 12 | ||
| 13 | const Unordered: LE = .Greater; | |
| 14 | }; | |
| 15 | ||
| 16 | const GE = enum(i32) { | |
| 17 | Less = -1, | |
| 18 | Equal = 0, | |
| 19 | Greater = 1, | |
| 20 | ||
| 21 | const Unordered: GE = .Less; | |
| 22 | }; | |
| 23 | ||
| 24 | pub inline fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT { | |
| 25 | @setRuntimeSafety(builtin.is_test); | |
| 26 | ||
| 27 | const bits = @typeInfo(T).Float.bits; | |
| 28 | const srep_t = std.meta.Int(.signed, bits); | |
| 29 | const rep_t = std.meta.Int(.unsigned, bits); | |
| 30 | ||
| 31 | const significandBits = std.math.floatMantissaBits(T); | |
| 32 | const exponentBits = std.math.floatExponentBits(T); | |
| 33 | const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); | |
| 34 | const absMask = signBit - 1; | |
| 35 | const infT = comptime std.math.inf(T); | |
| 36 | const infRep = @bitCast(rep_t, infT); | |
| 37 | ||
| 38 | const aInt = @bitCast(srep_t, a); | |
| 39 | const bInt = @bitCast(srep_t, b); | |
| 40 | const aAbs = @bitCast(rep_t, aInt) & absMask; | |
| 41 | const bAbs = @bitCast(rep_t, bInt) & absMask; | |
| 42 | ||
| 43 | // If either a or b is NaN, they are unordered. | |
| 44 | if (aAbs > infRep or bAbs > infRep) return RT.Unordered; | |
| 45 | ||
| 46 | // If a and b are both zeros, they are equal. | |
| 47 | if ((aAbs | bAbs) == 0) return .Equal; | |
| 48 | ||
| 49 | // If at least one of a and b is positive, we get the same result comparing | |
| 50 | // a and b as signed integers as we would with a floating-point compare. | |
| 51 | if ((aInt & bInt) >= 0) { | |
| 52 | if (aInt < bInt) { | |
| 53 | return .Less; | |
| 54 | } else if (aInt == bInt) { | |
| 55 | return .Equal; | |
| 56 | } else return .Greater; | |
| 57 | } else { | |
| 58 | // Otherwise, both are negative, so we need to flip the sense of the | |
| 59 | // comparison to get the correct result. (This assumes a twos- or ones- | |
| 60 | // complement integer representation; if integers are represented in a | |
| 61 | // sign-magnitude representation, then this flip is incorrect). | |
| 62 | if (aInt > bInt) { | |
| 63 | return .Less; | |
| 64 | } else if (aInt == bInt) { | |
| 65 | return .Equal; | |
| 66 | } else return .Greater; | |
| 67 | } | |
| 68 | } | |
| 69 | ||
| 70 | pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 { | |
| 71 | @setRuntimeSafety(builtin.is_test); | |
| 72 | ||
| 73 | const rep_t = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); | |
| 74 | ||
| 75 | const significandBits = std.math.floatMantissaBits(T); | |
| 76 | const exponentBits = std.math.floatExponentBits(T); | |
| 77 | const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); | |
| 78 | const absMask = signBit - 1; | |
| 79 | const infRep = @bitCast(rep_t, std.math.inf(T)); | |
| 80 | ||
| 81 | const aAbs: rep_t = @bitCast(rep_t, a) & absMask; | |
| 82 | const bAbs: rep_t = @bitCast(rep_t, b) & absMask; | |
| 83 | ||
| 84 | return @boolToInt(aAbs > infRep or bAbs > infRep); | |
| 85 | } | |
| 86 | ||
| 87 | // Comparison between f32 | |
| 88 | ||
| 89 | pub fn __lesf2(a: f32, b: f32) callconv(.C) i32 { | |
| 90 | @setRuntimeSafety(builtin.is_test); | |
| 91 | const float = cmp(f32, LE, a, b); | |
| 92 | return @bitCast(i32, float); | |
| 93 | } | |
| 94 | ||
| 95 | pub fn __gesf2(a: f32, b: f32) callconv(.C) i32 { | |
| 96 | @setRuntimeSafety(builtin.is_test); | |
| 97 | const float = cmp(f32, GE, a, b); | |
| 98 | return @bitCast(i32, float); | |
| 99 | } | |
| 100 | ||
| 101 | pub fn __eqsf2(a: f32, b: f32) callconv(.C) i32 { | |
| 102 | return __lesf2(a, b); | |
| 103 | } | |
| 104 | ||
| 105 | pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 { | |
| 106 | return __lesf2(a, b); | |
| 107 | } | |
| 108 | ||
| 109 | pub fn __nesf2(a: f32, b: f32) callconv(.C) i32 { | |
| 110 | return __lesf2(a, b); | |
| 111 | } | |
| 112 | ||
| 113 | pub fn __gtsf2(a: f32, b: f32) callconv(.C) i32 { | |
| 114 | return __gesf2(a, b); | |
| 115 | } | |
| 116 | ||
| 117 | // Comparison between f64 | |
| 118 | ||
| 119 | pub fn __ledf2(a: f64, b: f64) callconv(.C) i32 { | |
| 120 | @setRuntimeSafety(builtin.is_test); | |
| 121 | const float = cmp(f64, LE, a, b); | |
| 122 | return @bitCast(i32, float); | |
| 123 | } | |
| 124 | ||
| 125 | pub fn __gedf2(a: f64, b: f64) callconv(.C) i32 { | |
| 126 | @setRuntimeSafety(builtin.is_test); | |
| 127 | const float = cmp(f64, GE, a, b); | |
| 128 | return @bitCast(i32, float); | |
| 129 | } | |
| 130 | ||
| 131 | pub fn __eqdf2(a: f64, b: f64) callconv(.C) i32 { | |
| 132 | return __ledf2(a, b); | |
| 133 | } | |
| 134 | ||
| 135 | pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 { | |
| 136 | return __ledf2(a, b); | |
| 137 | } | |
| 138 | ||
| 139 | pub fn __nedf2(a: f64, b: f64) callconv(.C) i32 { | |
| 140 | return __ledf2(a, b); | |
| 141 | } | |
| 142 | ||
| 143 | pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 { | |
| 144 | return __gedf2(a, b); | |
| 145 | } | |
| 146 | ||
| 147 | // Comparison between f80 | |
| 148 | ||
| 149 | pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT { | |
| 150 | const a_rep = std.math.break_f80(a); | |
| 151 | const b_rep = std.math.break_f80(b); | |
| 152 | const sig_bits = std.math.floatMantissaBits(f80); | |
| 153 | const int_bit = 0x8000000000000000; | |
| 154 | const sign_bit = 0x8000; | |
| 155 | const special_exp = 0x7FFF; | |
| 156 | ||
| 157 | // If either a or b is NaN, they are unordered. | |
| 158 | if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or | |
| 159 | (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0)) | |
| 160 | return RT.Unordered; | |
| 161 | ||
| 162 | // If a and b are both zeros, they are equal. | |
| 163 | if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0) | |
| 164 | return .Equal; | |
| 165 | ||
| 166 | if (@boolToInt(a_rep.exp == b_rep.exp) & @boolToInt(a_rep.fraction == b_rep.fraction) != 0) { | |
| 167 | return .Equal; | |
| 168 | } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) { | |
| 169 | // signs are different | |
| 170 | if (@bitCast(i16, a_rep.exp) < @bitCast(i16, b_rep.exp)) { | |
| 171 | return .Less; | |
| 172 | } else { | |
| 173 | return .Greater; | |
| 174 | } | |
| 175 | } else { | |
| 176 | const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits); | |
| 177 | const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits); | |
| 178 | if (a_fraction < b_fraction) { | |
| 179 | return .Less; | |
| 180 | } else { | |
| 181 | return .Greater; | |
| 182 | } | |
| 183 | } | |
| 184 | } | |
| 185 | ||
| 186 | pub fn __lexf2(a: f80, b: f80) callconv(.C) i32 { | |
| 187 | @setRuntimeSafety(builtin.is_test); | |
| 188 | const float = cmp_f80(LE, a, b); | |
| 189 | return @bitCast(i32, float); | |
| 190 | } | |
| 191 | ||
| 192 | pub fn __gexf2(a: f80, b: f80) callconv(.C) i32 { | |
| 193 | @setRuntimeSafety(builtin.is_test); | |
| 194 | const float = cmp_f80(GE, a, b); | |
| 195 | return @bitCast(i32, float); | |
| 196 | } | |
| 197 | ||
| 198 | pub fn __eqxf2(a: f80, b: f80) callconv(.C) i32 { | |
| 199 | return __lexf2(a, b); | |
| 200 | } | |
| 201 | ||
| 202 | pub fn __ltxf2(a: f80, b: f80) callconv(.C) i32 { | |
| 203 | return __lexf2(a, b); | |
| 204 | } | |
| 205 | ||
| 206 | pub fn __nexf2(a: f80, b: f80) callconv(.C) i32 { | |
| 207 | return __lexf2(a, b); | |
| 208 | } | |
| 209 | ||
| 210 | pub fn __gtxf2(a: f80, b: f80) callconv(.C) i32 { | |
| 211 | return __gexf2(a, b); | |
| 212 | } | |
| 213 | ||
| 214 | // Comparison between f128 | |
| 215 | ||
| 216 | pub fn __letf2(a: f128, b: f128) callconv(.C) i32 { | |
| 217 | @setRuntimeSafety(builtin.is_test); | |
| 218 | const float = cmp(f128, LE, a, b); | |
| 219 | return @bitCast(i32, float); | |
| 220 | } | |
| 221 | ||
| 222 | pub fn __getf2(a: f128, b: f128) callconv(.C) i32 { | |
| 223 | @setRuntimeSafety(builtin.is_test); | |
| 224 | const float = cmp(f128, GE, a, b); | |
| 225 | return @bitCast(i32, float); | |
| 226 | } | |
| 227 | ||
| 228 | pub fn __eqtf2(a: f128, b: f128) callconv(.C) i32 { | |
| 229 | return __letf2(a, b); | |
| 230 | } | |
| 231 | ||
| 232 | pub fn __lttf2(a: f128, b: f128) callconv(.C) i32 { | |
| 233 | return __letf2(a, b); | |
| 234 | } | |
| 235 | ||
| 236 | pub fn __netf2(a: f128, b: f128) callconv(.C) i32 { | |
| 237 | return __letf2(a, b); | |
| 238 | } | |
| 239 | ||
| 240 | pub fn __gttf2(a: f128, b: f128) callconv(.C) i32 { | |
| 241 | return __getf2(a, b); | |
| 242 | } | |
| 243 | ||
| 244 | // Unordered comparison between f32/f64/f128 | |
| 245 | ||
| 246 | pub fn __unordsf2(a: f32, b: f32) callconv(.C) i32 { | |
| 247 | @setRuntimeSafety(builtin.is_test); | |
| 248 | return unordcmp(f32, a, b); | |
| 249 | } | |
| 250 | ||
| 251 | pub fn __unorddf2(a: f64, b: f64) callconv(.C) i32 { | |
| 252 | @setRuntimeSafety(builtin.is_test); | |
| 253 | return unordcmp(f64, a, b); | |
| 254 | } | |
| 255 | ||
| 256 | pub fn __unordtf2(a: f128, b: f128) callconv(.C) i32 { | |
| 257 | @setRuntimeSafety(builtin.is_test); | |
| 258 | return unordcmp(f128, a, b); | |
| 259 | } | |
| 260 | ||
| 261 | // ARM EABI intrinsics | |
| 262 | ||
| 263 | pub fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 264 | @setRuntimeSafety(false); | |
| 265 | return @boolToInt(@call(.{ .modifier = .always_inline }, __eqsf2, .{ a, b }) == 0); | |
| 266 | } | |
| 267 | ||
| 268 | pub fn __aeabi_fcmplt(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 269 | @setRuntimeSafety(false); | |
| 270 | return @boolToInt(@call(.{ .modifier = .always_inline }, __ltsf2, .{ a, b }) < 0); | |
| 271 | } | |
| 272 | ||
| 273 | pub fn __aeabi_fcmple(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 274 | @setRuntimeSafety(false); | |
| 275 | return @boolToInt(@call(.{ .modifier = .always_inline }, __lesf2, .{ a, b }) <= 0); | |
| 276 | } | |
| 277 | ||
| 278 | pub fn __aeabi_fcmpge(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 279 | @setRuntimeSafety(false); | |
| 280 | return @boolToInt(@call(.{ .modifier = .always_inline }, __gesf2, .{ a, b }) >= 0); | |
| 281 | } | |
| 282 | ||
| 283 | pub fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 284 | @setRuntimeSafety(false); | |
| 285 | return @boolToInt(@call(.{ .modifier = .always_inline }, __gtsf2, .{ a, b }) > 0); | |
| 286 | } | |
| 287 | ||
| 288 | pub fn __aeabi_fcmpun(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 289 | @setRuntimeSafety(false); | |
| 290 | return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b }); | |
| 291 | } | |
| 292 | ||
| 293 | pub fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 294 | @setRuntimeSafety(false); | |
| 295 | return @boolToInt(@call(.{ .modifier = .always_inline }, __eqdf2, .{ a, b }) == 0); | |
| 296 | } | |
| 297 | ||
| 298 | pub fn __aeabi_dcmplt(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 299 | @setRuntimeSafety(false); | |
| 300 | return @boolToInt(@call(.{ .modifier = .always_inline }, __ltdf2, .{ a, b }) < 0); | |
| 301 | } | |
| 302 | ||
| 303 | pub fn __aeabi_dcmple(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 304 | @setRuntimeSafety(false); | |
| 305 | return @boolToInt(@call(.{ .modifier = .always_inline }, __ledf2, .{ a, b }) <= 0); | |
| 306 | } | |
| 307 | ||
| 308 | pub fn __aeabi_dcmpge(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 309 | @setRuntimeSafety(false); | |
| 310 | return @boolToInt(@call(.{ .modifier = .always_inline }, __gedf2, .{ a, b }) >= 0); | |
| 311 | } | |
| 312 | ||
| 313 | pub fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 314 | @setRuntimeSafety(false); | |
| 315 | return @boolToInt(@call(.{ .modifier = .always_inline }, __gtdf2, .{ a, b }) > 0); | |
| 316 | } | |
| 317 | ||
| 318 | pub fn __aeabi_dcmpun(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 319 | @setRuntimeSafety(false); | |
| 320 | return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b }); | |
| 321 | } | |
| 322 | ||
| 323 | test "comparesf2" { | |
| 324 | _ = @import("comparesf2_test.zig"); | |
| 325 | } | |
| 326 | test "comparedf2" { | |
| 327 | _ = @import("comparedf2_test.zig"); | |
| 328 | } |
lib/compiler_rt/comparedf2_test.zig+16-8| ... | ... | @@ -6,7 +6,15 @@ const std = @import("std"); |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | 7 | const is_test = builtin.is_test; |
| 8 | 8 | |
| 9 | const comparedf2 = @import("compareXf2.zig"); | |
| 9 | const __eqdf2 = @import("./cmpdf2.zig").__eqdf2; | |
| 10 | const __ledf2 = @import("./cmpdf2.zig").__ledf2; | |
| 11 | const __ltdf2 = @import("./cmpdf2.zig").__ltdf2; | |
| 12 | const __nedf2 = @import("./cmpdf2.zig").__nedf2; | |
| 13 | ||
| 14 | const __gedf2 = @import("./gedf2.zig").__gedf2; | |
| 15 | const __gtdf2 = @import("./gedf2.zig").__gtdf2; | |
| 16 | ||
| 17 | const __unorddf2 = @import("./unorddf2.zig").__unorddf2; | |
| 10 | 18 | |
| 11 | 19 | const TestVector = struct { |
| 12 | 20 | a: f64, |
| ... | ... | @@ -21,25 +29,25 @@ const TestVector = struct { |
| 21 | 29 | }; |
| 22 | 30 | |
| 23 | 31 | fn test__cmpdf2(vector: TestVector) bool { |
| 24 | if (comparedf2.__eqdf2(vector.a, vector.b) != vector.eqReference) { | |
| 32 | if (__eqdf2(vector.a, vector.b) != vector.eqReference) { | |
| 25 | 33 | return false; |
| 26 | 34 | } |
| 27 | if (comparedf2.__gedf2(vector.a, vector.b) != vector.geReference) { | |
| 35 | if (__gedf2(vector.a, vector.b) != vector.geReference) { | |
| 28 | 36 | return false; |
| 29 | 37 | } |
| 30 | if (comparedf2.__gtdf2(vector.a, vector.b) != vector.gtReference) { | |
| 38 | if (__gtdf2(vector.a, vector.b) != vector.gtReference) { | |
| 31 | 39 | return false; |
| 32 | 40 | } |
| 33 | if (comparedf2.__ledf2(vector.a, vector.b) != vector.leReference) { | |
| 41 | if (__ledf2(vector.a, vector.b) != vector.leReference) { | |
| 34 | 42 | return false; |
| 35 | 43 | } |
| 36 | if (comparedf2.__ltdf2(vector.a, vector.b) != vector.ltReference) { | |
| 44 | if (__ltdf2(vector.a, vector.b) != vector.ltReference) { | |
| 37 | 45 | return false; |
| 38 | 46 | } |
| 39 | if (comparedf2.__nedf2(vector.a, vector.b) != vector.neReference) { | |
| 47 | if (__nedf2(vector.a, vector.b) != vector.neReference) { | |
| 40 | 48 | return false; |
| 41 | 49 | } |
| 42 | if (comparedf2.__unorddf2(vector.a, vector.b) != vector.unReference) { | |
| 50 | if (__unorddf2(vector.a, vector.b) != vector.unReference) { | |
| 43 | 51 | return false; |
| 44 | 52 | } |
| 45 | 53 | return true; |
lib/compiler_rt/comparef.zig created+118| ... | ... | @@ -0,0 +1,118 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub const LE = enum(i32) { | |
| 4 | Less = -1, | |
| 5 | Equal = 0, | |
| 6 | Greater = 1, | |
| 7 | ||
| 8 | const Unordered: LE = .Greater; | |
| 9 | }; | |
| 10 | ||
| 11 | pub const GE = enum(i32) { | |
| 12 | Less = -1, | |
| 13 | Equal = 0, | |
| 14 | Greater = 1, | |
| 15 | ||
| 16 | const Unordered: GE = .Less; | |
| 17 | }; | |
| 18 | ||
| 19 | pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT { | |
| 20 | const bits = @typeInfo(T).Float.bits; | |
| 21 | const srep_t = std.meta.Int(.signed, bits); | |
| 22 | const rep_t = std.meta.Int(.unsigned, bits); | |
| 23 | ||
| 24 | const significandBits = std.math.floatMantissaBits(T); | |
| 25 | const exponentBits = std.math.floatExponentBits(T); | |
| 26 | const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); | |
| 27 | const absMask = signBit - 1; | |
| 28 | const infT = comptime std.math.inf(T); | |
| 29 | const infRep = @bitCast(rep_t, infT); | |
| 30 | ||
| 31 | const aInt = @bitCast(srep_t, a); | |
| 32 | const bInt = @bitCast(srep_t, b); | |
| 33 | const aAbs = @bitCast(rep_t, aInt) & absMask; | |
| 34 | const bAbs = @bitCast(rep_t, bInt) & absMask; | |
| 35 | ||
| 36 | // If either a or b is NaN, they are unordered. | |
| 37 | if (aAbs > infRep or bAbs > infRep) return RT.Unordered; | |
| 38 | ||
| 39 | // If a and b are both zeros, they are equal. | |
| 40 | if ((aAbs | bAbs) == 0) return .Equal; | |
| 41 | ||
| 42 | // If at least one of a and b is positive, we get the same result comparing | |
| 43 | // a and b as signed integers as we would with a floating-point compare. | |
| 44 | if ((aInt & bInt) >= 0) { | |
| 45 | if (aInt < bInt) { | |
| 46 | return .Less; | |
| 47 | } else if (aInt == bInt) { | |
| 48 | return .Equal; | |
| 49 | } else return .Greater; | |
| 50 | } else { | |
| 51 | // Otherwise, both are negative, so we need to flip the sense of the | |
| 52 | // comparison to get the correct result. (This assumes a twos- or ones- | |
| 53 | // complement integer representation; if integers are represented in a | |
| 54 | // sign-magnitude representation, then this flip is incorrect). | |
| 55 | if (aInt > bInt) { | |
| 56 | return .Less; | |
| 57 | } else if (aInt == bInt) { | |
| 58 | return .Equal; | |
| 59 | } else return .Greater; | |
| 60 | } | |
| 61 | } | |
| 62 | ||
| 63 | pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT { | |
| 64 | const a_rep = std.math.break_f80(a); | |
| 65 | const b_rep = std.math.break_f80(b); | |
| 66 | const sig_bits = std.math.floatMantissaBits(f80); | |
| 67 | const int_bit = 0x8000000000000000; | |
| 68 | const sign_bit = 0x8000; | |
| 69 | const special_exp = 0x7FFF; | |
| 70 | ||
| 71 | // If either a or b is NaN, they are unordered. | |
| 72 | if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or | |
| 73 | (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0)) | |
| 74 | return RT.Unordered; | |
| 75 | ||
| 76 | // If a and b are both zeros, they are equal. | |
| 77 | if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0) | |
| 78 | return .Equal; | |
| 79 | ||
| 80 | if (@boolToInt(a_rep.exp == b_rep.exp) & @boolToInt(a_rep.fraction == b_rep.fraction) != 0) { | |
| 81 | return .Equal; | |
| 82 | } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) { | |
| 83 | // signs are different | |
| 84 | if (@bitCast(i16, a_rep.exp) < @bitCast(i16, b_rep.exp)) { | |
| 85 | return .Less; | |
| 86 | } else { | |
| 87 | return .Greater; | |
| 88 | } | |
| 89 | } else { | |
| 90 | const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits); | |
| 91 | const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits); | |
| 92 | if (a_fraction < b_fraction) { | |
| 93 | return .Less; | |
| 94 | } else { | |
| 95 | return .Greater; | |
| 96 | } | |
| 97 | } | |
| 98 | } | |
| 99 | ||
| 100 | pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 { | |
| 101 | const rep_t = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); | |
| 102 | ||
| 103 | const significandBits = std.math.floatMantissaBits(T); | |
| 104 | const exponentBits = std.math.floatExponentBits(T); | |
| 105 | const signBit = (@as(rep_t, 1) << (significandBits + exponentBits)); | |
| 106 | const absMask = signBit - 1; | |
| 107 | const infRep = @bitCast(rep_t, std.math.inf(T)); | |
| 108 | ||
| 109 | const aAbs: rep_t = @bitCast(rep_t, a) & absMask; | |
| 110 | const bAbs: rep_t = @bitCast(rep_t, b) & absMask; | |
| 111 | ||
| 112 | return @boolToInt(aAbs > infRep or bAbs > infRep); | |
| 113 | } | |
| 114 | ||
| 115 | test { | |
| 116 | _ = @import("comparesf2_test.zig"); | |
| 117 | _ = @import("comparedf2_test.zig"); | |
| 118 | } |
lib/compiler_rt/comparesf2_test.zig+16-8| ... | ... | @@ -6,7 +6,15 @@ const std = @import("std"); |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | 7 | const is_test = builtin.is_test; |
| 8 | 8 | |
| 9 | const comparesf2 = @import("compareXf2.zig"); | |
| 9 | const __eqsf2 = @import("./cmpsf2.zig").__eqsf2; | |
| 10 | const __lesf2 = @import("./cmpsf2.zig").__lesf2; | |
| 11 | const __ltsf2 = @import("./cmpsf2.zig").__ltsf2; | |
| 12 | const __nesf2 = @import("./cmpsf2.zig").__nesf2; | |
| 13 | ||
| 14 | const __gesf2 = @import("./gesf2.zig").__gesf2; | |
| 15 | const __gtsf2 = @import("./gesf2.zig").__gtsf2; | |
| 16 | ||
| 17 | const __unordsf2 = @import("./unordsf2.zig").__unordsf2; | |
| 10 | 18 | |
| 11 | 19 | const TestVector = struct { |
| 12 | 20 | a: f32, |
| ... | ... | @@ -21,25 +29,25 @@ const TestVector = struct { |
| 21 | 29 | }; |
| 22 | 30 | |
| 23 | 31 | fn test__cmpsf2(vector: TestVector) bool { |
| 24 | if (comparesf2.__eqsf2(vector.a, vector.b) != vector.eqReference) { | |
| 32 | if (__eqsf2(vector.a, vector.b) != vector.eqReference) { | |
| 25 | 33 | return false; |
| 26 | 34 | } |
| 27 | if (comparesf2.__gesf2(vector.a, vector.b) != vector.geReference) { | |
| 35 | if (__gesf2(vector.a, vector.b) != vector.geReference) { | |
| 28 | 36 | return false; |
| 29 | 37 | } |
| 30 | if (comparesf2.__gtsf2(vector.a, vector.b) != vector.gtReference) { | |
| 38 | if (__gtsf2(vector.a, vector.b) != vector.gtReference) { | |
| 31 | 39 | return false; |
| 32 | 40 | } |
| 33 | if (comparesf2.__lesf2(vector.a, vector.b) != vector.leReference) { | |
| 41 | if (__lesf2(vector.a, vector.b) != vector.leReference) { | |
| 34 | 42 | return false; |
| 35 | 43 | } |
| 36 | if (comparesf2.__ltsf2(vector.a, vector.b) != vector.ltReference) { | |
| 44 | if (__ltsf2(vector.a, vector.b) != vector.ltReference) { | |
| 37 | 45 | return false; |
| 38 | 46 | } |
| 39 | if (comparesf2.__nesf2(vector.a, vector.b) != vector.neReference) { | |
| 47 | if (__nesf2(vector.a, vector.b) != vector.neReference) { | |
| 40 | 48 | return false; |
| 41 | 49 | } |
| 42 | if (comparesf2.__unordsf2(vector.a, vector.b) != vector.unReference) { | |
| 50 | if (__unordsf2(vector.a, vector.b) != vector.unReference) { | |
| 43 | 51 | return false; |
| 44 | 52 | } |
| 45 | 53 | return true; |
lib/compiler_rt/cos.zig+15| ... | ... | @@ -1,11 +1,26 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | const arch = builtin.cpu.arch; | |
| 2 | 4 | const math = std.math; |
| 3 | 5 | const expect = std.testing.expect; |
| 6 | const common = @import("common.zig"); | |
| 7 | ||
| 8 | pub const panic = common.panic; | |
| 4 | 9 | |
| 5 | 10 | const trig = @import("trig.zig"); |
| 6 | 11 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 7 | 12 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 8 | 13 | |
| 14 | comptime { | |
| 15 | @export(__cosh, .{ .name = "__cosh", .linkage = common.linkage }); | |
| 16 | @export(cosf, .{ .name = "cosf", .linkage = common.linkage }); | |
| 17 | @export(cos, .{ .name = "cos", .linkage = common.linkage }); | |
| 18 | @export(__cosx, .{ .name = "__cosx", .linkage = common.linkage }); | |
| 19 | const cosq_sym_name = if (common.want_ppc_abi) "cosf128" else "cosq"; | |
| 20 | @export(cosq, .{ .name = cosq_sym_name, .linkage = common.linkage }); | |
| 21 | @export(cosl, .{ .name = "cosl", .linkage = common.linkage }); | |
| 22 | } | |
| 23 | ||
| 9 | 24 | pub fn __cosh(a: f16) callconv(.C) f16 { |
| 10 | 25 | // TODO: more efficient implementation |
| 11 | 26 | return @floatCast(f16, cosf(a)); |
lib/compiler_rt/count0bits.zig+16-6| ... | ... | @@ -1,5 +1,21 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | |
| 4 | const common = @import("common.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | @export(__clzsi2, .{ .name = "__clzsi2", .linkage = common.linkage }); | |
| 10 | @export(__clzdi2, .{ .name = "__clzdi2", .linkage = common.linkage }); | |
| 11 | @export(__clzti2, .{ .name = "__clzti2", .linkage = common.linkage }); | |
| 12 | @export(__ctzsi2, .{ .name = "__ctzsi2", .linkage = common.linkage }); | |
| 13 | @export(__ctzdi2, .{ .name = "__ctzdi2", .linkage = common.linkage }); | |
| 14 | @export(__ctzti2, .{ .name = "__ctzti2", .linkage = common.linkage }); | |
| 15 | @export(__ffssi2, .{ .name = "__ffssi2", .linkage = common.linkage }); | |
| 16 | @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = common.linkage }); | |
| 17 | @export(__ffsti2, .{ .name = "__ffsti2", .linkage = common.linkage }); | |
| 18 | } | |
| 3 | 19 | |
| 4 | 20 | // clz - count leading zeroes |
| 5 | 21 | // - clzXi2 for unoptimized little and big endian |
| ... | ... | @@ -15,8 +31,6 @@ const builtin = @import("builtin"); |
| 15 | 31 | // - ffsXi2 for unoptimized little and big endian |
| 16 | 32 | |
| 17 | 33 | inline fn clzXi2(comptime T: type, a: T) i32 { |
| 18 | @setRuntimeSafety(builtin.is_test); | |
| 19 | ||
| 20 | 34 | var x = switch (@bitSizeOf(T)) { |
| 21 | 35 | 32 => @bitCast(u32, a), |
| 22 | 36 | 64 => @bitCast(u64, a), |
| ... | ... | @@ -154,8 +168,6 @@ pub fn __clzti2(a: i128) callconv(.C) i32 { |
| 154 | 168 | } |
| 155 | 169 | |
| 156 | 170 | inline fn ctzXi2(comptime T: type, a: T) i32 { |
| 157 | @setRuntimeSafety(builtin.is_test); | |
| 158 | ||
| 159 | 171 | var x = switch (@bitSizeOf(T)) { |
| 160 | 172 | 32 => @bitCast(u32, a), |
| 161 | 173 | 64 => @bitCast(u64, a), |
| ... | ... | @@ -191,8 +203,6 @@ pub fn __ctzti2(a: i128) callconv(.C) i32 { |
| 191 | 203 | } |
| 192 | 204 | |
| 193 | 205 | inline fn ffsXi2(comptime T: type, a: T) i32 { |
| 194 | @setRuntimeSafety(builtin.is_test); | |
| 195 | ||
| 196 | 206 | var x = switch (@bitSizeOf(T)) { |
| 197 | 207 | 32 => @bitCast(u32, a), |
| 198 | 208 | 64 => @bitCast(u64, a), |
lib/compiler_rt/divdf3.zig+27-128| ... | ... | @@ -1,12 +1,35 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divdf3.c | |
| 1 | //! Ported from: | |
| 2 | //! | |
| 3 | //! https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divdf3.c | |
| 4 | 4 | |
| 5 | 5 | const std = @import("std"); |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | const arch = builtin.cpu.arch; | |
| 8 | const is_test = builtin.is_test; | |
| 9 | const common = @import("common.zig"); | |
| 10 | ||
| 11 | const normalize = common.normalize; | |
| 12 | const wideMultiply = common.wideMultiply; | |
| 13 | ||
| 14 | pub const panic = common.panic; | |
| 15 | ||
| 16 | comptime { | |
| 17 | if (common.want_aeabi) { | |
| 18 | @export(__aeabi_ddiv, .{ .name = "__aeabi_ddiv", .linkage = common.linkage }); | |
| 19 | } else { | |
| 20 | @export(__divdf3, .{ .name = "__divdf3", .linkage = common.linkage }); | |
| 21 | } | |
| 22 | } | |
| 7 | 23 | |
| 8 | 24 | pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 { |
| 9 | @setRuntimeSafety(builtin.is_test); | |
| 25 | return div(a, b); | |
| 26 | } | |
| 27 | ||
| 28 | fn __aeabi_ddiv(a: f64, b: f64) callconv(.AAPCS) f64 { | |
| 29 | return div(a, b); | |
| 30 | } | |
| 31 | ||
| 32 | inline fn div(a: f64, b: f64) f64 { | |
| 10 | 33 | const Z = std.meta.Int(.unsigned, 64); |
| 11 | 34 | const SignedZ = std.meta.Int(.signed, 64); |
| 12 | 35 | |
| ... | ... | @@ -202,130 +225,6 @@ pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 { |
| 202 | 225 | } |
| 203 | 226 | } |
| 204 | 227 | |
| 205 | pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { | |
| 206 | @setRuntimeSafety(builtin.is_test); | |
| 207 | switch (Z) { | |
| 208 | u32 => { | |
| 209 | // 32x32 --> 64 bit multiply | |
| 210 | const product = @as(u64, a) * @as(u64, b); | |
| 211 | hi.* = @truncate(u32, product >> 32); | |
| 212 | lo.* = @truncate(u32, product); | |
| 213 | }, | |
| 214 | u64 => { | |
| 215 | const S = struct { | |
| 216 | fn loWord(x: u64) u64 { | |
| 217 | return @truncate(u32, x); | |
| 218 | } | |
| 219 | fn hiWord(x: u64) u64 { | |
| 220 | return @truncate(u32, x >> 32); | |
| 221 | } | |
| 222 | }; | |
| 223 | // 64x64 -> 128 wide multiply for platforms that don't have such an operation; | |
| 224 | // many 64-bit platforms have this operation, but they tend to have hardware | |
| 225 | // floating-point, so we don't bother with a special case for them here. | |
| 226 | // Each of the component 32x32 -> 64 products | |
| 227 | const plolo: u64 = S.loWord(a) * S.loWord(b); | |
| 228 | const plohi: u64 = S.loWord(a) * S.hiWord(b); | |
| 229 | const philo: u64 = S.hiWord(a) * S.loWord(b); | |
| 230 | const phihi: u64 = S.hiWord(a) * S.hiWord(b); | |
| 231 | // Sum terms that contribute to lo in a way that allows us to get the carry | |
| 232 | const r0: u64 = S.loWord(plolo); | |
| 233 | const r1: u64 = S.hiWord(plolo) +% S.loWord(plohi) +% S.loWord(philo); | |
| 234 | lo.* = r0 +% (r1 << 32); | |
| 235 | // Sum terms contributing to hi with the carry from lo | |
| 236 | hi.* = S.hiWord(plohi) +% S.hiWord(philo) +% S.hiWord(r1) +% phihi; | |
| 237 | }, | |
| 238 | u128 => { | |
| 239 | const Word_LoMask = @as(u64, 0x00000000ffffffff); | |
| 240 | const Word_HiMask = @as(u64, 0xffffffff00000000); | |
| 241 | const Word_FullMask = @as(u64, 0xffffffffffffffff); | |
| 242 | const S = struct { | |
| 243 | fn Word_1(x: u128) u64 { | |
| 244 | return @truncate(u32, x >> 96); | |
| 245 | } | |
| 246 | fn Word_2(x: u128) u64 { | |
| 247 | return @truncate(u32, x >> 64); | |
| 248 | } | |
| 249 | fn Word_3(x: u128) u64 { | |
| 250 | return @truncate(u32, x >> 32); | |
| 251 | } | |
| 252 | fn Word_4(x: u128) u64 { | |
| 253 | return @truncate(u32, x); | |
| 254 | } | |
| 255 | }; | |
| 256 | // 128x128 -> 256 wide multiply for platforms that don't have such an operation; | |
| 257 | // many 64-bit platforms have this operation, but they tend to have hardware | |
| 258 | // floating-point, so we don't bother with a special case for them here. | |
| 259 | ||
| 260 | const product11: u64 = S.Word_1(a) * S.Word_1(b); | |
| 261 | const product12: u64 = S.Word_1(a) * S.Word_2(b); | |
| 262 | const product13: u64 = S.Word_1(a) * S.Word_3(b); | |
| 263 | const product14: u64 = S.Word_1(a) * S.Word_4(b); | |
| 264 | const product21: u64 = S.Word_2(a) * S.Word_1(b); | |
| 265 | const product22: u64 = S.Word_2(a) * S.Word_2(b); | |
| 266 | const product23: u64 = S.Word_2(a) * S.Word_3(b); | |
| 267 | const product24: u64 = S.Word_2(a) * S.Word_4(b); | |
| 268 | const product31: u64 = S.Word_3(a) * S.Word_1(b); | |
| 269 | const product32: u64 = S.Word_3(a) * S.Word_2(b); | |
| 270 | const product33: u64 = S.Word_3(a) * S.Word_3(b); | |
| 271 | const product34: u64 = S.Word_3(a) * S.Word_4(b); | |
| 272 | const product41: u64 = S.Word_4(a) * S.Word_1(b); | |
| 273 | const product42: u64 = S.Word_4(a) * S.Word_2(b); | |
| 274 | const product43: u64 = S.Word_4(a) * S.Word_3(b); | |
| 275 | const product44: u64 = S.Word_4(a) * S.Word_4(b); | |
| 276 | ||
| 277 | const sum0: u128 = @as(u128, product44); | |
| 278 | const sum1: u128 = @as(u128, product34) +% | |
| 279 | @as(u128, product43); | |
| 280 | const sum2: u128 = @as(u128, product24) +% | |
| 281 | @as(u128, product33) +% | |
| 282 | @as(u128, product42); | |
| 283 | const sum3: u128 = @as(u128, product14) +% | |
| 284 | @as(u128, product23) +% | |
| 285 | @as(u128, product32) +% | |
| 286 | @as(u128, product41); | |
| 287 | const sum4: u128 = @as(u128, product13) +% | |
| 288 | @as(u128, product22) +% | |
| 289 | @as(u128, product31); | |
| 290 | const sum5: u128 = @as(u128, product12) +% | |
| 291 | @as(u128, product21); | |
| 292 | const sum6: u128 = @as(u128, product11); | |
| 293 | ||
| 294 | const r0: u128 = (sum0 & Word_FullMask) +% | |
| 295 | ((sum1 & Word_LoMask) << 32); | |
| 296 | const r1: u128 = (sum0 >> 64) +% | |
| 297 | ((sum1 >> 32) & Word_FullMask) +% | |
| 298 | (sum2 & Word_FullMask) +% | |
| 299 | ((sum3 << 32) & Word_HiMask); | |
| 300 | ||
| 301 | lo.* = r0 +% (r1 << 64); | |
| 302 | hi.* = (r1 >> 64) +% | |
| 303 | (sum1 >> 96) +% | |
| 304 | (sum2 >> 64) +% | |
| 305 | (sum3 >> 32) +% | |
| 306 | sum4 +% | |
| 307 | (sum5 << 32) +% | |
| 308 | (sum6 << 64); | |
| 309 | }, | |
| 310 | else => @compileError("unsupported"), | |
| 311 | } | |
| 312 | } | |
| 313 | ||
| 314 | pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T).Float.bits)) i32 { | |
| 315 | @setRuntimeSafety(builtin.is_test); | |
| 316 | const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); | |
| 317 | const integerBit = @as(Z, 1) << std.math.floatFractionalBits(T); | |
| 318 | ||
| 319 | const shift = @clz(Z, significand.*) - @clz(Z, integerBit); | |
| 320 | significand.* <<= @intCast(std.math.Log2Int(Z), shift); | |
| 321 | return @as(i32, 1) - shift; | |
| 322 | } | |
| 323 | ||
| 324 | pub fn __aeabi_ddiv(a: f64, b: f64) callconv(.AAPCS) f64 { | |
| 325 | @setRuntimeSafety(false); | |
| 326 | return @call(.{ .modifier = .always_inline }, __divdf3, .{ a, b }); | |
| 327 | } | |
| 328 | ||
| 329 | 228 | test { |
| 330 | 229 | _ = @import("divdf3_test.zig"); |
| 331 | 230 | } |
lib/compiler_rt/divsf3.zig+25-20| ... | ... | @@ -1,12 +1,33 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divsf3.c | |
| 1 | //! Ported from: | |
| 2 | //! | |
| 3 | //! https://github.com/llvm/llvm-project/commit/d674d96bc56c0f377879d01c9d8dfdaaa7859cdb/compiler-rt/lib/builtins/divsf3.c | |
| 4 | 4 | |
| 5 | 5 | const std = @import("std"); |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | const arch = builtin.cpu.arch; | |
| 8 | ||
| 9 | const common = @import("common.zig"); | |
| 10 | const normalize = common.normalize; | |
| 11 | ||
| 12 | pub const panic = common.panic; | |
| 13 | ||
| 14 | comptime { | |
| 15 | if (common.want_aeabi) { | |
| 16 | @export(__aeabi_fdiv, .{ .name = "__aeabi_fdiv", .linkage = common.linkage }); | |
| 17 | } else { | |
| 18 | @export(__divsf3, .{ .name = "__divsf3", .linkage = common.linkage }); | |
| 19 | } | |
| 20 | } | |
| 7 | 21 | |
| 8 | 22 | pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 { |
| 9 | @setRuntimeSafety(builtin.is_test); | |
| 23 | return div(a, b); | |
| 24 | } | |
| 25 | ||
| 26 | fn __aeabi_fdiv(a: f32, b: f32) callconv(.AAPCS) f32 { | |
| 27 | return div(a, b); | |
| 28 | } | |
| 29 | ||
| 30 | inline fn div(a: f32, b: f32) f32 { | |
| 10 | 31 | const Z = std.meta.Int(.unsigned, 32); |
| 11 | 32 | |
| 12 | 33 | const significandBits = std.math.floatMantissaBits(f32); |
| ... | ... | @@ -184,22 +205,6 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 { |
| 184 | 205 | } |
| 185 | 206 | } |
| 186 | 207 | |
| 187 | fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T).Float.bits)) i32 { | |
| 188 | @setRuntimeSafety(builtin.is_test); | |
| 189 | const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); | |
| 190 | const significandBits = std.math.floatMantissaBits(T); | |
| 191 | const implicitBit = @as(Z, 1) << significandBits; | |
| 192 | ||
| 193 | const shift = @clz(Z, significand.*) - @clz(Z, implicitBit); | |
| 194 | significand.* <<= @intCast(std.math.Log2Int(Z), shift); | |
| 195 | return 1 - shift; | |
| 196 | } | |
| 197 | ||
| 198 | pub fn __aeabi_fdiv(a: f32, b: f32) callconv(.AAPCS) f32 { | |
| 199 | @setRuntimeSafety(false); | |
| 200 | return @call(.{ .modifier = .always_inline }, __divsf3, .{ a, b }); | |
| 201 | } | |
| 202 | ||
| 203 | 208 | test { |
| 204 | 209 | _ = @import("divsf3_test.zig"); |
| 205 | 210 | } |
lib/compiler_rt/divtf3.zig+27-3| ... | ... | @@ -1,11 +1,35 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | |
| 4 | const normalize = @import("divdf3.zig").normalize; | |
| 5 | const wideMultiply = @import("divdf3.zig").wideMultiply; | |
| 4 | const common = @import("common.zig"); | |
| 5 | const normalize = common.normalize; | |
| 6 | const wideMultiply = common.wideMultiply; | |
| 7 | ||
| 8 | pub const panic = common.panic; | |
| 9 | ||
| 10 | comptime { | |
| 11 | if (common.want_ppc_abi) { | |
| 12 | @export(__divkf3, .{ .name = "__divkf3", .linkage = common.linkage }); | |
| 13 | } else if (common.want_sparc_abi) { | |
| 14 | @export(_Qp_div, .{ .name = "_Qp_div", .linkage = common.linkage }); | |
| 15 | } else { | |
| 16 | @export(__divtf3, .{ .name = "__divtf3", .linkage = common.linkage }); | |
| 17 | } | |
| 18 | } | |
| 6 | 19 | |
| 7 | 20 | pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 { |
| 8 | @setRuntimeSafety(builtin.is_test); | |
| 21 | return div(a, b); | |
| 22 | } | |
| 23 | ||
| 24 | fn __divkf3(a: f128, b: f128) callconv(.C) f128 { | |
| 25 | return div(a, b); | |
| 26 | } | |
| 27 | ||
| 28 | fn _Qp_div(c: *f128, a: *const f128, b: *const f128) callconv(.C) void { | |
| 29 | c.* = div(a.*, b.*); | |
| 30 | } | |
| 31 | ||
| 32 | inline fn div(a: f128, b: f128) f128 { | |
| 9 | 33 | const Z = std.meta.Int(.unsigned, 128); |
| 10 | 34 | |
| 11 | 35 | const significandBits = std.math.floatMantissaBits(f128); |
lib/compiler_rt/divti3.zig+36-10| ... | ... | @@ -1,9 +1,43 @@ |
| 1 | const udivmod = @import("udivmod.zig").udivmod; | |
| 1 | const std = @import("std"); | |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const udivmod = @import("udivmod.zig").udivmod; | |
| 4 | const arch = builtin.cpu.arch; | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | if (builtin.os.tag == .windows) { | |
| 11 | switch (arch) { | |
| 12 | .i386 => { | |
| 13 | @export(__divti3, .{ .name = "__divti3", .linkage = common.linkage }); | |
| 14 | }, | |
| 15 | .x86_64 => { | |
| 16 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | |
| 17 | // that LLVM expects compiler-rt to have. | |
| 18 | @export(__divti3_windows_x86_64, .{ .name = "__divti3", .linkage = common.linkage }); | |
| 19 | }, | |
| 20 | else => {}, | |
| 21 | } | |
| 22 | if (arch.isAARCH64()) { | |
| 23 | @export(__divti3, .{ .name = "__divti3", .linkage = common.linkage }); | |
| 24 | } | |
| 25 | } else { | |
| 26 | @export(__divti3, .{ .name = "__divti3", .linkage = common.linkage }); | |
| 27 | } | |
| 28 | } | |
| 3 | 29 | |
| 4 | 30 | pub fn __divti3(a: i128, b: i128) callconv(.C) i128 { |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 31 | return div(a, b); | |
| 32 | } | |
| 6 | 33 | |
| 34 | const v128 = @import("std").meta.Vector(2, u64); | |
| 35 | ||
| 36 | fn __divti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 37 | return @bitCast(v128, div(@bitCast(i128, a), @bitCast(i128, b))); | |
| 38 | } | |
| 39 | ||
| 40 | inline fn div(a: i128, b: i128) i128 { | |
| 7 | 41 | const s_a = a >> (128 - 1); |
| 8 | 42 | const s_b = b >> (128 - 1); |
| 9 | 43 | |
| ... | ... | @@ -15,14 +49,6 @@ pub fn __divti3(a: i128, b: i128) callconv(.C) i128 { |
| 15 | 49 | return (@bitCast(i128, r) ^ s) -% s; |
| 16 | 50 | } |
| 17 | 51 | |
| 18 | const v128 = @import("std").meta.Vector(2, u64); | |
| 19 | pub fn __divti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 20 | return @bitCast(v128, @call(.{ .modifier = .always_inline }, __divti3, .{ | |
| 21 | @bitCast(i128, a), | |
| 22 | @bitCast(i128, b), | |
| 23 | })); | |
| 24 | } | |
| 25 | ||
| 26 | 52 | test { |
| 27 | 53 | _ = @import("divti3_test.zig"); |
| 28 | 54 | } |
lib/compiler_rt/divxf3.zig+11-3| ... | ... | @@ -1,10 +1,18 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const normalize = @import("divdf3.zig").normalize; | |
| 4 | const wideMultiply = @import("divdf3.zig").wideMultiply; | |
| 3 | const arch = builtin.cpu.arch; | |
| 4 | ||
| 5 | const common = @import("common.zig"); | |
| 6 | const normalize = common.normalize; | |
| 7 | const wideMultiply = common.wideMultiply; | |
| 8 | ||
| 9 | pub const panic = common.panic; | |
| 10 | ||
| 11 | comptime { | |
| 12 | @export(__divxf3, .{ .name = "__divxf3", .linkage = common.linkage }); | |
| 13 | } | |
| 5 | 14 | |
| 6 | 15 | pub fn __divxf3(a: f80, b: f80) callconv(.C) f80 { |
| 7 | @setRuntimeSafety(builtin.is_test); | |
| 8 | 16 | const T = f80; |
| 9 | 17 | const Z = std.meta.Int(.unsigned, @bitSizeOf(T)); |
| 10 | 18 |
lib/compiler_rt/emutls.zig+20-8| ... | ... | @@ -1,22 +1,26 @@ |
| 1 | // __emutls_get_address specific builtin | |
| 2 | // | |
| 3 | // derived work from LLVM Compiler Infrastructure - release 8.0 (MIT) | |
| 4 | // https://github.com/llvm-mirror/compiler-rt/blob/release_80/lib/builtins/emutls.c | |
| 5 | // | |
| 1 | //! __emutls_get_address specific builtin | |
| 2 | //! | |
| 3 | //! derived work from LLVM Compiler Infrastructure - release 8.0 (MIT) | |
| 4 | //! https://github.com/llvm-mirror/compiler-rt/blob/release_80/lib/builtins/emutls.c | |
| 6 | 5 | |
| 7 | 6 | const std = @import("std"); |
| 8 | 7 | const builtin = @import("builtin"); |
| 8 | const common = @import("common.zig"); | |
| 9 | 9 | |
| 10 | 10 | const abort = std.os.abort; |
| 11 | 11 | const assert = std.debug.assert; |
| 12 | 12 | const expect = std.testing.expect; |
| 13 | 13 | |
| 14 | // defined in C as: | |
| 15 | // typedef unsigned int gcc_word __attribute__((mode(word))); | |
| 14 | /// defined in C as: | |
| 15 | /// typedef unsigned int gcc_word __attribute__((mode(word))); | |
| 16 | 16 | const gcc_word = usize; |
| 17 | 17 | |
| 18 | pub const panic = common.panic; | |
| 19 | ||
| 18 | 20 | comptime { |
| 19 | assert(builtin.link_libc); | |
| 21 | if (builtin.link_libc and builtin.os.tag == .openbsd) { | |
| 22 | @export(__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = common.linkage }); | |
| 23 | } | |
| 20 | 24 | } |
| 21 | 25 | |
| 22 | 26 | /// public entrypoint for generated code using EmulatedTLS |
| ... | ... | @@ -319,6 +323,8 @@ const emutls_control = extern struct { |
| 319 | 323 | }; |
| 320 | 324 | |
| 321 | 325 | test "simple_allocator" { |
| 326 | if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest; | |
| 327 | ||
| 322 | 328 | var data1: *[64]u8 = simple_allocator.alloc([64]u8); |
| 323 | 329 | defer simple_allocator.free(data1); |
| 324 | 330 | for (data1) |*c| { |
| ... | ... | @@ -333,6 +339,8 @@ test "simple_allocator" { |
| 333 | 339 | } |
| 334 | 340 | |
| 335 | 341 | test "__emutls_get_address zeroed" { |
| 342 | if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest; | |
| 343 | ||
| 336 | 344 | var ctl = emutls_control.init(usize, null); |
| 337 | 345 | try expect(ctl.object.index == 0); |
| 338 | 346 | |
| ... | ... | @@ -352,6 +360,8 @@ test "__emutls_get_address zeroed" { |
| 352 | 360 | } |
| 353 | 361 | |
| 354 | 362 | test "__emutls_get_address with default_value" { |
| 363 | if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest; | |
| 364 | ||
| 355 | 365 | var value: usize = 5678; // default value |
| 356 | 366 | var ctl = emutls_control.init(usize, &value); |
| 357 | 367 | try expect(ctl.object.index == 0); |
| ... | ... | @@ -370,6 +380,8 @@ test "__emutls_get_address with default_value" { |
| 370 | 380 | } |
| 371 | 381 | |
| 372 | 382 | test "test default_value with differents sizes" { |
| 383 | if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest; | |
| 384 | ||
| 373 | 385 | const testType = struct { |
| 374 | 386 | fn _testType(comptime T: type, value: T) !void { |
| 375 | 387 | var def: T = value; |
lib/compiler_rt/exp.zig+15| ... | ... | @@ -5,8 +5,23 @@ |
| 5 | 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/exp.c |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 9 | const arch = builtin.cpu.arch; | |
| 8 | 10 | const math = std.math; |
| 9 | 11 | const expect = std.testing.expect; |
| 12 | const common = @import("common.zig"); | |
| 13 | ||
| 14 | pub const panic = common.panic; | |
| 15 | ||
| 16 | comptime { | |
| 17 | @export(__exph, .{ .name = "__exph", .linkage = common.linkage }); | |
| 18 | @export(expf, .{ .name = "expf", .linkage = common.linkage }); | |
| 19 | @export(exp, .{ .name = "exp", .linkage = common.linkage }); | |
| 20 | @export(__expx, .{ .name = "__expx", .linkage = common.linkage }); | |
| 21 | const expq_sym_name = if (common.want_ppc_abi) "expf128" else "expq"; | |
| 22 | @export(expq, .{ .name = expq_sym_name, .linkage = common.linkage }); | |
| 23 | @export(expl, .{ .name = "expl", .linkage = common.linkage }); | |
| 24 | } | |
| 10 | 25 | |
| 11 | 26 | pub fn __exph(a: f16) callconv(.C) f16 { |
| 12 | 27 | // TODO: more efficient implementation |
lib/compiler_rt/exp2.zig+15| ... | ... | @@ -5,8 +5,23 @@ |
| 5 | 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/exp2.c |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 9 | const arch = builtin.cpu.arch; | |
| 8 | 10 | const math = std.math; |
| 9 | 11 | const expect = std.testing.expect; |
| 12 | const common = @import("common.zig"); | |
| 13 | ||
| 14 | pub const panic = common.panic; | |
| 15 | ||
| 16 | comptime { | |
| 17 | @export(__exp2h, .{ .name = "__exp2h", .linkage = common.linkage }); | |
| 18 | @export(exp2f, .{ .name = "exp2f", .linkage = common.linkage }); | |
| 19 | @export(exp2, .{ .name = "exp2", .linkage = common.linkage }); | |
| 20 | @export(__exp2x, .{ .name = "__exp2x", .linkage = common.linkage }); | |
| 21 | const exp2q_sym_name = if (common.want_ppc_abi) "exp2f128" else "exp2q"; | |
| 22 | @export(exp2q, .{ .name = exp2q_sym_name, .linkage = common.linkage }); | |
| 23 | @export(exp2l, .{ .name = "exp2l", .linkage = common.linkage }); | |
| 24 | } | |
| 10 | 25 | |
| 11 | 26 | pub fn __exp2h(x: f16) callconv(.C) f16 { |
| 12 | 27 | // TODO: more efficient implementation |
lib/compiler_rt/extendXfYf2.zig deleted-112| ... | ... | @@ -1,112 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const is_test = builtin.is_test; | |
| 4 | const native_arch = builtin.cpu.arch; | |
| 5 | ||
| 6 | pub fn __extendsfdf2(a: f32) callconv(.C) f64 { | |
| 7 | return extendXfYf2(f64, f32, @bitCast(u32, a)); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __extenddftf2(a: f64) callconv(.C) f128 { | |
| 11 | return extendXfYf2(f128, f64, @bitCast(u64, a)); | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __extendsftf2(a: f32) callconv(.C) f128 { | |
| 15 | return extendXfYf2(f128, f32, @bitCast(u32, a)); | |
| 16 | } | |
| 17 | ||
| 18 | // AArch64 is the only ABI (at the moment) to support f16 arguments without the | |
| 19 | // need for extending them to wider fp types. | |
| 20 | pub const F16T = if (native_arch.isAARCH64()) f16 else u16; | |
| 21 | ||
| 22 | pub fn __extendhfsf2(a: F16T) callconv(.C) f32 { | |
| 23 | return extendXfYf2(f32, f16, @bitCast(u16, a)); | |
| 24 | } | |
| 25 | ||
| 26 | pub fn __extendhftf2(a: F16T) callconv(.C) f128 { | |
| 27 | return extendXfYf2(f128, f16, @bitCast(u16, a)); | |
| 28 | } | |
| 29 | ||
| 30 | pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 { | |
| 31 | @setRuntimeSafety(false); | |
| 32 | return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, arg }); | |
| 33 | } | |
| 34 | ||
| 35 | pub fn __aeabi_f2d(arg: f32) callconv(.AAPCS) f64 { | |
| 36 | @setRuntimeSafety(false); | |
| 37 | return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f64, f32, @bitCast(u32, arg) }); | |
| 38 | } | |
| 39 | ||
| 40 | inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) dst_t { | |
| 41 | @setRuntimeSafety(builtin.is_test); | |
| 42 | ||
| 43 | const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits); | |
| 44 | const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits); | |
| 45 | const srcSigBits = std.math.floatMantissaBits(src_t); | |
| 46 | const dstSigBits = std.math.floatMantissaBits(dst_t); | |
| 47 | const DstShift = std.math.Log2Int(dst_rep_t); | |
| 48 | ||
| 49 | // Various constants whose values follow from the type parameters. | |
| 50 | // Any reasonable optimizer will fold and propagate all of these. | |
| 51 | const srcBits = @bitSizeOf(src_t); | |
| 52 | const srcExpBits = srcBits - srcSigBits - 1; | |
| 53 | const srcInfExp = (1 << srcExpBits) - 1; | |
| 54 | const srcExpBias = srcInfExp >> 1; | |
| 55 | ||
| 56 | const srcMinNormal = 1 << srcSigBits; | |
| 57 | const srcInfinity = srcInfExp << srcSigBits; | |
| 58 | const srcSignMask = 1 << (srcSigBits + srcExpBits); | |
| 59 | const srcAbsMask = srcSignMask - 1; | |
| 60 | const srcQNaN = 1 << (srcSigBits - 1); | |
| 61 | const srcNaNCode = srcQNaN - 1; | |
| 62 | ||
| 63 | const dstBits = @bitSizeOf(dst_t); | |
| 64 | const dstExpBits = dstBits - dstSigBits - 1; | |
| 65 | const dstInfExp = (1 << dstExpBits) - 1; | |
| 66 | const dstExpBias = dstInfExp >> 1; | |
| 67 | ||
| 68 | const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits; | |
| 69 | ||
| 70 | // Break a into a sign and representation of the absolute value | |
| 71 | const aRep: src_rep_t = @bitCast(src_rep_t, a); | |
| 72 | const aAbs: src_rep_t = aRep & srcAbsMask; | |
| 73 | const sign: src_rep_t = aRep & srcSignMask; | |
| 74 | var absResult: dst_rep_t = undefined; | |
| 75 | ||
| 76 | if (aAbs -% srcMinNormal < srcInfinity - srcMinNormal) { | |
| 77 | // a is a normal number. | |
| 78 | // Extend to the destination type by shifting the significand and | |
| 79 | // exponent into the proper position and rebiasing the exponent. | |
| 80 | absResult = @as(dst_rep_t, aAbs) << (dstSigBits - srcSigBits); | |
| 81 | absResult += (dstExpBias - srcExpBias) << dstSigBits; | |
| 82 | } else if (aAbs >= srcInfinity) { | |
| 83 | // a is NaN or infinity. | |
| 84 | // Conjure the result by beginning with infinity, then setting the qNaN | |
| 85 | // bit (if needed) and right-aligning the rest of the trailing NaN | |
| 86 | // payload field. | |
| 87 | absResult = dstInfExp << dstSigBits; | |
| 88 | absResult |= @as(dst_rep_t, aAbs & srcQNaN) << (dstSigBits - srcSigBits); | |
| 89 | absResult |= @as(dst_rep_t, aAbs & srcNaNCode) << (dstSigBits - srcSigBits); | |
| 90 | } else if (aAbs != 0) { | |
| 91 | // a is denormal. | |
| 92 | // renormalize the significand and clear the leading bit, then insert | |
| 93 | // the correct adjusted exponent in the destination type. | |
| 94 | const scale: u32 = @clz(src_rep_t, aAbs) - | |
| 95 | @clz(src_rep_t, @as(src_rep_t, srcMinNormal)); | |
| 96 | absResult = @as(dst_rep_t, aAbs) << @intCast(DstShift, dstSigBits - srcSigBits + scale); | |
| 97 | absResult ^= dstMinNormal; | |
| 98 | const resultExponent: u32 = dstExpBias - srcExpBias - scale + 1; | |
| 99 | absResult |= @intCast(dst_rep_t, resultExponent) << dstSigBits; | |
| 100 | } else { | |
| 101 | // a is zero. | |
| 102 | absResult = 0; | |
| 103 | } | |
| 104 | ||
| 105 | // Apply the signbit to (dst_t)abs(a). | |
| 106 | const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits); | |
| 107 | return @bitCast(dst_t, result); | |
| 108 | } | |
| 109 | ||
| 110 | test { | |
| 111 | _ = @import("extendXfYf2_test.zig"); | |
| 112 | } |
lib/compiler_rt/extendXfYf2_test.zig deleted-206| ... | ... | @@ -1,206 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2; | |
| 3 | const __extendhftf2 = @import("extendXfYf2.zig").__extendhftf2; | |
| 4 | const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2; | |
| 5 | const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2; | |
| 6 | const F16T = @import("extendXfYf2.zig").F16T; | |
| 7 | ||
| 8 | fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) !void { | |
| 9 | const x = __extenddftf2(a); | |
| 10 | ||
| 11 | const rep = @bitCast(u128, x); | |
| 12 | const hi = @intCast(u64, rep >> 64); | |
| 13 | const lo = @truncate(u64, rep); | |
| 14 | ||
| 15 | if (hi == expectedHi and lo == expectedLo) | |
| 16 | return; | |
| 17 | ||
| 18 | // test other possible NaN representation(signal NaN) | |
| 19 | if (expectedHi == 0x7fff800000000000 and expectedLo == 0x0) { | |
| 20 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 21 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 22 | { | |
| 23 | return; | |
| 24 | } | |
| 25 | } | |
| 26 | ||
| 27 | @panic("__extenddftf2 test failure"); | |
| 28 | } | |
| 29 | ||
| 30 | fn test__extendhfsf2(a: u16, expected: u32) !void { | |
| 31 | const x = __extendhfsf2(@bitCast(F16T, a)); | |
| 32 | const rep = @bitCast(u32, x); | |
| 33 | ||
| 34 | if (rep == expected) { | |
| 35 | if (rep & 0x7fffffff > 0x7f800000) { | |
| 36 | return; // NaN is always unequal. | |
| 37 | } | |
| 38 | if (x == @bitCast(f32, expected)) { | |
| 39 | return; | |
| 40 | } | |
| 41 | } | |
| 42 | ||
| 43 | return error.TestFailure; | |
| 44 | } | |
| 45 | ||
| 46 | fn test__extendsftf2(a: f32, expectedHi: u64, expectedLo: u64) !void { | |
| 47 | const x = __extendsftf2(a); | |
| 48 | ||
| 49 | const rep = @bitCast(u128, x); | |
| 50 | const hi = @intCast(u64, rep >> 64); | |
| 51 | const lo = @truncate(u64, rep); | |
| 52 | ||
| 53 | if (hi == expectedHi and lo == expectedLo) | |
| 54 | return; | |
| 55 | ||
| 56 | // test other possible NaN representation(signal NaN) | |
| 57 | if (expectedHi == 0x7fff800000000000 and expectedLo == 0x0) { | |
| 58 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 59 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 60 | { | |
| 61 | return; | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | return error.TestFailure; | |
| 66 | } | |
| 67 | ||
| 68 | test "extenddftf2" { | |
| 69 | // qNaN | |
| 70 | try test__extenddftf2(makeQNaN64(), 0x7fff800000000000, 0x0); | |
| 71 | ||
| 72 | // NaN | |
| 73 | try test__extenddftf2(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0); | |
| 74 | ||
| 75 | // inf | |
| 76 | try test__extenddftf2(makeInf64(), 0x7fff000000000000, 0x0); | |
| 77 | ||
| 78 | // zero | |
| 79 | try test__extenddftf2(0.0, 0x0, 0x0); | |
| 80 | ||
| 81 | try test__extenddftf2(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000); | |
| 82 | ||
| 83 | try test__extenddftf2(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000); | |
| 84 | ||
| 85 | try test__extenddftf2(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000); | |
| 86 | ||
| 87 | try test__extenddftf2(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); | |
| 88 | } | |
| 89 | ||
| 90 | test "extendhfsf2" { | |
| 91 | try test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN | |
| 92 | try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN | |
| 93 | // On x86 the NaN becomes quiet because the return is pushed on the x87 | |
| 94 | // stack due to ABI requirements | |
| 95 | if (builtin.target.cpu.arch != .i386 and builtin.target.os.tag == .windows) | |
| 96 | try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN | |
| 97 | ||
| 98 | try test__extendhfsf2(0, 0); // 0 | |
| 99 | try test__extendhfsf2(0x8000, 0x80000000); // -0 | |
| 100 | ||
| 101 | try test__extendhfsf2(0x7c00, 0x7f800000); // inf | |
| 102 | try test__extendhfsf2(0xfc00, 0xff800000); // -inf | |
| 103 | ||
| 104 | try test__extendhfsf2(0x0001, 0x33800000); // denormal (min), 2**-24 | |
| 105 | try test__extendhfsf2(0x8001, 0xb3800000); // denormal (min), -2**-24 | |
| 106 | ||
| 107 | try test__extendhfsf2(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 | |
| 108 | try test__extendhfsf2(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 | |
| 109 | ||
| 110 | try test__extendhfsf2(0x0400, 0x38800000); // normal (min), 2**-14 | |
| 111 | try test__extendhfsf2(0x8400, 0xb8800000); // normal (min), -2**-14 | |
| 112 | ||
| 113 | try test__extendhfsf2(0x7bff, 0x477fe000); // normal (max), 65504 | |
| 114 | try test__extendhfsf2(0xfbff, 0xc77fe000); // normal (max), -65504 | |
| 115 | ||
| 116 | try test__extendhfsf2(0x3c01, 0x3f802000); // normal, 1 + 2**-10 | |
| 117 | try test__extendhfsf2(0xbc01, 0xbf802000); // normal, -1 - 2**-10 | |
| 118 | ||
| 119 | try test__extendhfsf2(0x3555, 0x3eaaa000); // normal, approx. 1/3 | |
| 120 | try test__extendhfsf2(0xb555, 0xbeaaa000); // normal, approx. -1/3 | |
| 121 | } | |
| 122 | ||
| 123 | test "extendsftf2" { | |
| 124 | // qNaN | |
| 125 | try test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0); | |
| 126 | // NaN | |
| 127 | try test__extendsftf2(makeNaN32(0x410000), 0x7fff820000000000, 0x0); | |
| 128 | // inf | |
| 129 | try test__extendsftf2(makeInf32(), 0x7fff000000000000, 0x0); | |
| 130 | // zero | |
| 131 | try test__extendsftf2(0.0, 0x0, 0x0); | |
| 132 | try test__extendsftf2(0x1.23456p+5, 0x4004234560000000, 0x0); | |
| 133 | try test__extendsftf2(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0); | |
| 134 | try test__extendsftf2(0x1.23456p+45, 0x402c234560000000, 0x0); | |
| 135 | try test__extendsftf2(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0); | |
| 136 | } | |
| 137 | ||
| 138 | fn makeQNaN64() f64 { | |
| 139 | return @bitCast(f64, @as(u64, 0x7ff8000000000000)); | |
| 140 | } | |
| 141 | ||
| 142 | fn makeInf64() f64 { | |
| 143 | return @bitCast(f64, @as(u64, 0x7ff0000000000000)); | |
| 144 | } | |
| 145 | ||
| 146 | fn makeNaN64(rand: u64) f64 { | |
| 147 | return @bitCast(f64, 0x7ff0000000000000 | (rand & 0xfffffffffffff)); | |
| 148 | } | |
| 149 | ||
| 150 | fn makeQNaN32() f32 { | |
| 151 | return @bitCast(f32, @as(u32, 0x7fc00000)); | |
| 152 | } | |
| 153 | ||
| 154 | fn makeNaN32(rand: u32) f32 { | |
| 155 | return @bitCast(f32, 0x7f800000 | (rand & 0x7fffff)); | |
| 156 | } | |
| 157 | ||
| 158 | fn makeInf32() f32 { | |
| 159 | return @bitCast(f32, @as(u32, 0x7f800000)); | |
| 160 | } | |
| 161 | ||
| 162 | fn test__extendhftf2(a: u16, expectedHi: u64, expectedLo: u64) !void { | |
| 163 | const x = __extendhftf2(@bitCast(F16T, a)); | |
| 164 | ||
| 165 | const rep = @bitCast(u128, x); | |
| 166 | const hi = @intCast(u64, rep >> 64); | |
| 167 | const lo = @truncate(u64, rep); | |
| 168 | ||
| 169 | if (hi == expectedHi and lo == expectedLo) | |
| 170 | return; | |
| 171 | ||
| 172 | // test other possible NaN representation(signal NaN) | |
| 173 | if (expectedHi == 0x7fff800000000000 and expectedLo == 0x0) { | |
| 174 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 175 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 176 | { | |
| 177 | return; | |
| 178 | } | |
| 179 | } | |
| 180 | ||
| 181 | return error.TestFailure; | |
| 182 | } | |
| 183 | ||
| 184 | test "extendhftf2" { | |
| 185 | // qNaN | |
| 186 | try test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0); | |
| 187 | // NaN | |
| 188 | try test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0); | |
| 189 | // inf | |
| 190 | try test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0); | |
| 191 | try test__extendhftf2(0xfc00, 0xffff000000000000, 0x0); | |
| 192 | // zero | |
| 193 | try test__extendhftf2(0x0000, 0x0000000000000000, 0x0); | |
| 194 | try test__extendhftf2(0x8000, 0x8000000000000000, 0x0); | |
| 195 | // denormal | |
| 196 | try test__extendhftf2(0x0010, 0x3feb000000000000, 0x0); | |
| 197 | try test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0); | |
| 198 | try test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0); | |
| 199 | ||
| 200 | // pi | |
| 201 | try test__extendhftf2(0x4248, 0x4000920000000000, 0x0); | |
| 202 | try test__extendhftf2(0xc248, 0xc000920000000000, 0x0); | |
| 203 | ||
| 204 | try test__extendhftf2(0x508c, 0x4004230000000000, 0x0); | |
| 205 | try test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0); | |
| 206 | } |
lib/compiler_rt/extend_f80.zig deleted-131| ... | ... | @@ -1,131 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const is_test = builtin.is_test; | |
| 4 | const native_arch = builtin.cpu.arch; | |
| 5 | ||
| 6 | // AArch64 is the only ABI (at the moment) to support f16 arguments without the | |
| 7 | // need for extending them to wider fp types. | |
| 8 | pub const F16T = if (native_arch.isAARCH64()) f16 else u16; | |
| 9 | ||
| 10 | pub fn __extendhfxf2(a: F16T) callconv(.C) f80 { | |
| 11 | return extendF80(f16, @bitCast(u16, a)); | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __extendsfxf2(a: f32) callconv(.C) f80 { | |
| 15 | return extendF80(f32, @bitCast(u32, a)); | |
| 16 | } | |
| 17 | ||
| 18 | pub fn __extenddfxf2(a: f64) callconv(.C) f80 { | |
| 19 | return extendF80(f64, @bitCast(u64, a)); | |
| 20 | } | |
| 21 | ||
| 22 | inline fn extendF80(comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) f80 { | |
| 23 | @setRuntimeSafety(builtin.is_test); | |
| 24 | ||
| 25 | const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits); | |
| 26 | const src_sig_bits = std.math.floatMantissaBits(src_t); | |
| 27 | const dst_int_bit = 0x8000000000000000; | |
| 28 | const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit | |
| 29 | ||
| 30 | const dst_exp_bias = 16383; | |
| 31 | ||
| 32 | const src_bits = @bitSizeOf(src_t); | |
| 33 | const src_exp_bits = src_bits - src_sig_bits - 1; | |
| 34 | const src_inf_exp = (1 << src_exp_bits) - 1; | |
| 35 | const src_exp_bias = src_inf_exp >> 1; | |
| 36 | ||
| 37 | const src_min_normal = 1 << src_sig_bits; | |
| 38 | const src_inf = src_inf_exp << src_sig_bits; | |
| 39 | const src_sign_mask = 1 << (src_sig_bits + src_exp_bits); | |
| 40 | const src_abs_mask = src_sign_mask - 1; | |
| 41 | const src_qnan = 1 << (src_sig_bits - 1); | |
| 42 | const src_nan_code = src_qnan - 1; | |
| 43 | ||
| 44 | var dst: std.math.F80 = undefined; | |
| 45 | ||
| 46 | // Break a into a sign and representation of the absolute value | |
| 47 | const a_abs = a & src_abs_mask; | |
| 48 | const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0; | |
| 49 | ||
| 50 | if (a_abs -% src_min_normal < src_inf - src_min_normal) { | |
| 51 | // a is a normal number. | |
| 52 | // Extend to the destination type by shifting the significand and | |
| 53 | // exponent into the proper position and rebiasing the exponent. | |
| 54 | dst.exp = @intCast(u16, a_abs >> src_sig_bits); | |
| 55 | dst.exp += dst_exp_bias - src_exp_bias; | |
| 56 | dst.fraction = @as(u64, a_abs) << (dst_sig_bits - src_sig_bits); | |
| 57 | dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers | |
| 58 | } else if (a_abs >= src_inf) { | |
| 59 | // a is NaN or infinity. | |
| 60 | // Conjure the result by beginning with infinity, then setting the qNaN | |
| 61 | // bit (if needed) and right-aligning the rest of the trailing NaN | |
| 62 | // payload field. | |
| 63 | dst.exp = 0x7fff; | |
| 64 | dst.fraction = dst_int_bit; | |
| 65 | dst.fraction |= @as(u64, a_abs & src_qnan) << (dst_sig_bits - src_sig_bits); | |
| 66 | dst.fraction |= @as(u64, a_abs & src_nan_code) << (dst_sig_bits - src_sig_bits); | |
| 67 | } else if (a_abs != 0) { | |
| 68 | // a is denormal. | |
| 69 | // renormalize the significand and clear the leading bit, then insert | |
| 70 | // the correct adjusted exponent in the destination type. | |
| 71 | const scale: u16 = @clz(src_rep_t, a_abs) - | |
| 72 | @clz(src_rep_t, @as(src_rep_t, src_min_normal)); | |
| 73 | ||
| 74 | dst.fraction = @as(u64, a_abs) << @intCast(u6, dst_sig_bits - src_sig_bits + scale); | |
| 75 | dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers | |
| 76 | dst.exp = @truncate(u16, a_abs >> @intCast(u4, src_sig_bits - scale)); | |
| 77 | dst.exp ^= 1; | |
| 78 | dst.exp |= dst_exp_bias - src_exp_bias - scale + 1; | |
| 79 | } else { | |
| 80 | // a is zero. | |
| 81 | dst.exp = 0; | |
| 82 | dst.fraction = 0; | |
| 83 | } | |
| 84 | ||
| 85 | dst.exp |= sign; | |
| 86 | return std.math.make_f80(dst); | |
| 87 | } | |
| 88 | ||
| 89 | pub fn __extendxftf2(a: f80) callconv(.C) f128 { | |
| 90 | @setRuntimeSafety(builtin.is_test); | |
| 91 | ||
| 92 | const src_int_bit: u64 = 0x8000000000000000; | |
| 93 | const src_sig_mask = ~src_int_bit; | |
| 94 | const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit | |
| 95 | const dst_sig_bits = std.math.floatMantissaBits(f128); | |
| 96 | ||
| 97 | const dst_bits = @bitSizeOf(f128); | |
| 98 | ||
| 99 | const dst_min_normal = @as(u128, 1) << dst_sig_bits; | |
| 100 | ||
| 101 | // Break a into a sign and representation of the absolute value | |
| 102 | var a_rep = std.math.break_f80(a); | |
| 103 | const sign = a_rep.exp & 0x8000; | |
| 104 | a_rep.exp &= 0x7FFF; | |
| 105 | var abs_result: u128 = undefined; | |
| 106 | ||
| 107 | if (a_rep.exp == 0 and a_rep.fraction == 0) { | |
| 108 | // zero | |
| 109 | abs_result = 0; | |
| 110 | } else if (a_rep.exp == 0x7FFF) { | |
| 111 | // a is nan or infinite | |
| 112 | abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); | |
| 113 | abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; | |
| 114 | } else if (a_rep.fraction & src_int_bit != 0) { | |
| 115 | // a is a normal value | |
| 116 | abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits); | |
| 117 | abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; | |
| 118 | } else { | |
| 119 | // a is denormal | |
| 120 | // renormalize the significand and clear the leading bit and integer part, | |
| 121 | // then insert the correct adjusted exponent in the destination type. | |
| 122 | const scale: u32 = @clz(u64, a_rep.fraction); | |
| 123 | abs_result = @as(u128, a_rep.fraction) << @intCast(u7, dst_sig_bits - src_sig_bits + scale + 1); | |
| 124 | abs_result ^= dst_min_normal; | |
| 125 | abs_result |= @as(u128, scale + 1) << dst_sig_bits; | |
| 126 | } | |
| 127 | ||
| 128 | // Apply the signbit to (dst_t)abs(a). | |
| 129 | const result: u128 align(@alignOf(f128)) = abs_result | @as(u128, sign) << (dst_bits - 16); | |
| 130 | return @bitCast(f128, result); | |
| 131 | } |
lib/compiler_rt/extenddftf2.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const extendf = @import("./extendf.zig").extendf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__extenddfkf2, .{ .name = "__extenddfkf2", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_dtoq, .{ .name = "_Qp_dtoq", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __extenddftf2(a: f64) callconv(.C) f128 { | |
| 17 | return extendf(f128, f64, @bitCast(u64, a)); | |
| 18 | } | |
| 19 | ||
| 20 | fn __extenddfkf2(a: f64) callconv(.C) f128 { | |
| 21 | return extendf(f128, f64, @bitCast(u64, a)); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void { | |
| 25 | c.* = extendf(f128, f64, @bitCast(u64, a)); | |
| 26 | } |
lib/compiler_rt/extenddfxf2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const extend_f80 = @import("./extendf.zig").extend_f80; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__extenddfxf2, .{ .name = "__extenddfxf2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __extenddfxf2(a: f64) callconv(.C) f80 { | |
| 11 | return extend_f80(f64, @bitCast(u64, a)); | |
| 12 | } |
lib/compiler_rt/extendf.zig created+142| ... | ... | @@ -0,0 +1,142 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub inline fn extendf( | |
| 4 | comptime dst_t: type, | |
| 5 | comptime src_t: type, | |
| 6 | a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits), | |
| 7 | ) dst_t { | |
| 8 | const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits); | |
| 9 | const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits); | |
| 10 | const srcSigBits = std.math.floatMantissaBits(src_t); | |
| 11 | const dstSigBits = std.math.floatMantissaBits(dst_t); | |
| 12 | const DstShift = std.math.Log2Int(dst_rep_t); | |
| 13 | ||
| 14 | // Various constants whose values follow from the type parameters. | |
| 15 | // Any reasonable optimizer will fold and propagate all of these. | |
| 16 | const srcBits = @bitSizeOf(src_t); | |
| 17 | const srcExpBits = srcBits - srcSigBits - 1; | |
| 18 | const srcInfExp = (1 << srcExpBits) - 1; | |
| 19 | const srcExpBias = srcInfExp >> 1; | |
| 20 | ||
| 21 | const srcMinNormal = 1 << srcSigBits; | |
| 22 | const srcInfinity = srcInfExp << srcSigBits; | |
| 23 | const srcSignMask = 1 << (srcSigBits + srcExpBits); | |
| 24 | const srcAbsMask = srcSignMask - 1; | |
| 25 | const srcQNaN = 1 << (srcSigBits - 1); | |
| 26 | const srcNaNCode = srcQNaN - 1; | |
| 27 | ||
| 28 | const dstBits = @bitSizeOf(dst_t); | |
| 29 | const dstExpBits = dstBits - dstSigBits - 1; | |
| 30 | const dstInfExp = (1 << dstExpBits) - 1; | |
| 31 | const dstExpBias = dstInfExp >> 1; | |
| 32 | ||
| 33 | const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits; | |
| 34 | ||
| 35 | // Break a into a sign and representation of the absolute value | |
| 36 | const aRep: src_rep_t = @bitCast(src_rep_t, a); | |
| 37 | const aAbs: src_rep_t = aRep & srcAbsMask; | |
| 38 | const sign: src_rep_t = aRep & srcSignMask; | |
| 39 | var absResult: dst_rep_t = undefined; | |
| 40 | ||
| 41 | if (aAbs -% srcMinNormal < srcInfinity - srcMinNormal) { | |
| 42 | // a is a normal number. | |
| 43 | // Extend to the destination type by shifting the significand and | |
| 44 | // exponent into the proper position and rebiasing the exponent. | |
| 45 | absResult = @as(dst_rep_t, aAbs) << (dstSigBits - srcSigBits); | |
| 46 | absResult += (dstExpBias - srcExpBias) << dstSigBits; | |
| 47 | } else if (aAbs >= srcInfinity) { | |
| 48 | // a is NaN or infinity. | |
| 49 | // Conjure the result by beginning with infinity, then setting the qNaN | |
| 50 | // bit (if needed) and right-aligning the rest of the trailing NaN | |
| 51 | // payload field. | |
| 52 | absResult = dstInfExp << dstSigBits; | |
| 53 | absResult |= @as(dst_rep_t, aAbs & srcQNaN) << (dstSigBits - srcSigBits); | |
| 54 | absResult |= @as(dst_rep_t, aAbs & srcNaNCode) << (dstSigBits - srcSigBits); | |
| 55 | } else if (aAbs != 0) { | |
| 56 | // a is denormal. | |
| 57 | // renormalize the significand and clear the leading bit, then insert | |
| 58 | // the correct adjusted exponent in the destination type. | |
| 59 | const scale: u32 = @clz(src_rep_t, aAbs) - | |
| 60 | @clz(src_rep_t, @as(src_rep_t, srcMinNormal)); | |
| 61 | absResult = @as(dst_rep_t, aAbs) << @intCast(DstShift, dstSigBits - srcSigBits + scale); | |
| 62 | absResult ^= dstMinNormal; | |
| 63 | const resultExponent: u32 = dstExpBias - srcExpBias - scale + 1; | |
| 64 | absResult |= @intCast(dst_rep_t, resultExponent) << dstSigBits; | |
| 65 | } else { | |
| 66 | // a is zero. | |
| 67 | absResult = 0; | |
| 68 | } | |
| 69 | ||
| 70 | // Apply the signbit to (dst_t)abs(a). | |
| 71 | const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits); | |
| 72 | return @bitCast(dst_t, result); | |
| 73 | } | |
| 74 | ||
| 75 | pub inline fn extend_f80(comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) f80 { | |
| 76 | const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits); | |
| 77 | const src_sig_bits = std.math.floatMantissaBits(src_t); | |
| 78 | const dst_int_bit = 0x8000000000000000; | |
| 79 | const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit | |
| 80 | ||
| 81 | const dst_exp_bias = 16383; | |
| 82 | ||
| 83 | const src_bits = @bitSizeOf(src_t); | |
| 84 | const src_exp_bits = src_bits - src_sig_bits - 1; | |
| 85 | const src_inf_exp = (1 << src_exp_bits) - 1; | |
| 86 | const src_exp_bias = src_inf_exp >> 1; | |
| 87 | ||
| 88 | const src_min_normal = 1 << src_sig_bits; | |
| 89 | const src_inf = src_inf_exp << src_sig_bits; | |
| 90 | const src_sign_mask = 1 << (src_sig_bits + src_exp_bits); | |
| 91 | const src_abs_mask = src_sign_mask - 1; | |
| 92 | const src_qnan = 1 << (src_sig_bits - 1); | |
| 93 | const src_nan_code = src_qnan - 1; | |
| 94 | ||
| 95 | var dst: std.math.F80 = undefined; | |
| 96 | ||
| 97 | // Break a into a sign and representation of the absolute value | |
| 98 | const a_abs = a & src_abs_mask; | |
| 99 | const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0; | |
| 100 | ||
| 101 | if (a_abs -% src_min_normal < src_inf - src_min_normal) { | |
| 102 | // a is a normal number. | |
| 103 | // Extend to the destination type by shifting the significand and | |
| 104 | // exponent into the proper position and rebiasing the exponent. | |
| 105 | dst.exp = @intCast(u16, a_abs >> src_sig_bits); | |
| 106 | dst.exp += dst_exp_bias - src_exp_bias; | |
| 107 | dst.fraction = @as(u64, a_abs) << (dst_sig_bits - src_sig_bits); | |
| 108 | dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers | |
| 109 | } else if (a_abs >= src_inf) { | |
| 110 | // a is NaN or infinity. | |
| 111 | // Conjure the result by beginning with infinity, then setting the qNaN | |
| 112 | // bit (if needed) and right-aligning the rest of the trailing NaN | |
| 113 | // payload field. | |
| 114 | dst.exp = 0x7fff; | |
| 115 | dst.fraction = dst_int_bit; | |
| 116 | dst.fraction |= @as(u64, a_abs & src_qnan) << (dst_sig_bits - src_sig_bits); | |
| 117 | dst.fraction |= @as(u64, a_abs & src_nan_code) << (dst_sig_bits - src_sig_bits); | |
| 118 | } else if (a_abs != 0) { | |
| 119 | // a is denormal. | |
| 120 | // renormalize the significand and clear the leading bit, then insert | |
| 121 | // the correct adjusted exponent in the destination type. | |
| 122 | const scale: u16 = @clz(src_rep_t, a_abs) - | |
| 123 | @clz(src_rep_t, @as(src_rep_t, src_min_normal)); | |
| 124 | ||
| 125 | dst.fraction = @as(u64, a_abs) << @intCast(u6, dst_sig_bits - src_sig_bits + scale); | |
| 126 | dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers | |
| 127 | dst.exp = @truncate(u16, a_abs >> @intCast(u4, src_sig_bits - scale)); | |
| 128 | dst.exp ^= 1; | |
| 129 | dst.exp |= dst_exp_bias - src_exp_bias - scale + 1; | |
| 130 | } else { | |
| 131 | // a is zero. | |
| 132 | dst.exp = 0; | |
| 133 | dst.fraction = 0; | |
| 134 | } | |
| 135 | ||
| 136 | dst.exp |= sign; | |
| 137 | return std.math.make_f80(dst); | |
| 138 | } | |
| 139 | ||
| 140 | test { | |
| 141 | _ = @import("extendf_test.zig"); | |
| 142 | } |
lib/compiler_rt/extendf_test.zig created+206| ... | ... | @@ -0,0 +1,206 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const __extendhfsf2 = @import("extendhfsf2.zig").__extendhfsf2; | |
| 3 | const __extendhftf2 = @import("extendhftf2.zig").__extendhftf2; | |
| 4 | const __extendsftf2 = @import("extendsftf2.zig").__extendsftf2; | |
| 5 | const __extenddftf2 = @import("extenddftf2.zig").__extenddftf2; | |
| 6 | const F16T = @import("./common.zig").F16T; | |
| 7 | ||
| 8 | fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { | |
| 9 | const x = __extenddftf2(a); | |
| 10 | ||
| 11 | const rep = @bitCast(u128, x); | |
| 12 | const hi = @intCast(u64, rep >> 64); | |
| 13 | const lo = @truncate(u64, rep); | |
| 14 | ||
| 15 | if (hi == expected_hi and lo == expected_lo) | |
| 16 | return; | |
| 17 | ||
| 18 | // test other possible NaN representation(signal NaN) | |
| 19 | if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 20 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 21 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 22 | { | |
| 23 | return; | |
| 24 | } | |
| 25 | } | |
| 26 | ||
| 27 | @panic("__extenddftf2 test failure"); | |
| 28 | } | |
| 29 | ||
| 30 | fn test__extendhfsf2(a: u16, expected: u32) !void { | |
| 31 | const x = __extendhfsf2(@bitCast(F16T, a)); | |
| 32 | const rep = @bitCast(u32, x); | |
| 33 | ||
| 34 | if (rep == expected) { | |
| 35 | if (rep & 0x7fffffff > 0x7f800000) { | |
| 36 | return; // NaN is always unequal. | |
| 37 | } | |
| 38 | if (x == @bitCast(f32, expected)) { | |
| 39 | return; | |
| 40 | } | |
| 41 | } | |
| 42 | ||
| 43 | return error.TestFailure; | |
| 44 | } | |
| 45 | ||
| 46 | fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { | |
| 47 | const x = __extendsftf2(a); | |
| 48 | ||
| 49 | const rep = @bitCast(u128, x); | |
| 50 | const hi = @intCast(u64, rep >> 64); | |
| 51 | const lo = @truncate(u64, rep); | |
| 52 | ||
| 53 | if (hi == expected_hi and lo == expected_lo) | |
| 54 | return; | |
| 55 | ||
| 56 | // test other possible NaN representation(signal NaN) | |
| 57 | if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 58 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 59 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 60 | { | |
| 61 | return; | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | return error.TestFailure; | |
| 66 | } | |
| 67 | ||
| 68 | test "extenddftf2" { | |
| 69 | // qNaN | |
| 70 | try test__extenddftf2(makeQNaN64(), 0x7fff800000000000, 0x0); | |
| 71 | ||
| 72 | // NaN | |
| 73 | try test__extenddftf2(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0); | |
| 74 | ||
| 75 | // inf | |
| 76 | try test__extenddftf2(makeInf64(), 0x7fff000000000000, 0x0); | |
| 77 | ||
| 78 | // zero | |
| 79 | try test__extenddftf2(0.0, 0x0, 0x0); | |
| 80 | ||
| 81 | try test__extenddftf2(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000); | |
| 82 | ||
| 83 | try test__extenddftf2(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000); | |
| 84 | ||
| 85 | try test__extenddftf2(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000); | |
| 86 | ||
| 87 | try test__extenddftf2(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); | |
| 88 | } | |
| 89 | ||
| 90 | test "extendhfsf2" { | |
| 91 | try test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN | |
| 92 | try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN | |
| 93 | // On x86 the NaN becomes quiet because the return is pushed on the x87 | |
| 94 | // stack due to ABI requirements | |
| 95 | if (builtin.target.cpu.arch != .i386 and builtin.target.os.tag == .windows) | |
| 96 | try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN | |
| 97 | ||
| 98 | try test__extendhfsf2(0, 0); // 0 | |
| 99 | try test__extendhfsf2(0x8000, 0x80000000); // -0 | |
| 100 | ||
| 101 | try test__extendhfsf2(0x7c00, 0x7f800000); // inf | |
| 102 | try test__extendhfsf2(0xfc00, 0xff800000); // -inf | |
| 103 | ||
| 104 | try test__extendhfsf2(0x0001, 0x33800000); // denormal (min), 2**-24 | |
| 105 | try test__extendhfsf2(0x8001, 0xb3800000); // denormal (min), -2**-24 | |
| 106 | ||
| 107 | try test__extendhfsf2(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 | |
| 108 | try test__extendhfsf2(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 | |
| 109 | ||
| 110 | try test__extendhfsf2(0x0400, 0x38800000); // normal (min), 2**-14 | |
| 111 | try test__extendhfsf2(0x8400, 0xb8800000); // normal (min), -2**-14 | |
| 112 | ||
| 113 | try test__extendhfsf2(0x7bff, 0x477fe000); // normal (max), 65504 | |
| 114 | try test__extendhfsf2(0xfbff, 0xc77fe000); // normal (max), -65504 | |
| 115 | ||
| 116 | try test__extendhfsf2(0x3c01, 0x3f802000); // normal, 1 + 2**-10 | |
| 117 | try test__extendhfsf2(0xbc01, 0xbf802000); // normal, -1 - 2**-10 | |
| 118 | ||
| 119 | try test__extendhfsf2(0x3555, 0x3eaaa000); // normal, approx. 1/3 | |
| 120 | try test__extendhfsf2(0xb555, 0xbeaaa000); // normal, approx. -1/3 | |
| 121 | } | |
| 122 | ||
| 123 | test "extendsftf2" { | |
| 124 | // qNaN | |
| 125 | try test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0); | |
| 126 | // NaN | |
| 127 | try test__extendsftf2(makeNaN32(0x410000), 0x7fff820000000000, 0x0); | |
| 128 | // inf | |
| 129 | try test__extendsftf2(makeInf32(), 0x7fff000000000000, 0x0); | |
| 130 | // zero | |
| 131 | try test__extendsftf2(0.0, 0x0, 0x0); | |
| 132 | try test__extendsftf2(0x1.23456p+5, 0x4004234560000000, 0x0); | |
| 133 | try test__extendsftf2(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0); | |
| 134 | try test__extendsftf2(0x1.23456p+45, 0x402c234560000000, 0x0); | |
| 135 | try test__extendsftf2(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0); | |
| 136 | } | |
| 137 | ||
| 138 | fn makeQNaN64() f64 { | |
| 139 | return @bitCast(f64, @as(u64, 0x7ff8000000000000)); | |
| 140 | } | |
| 141 | ||
| 142 | fn makeInf64() f64 { | |
| 143 | return @bitCast(f64, @as(u64, 0x7ff0000000000000)); | |
| 144 | } | |
| 145 | ||
| 146 | fn makeNaN64(rand: u64) f64 { | |
| 147 | return @bitCast(f64, 0x7ff0000000000000 | (rand & 0xfffffffffffff)); | |
| 148 | } | |
| 149 | ||
| 150 | fn makeQNaN32() f32 { | |
| 151 | return @bitCast(f32, @as(u32, 0x7fc00000)); | |
| 152 | } | |
| 153 | ||
| 154 | fn makeNaN32(rand: u32) f32 { | |
| 155 | return @bitCast(f32, 0x7f800000 | (rand & 0x7fffff)); | |
| 156 | } | |
| 157 | ||
| 158 | fn makeInf32() f32 { | |
| 159 | return @bitCast(f32, @as(u32, 0x7f800000)); | |
| 160 | } | |
| 161 | ||
| 162 | fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void { | |
| 163 | const x = __extendhftf2(@bitCast(F16T, a)); | |
| 164 | ||
| 165 | const rep = @bitCast(u128, x); | |
| 166 | const hi = @intCast(u64, rep >> 64); | |
| 167 | const lo = @truncate(u64, rep); | |
| 168 | ||
| 169 | if (hi == expected_hi and lo == expected_lo) | |
| 170 | return; | |
| 171 | ||
| 172 | // test other possible NaN representation(signal NaN) | |
| 173 | if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 174 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 175 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 176 | { | |
| 177 | return; | |
| 178 | } | |
| 179 | } | |
| 180 | ||
| 181 | return error.TestFailure; | |
| 182 | } | |
| 183 | ||
| 184 | test "extendhftf2" { | |
| 185 | // qNaN | |
| 186 | try test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0); | |
| 187 | // NaN | |
| 188 | try test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0); | |
| 189 | // inf | |
| 190 | try test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0); | |
| 191 | try test__extendhftf2(0xfc00, 0xffff000000000000, 0x0); | |
| 192 | // zero | |
| 193 | try test__extendhftf2(0x0000, 0x0000000000000000, 0x0); | |
| 194 | try test__extendhftf2(0x8000, 0x8000000000000000, 0x0); | |
| 195 | // denormal | |
| 196 | try test__extendhftf2(0x0010, 0x3feb000000000000, 0x0); | |
| 197 | try test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0); | |
| 198 | try test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0); | |
| 199 | ||
| 200 | // pi | |
| 201 | try test__extendhftf2(0x4248, 0x4000920000000000, 0x0); | |
| 202 | try test__extendhftf2(0xc248, 0xc000920000000000, 0x0); | |
| 203 | ||
| 204 | try test__extendhftf2(0x508c, 0x4004230000000000, 0x0); | |
| 205 | try test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0); | |
| 206 | } |
lib/compiler_rt/extendhfsf2.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const extendf = @import("./extendf.zig").extendf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.gnu_f16_abi) { | |
| 8 | @export(__gnu_h2f_ieee, .{ .name = "__gnu_h2f_ieee", .linkage = common.linkage }); | |
| 9 | } else if (common.want_aeabi) { | |
| 10 | @export(__aeabi_h2f, .{ .name = "__aeabi_h2f", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__extendhfsf2, .{ .name = "__extendhfsf2", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __extendhfsf2(a: common.F16T) callconv(.C) f32 { | |
| 17 | return extendf(f32, f16, @bitCast(u16, a)); | |
| 18 | } | |
| 19 | ||
| 20 | fn __gnu_h2f_ieee(a: common.F16T) callconv(.C) f32 { | |
| 21 | return extendf(f32, f16, @bitCast(u16, a)); | |
| 22 | } | |
| 23 | ||
| 24 | fn __aeabi_h2f(a: u16) callconv(.AAPCS) f32 { | |
| 25 | return extendf(f32, f16, @bitCast(u16, a)); | |
| 26 | } |
lib/compiler_rt/extendhftf2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const extendf = @import("./extendf.zig").extendf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__extendhftf2, .{ .name = "__extendhftf2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __extendhftf2(a: common.F16T) callconv(.C) f128 { | |
| 11 | return extendf(f128, f16, @bitCast(u16, a)); | |
| 12 | } |
lib/compiler_rt/extendhfxf2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const extend_f80 = @import("./extendf.zig").extend_f80; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__extendhfxf2, .{ .name = "__extendhfxf2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __extendhfxf2(a: common.F16T) callconv(.C) f80 { | |
| 11 | return extend_f80(f16, @bitCast(u16, a)); | |
| 12 | } |
lib/compiler_rt/extendsfdf2.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const extendf = @import("./extendf.zig").extendf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | fn __extendsfdf2(a: f32) callconv(.C) f64 { | |
| 15 | return extendf(f64, f32, @bitCast(u32, a)); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_f2d(a: f32) callconv(.AAPCS) f64 { | |
| 19 | return extendf(f64, f32, @bitCast(u32, a)); | |
| 20 | } |
lib/compiler_rt/extendsftf2.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const extendf = @import("./extendf.zig").extendf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__extendsfkf2, .{ .name = "__extendsfkf2", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_stoq, .{ .name = "_Qp_stoq", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__extendsftf2, .{ .name = "__extendsftf2", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __extendsftf2(a: f32) callconv(.C) f128 { | |
| 17 | return extendf(f128, f32, @bitCast(u32, a)); | |
| 18 | } | |
| 19 | ||
| 20 | fn __extendsfkf2(a: f32) callconv(.C) f128 { | |
| 21 | return extendf(f128, f32, @bitCast(u32, a)); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_stoq(c: *f128, a: f32) callconv(.C) void { | |
| 25 | c.* = extendf(f128, f32, @bitCast(u32, a)); | |
| 26 | } |
lib/compiler_rt/extendsfxf2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const extend_f80 = @import("./extendf.zig").extend_f80; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__extendsfxf2, .{ .name = "__extendsfxf2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __extendsfxf2(a: f32) callconv(.C) f80 { | |
| 11 | return extend_f80(f32, @bitCast(u32, a)); | |
| 12 | } |
lib/compiler_rt/extendxftf2.zig created+50| ... | ... | @@ -0,0 +1,50 @@ |
| 1 | const std = @import("std"); | |
| 2 | const common = @import("./common.zig"); | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__extendxftf2, .{ .name = "__extendxftf2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __extendxftf2(a: f80) callconv(.C) f128 { | |
| 11 | const src_int_bit: u64 = 0x8000000000000000; | |
| 12 | const src_sig_mask = ~src_int_bit; | |
| 13 | const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit | |
| 14 | const dst_sig_bits = std.math.floatMantissaBits(f128); | |
| 15 | ||
| 16 | const dst_bits = @bitSizeOf(f128); | |
| 17 | ||
| 18 | const dst_min_normal = @as(u128, 1) << dst_sig_bits; | |
| 19 | ||
| 20 | // Break a into a sign and representation of the absolute value | |
| 21 | var a_rep = std.math.break_f80(a); | |
| 22 | const sign = a_rep.exp & 0x8000; | |
| 23 | a_rep.exp &= 0x7FFF; | |
| 24 | var abs_result: u128 = undefined; | |
| 25 | ||
| 26 | if (a_rep.exp == 0 and a_rep.fraction == 0) { | |
| 27 | // zero | |
| 28 | abs_result = 0; | |
| 29 | } else if (a_rep.exp == 0x7FFF) { | |
| 30 | // a is nan or infinite | |
| 31 | abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits); | |
| 32 | abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; | |
| 33 | } else if (a_rep.fraction & src_int_bit != 0) { | |
| 34 | // a is a normal value | |
| 35 | abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits); | |
| 36 | abs_result |= @as(u128, a_rep.exp) << dst_sig_bits; | |
| 37 | } else { | |
| 38 | // a is denormal | |
| 39 | // renormalize the significand and clear the leading bit and integer part, | |
| 40 | // then insert the correct adjusted exponent in the destination type. | |
| 41 | const scale: u32 = @clz(u64, a_rep.fraction); | |
| 42 | abs_result = @as(u128, a_rep.fraction) << @intCast(u7, dst_sig_bits - src_sig_bits + scale + 1); | |
| 43 | abs_result ^= dst_min_normal; | |
| 44 | abs_result |= @as(u128, scale + 1) << dst_sig_bits; | |
| 45 | } | |
| 46 | ||
| 47 | // Apply the signbit to (dst_t)abs(a). | |
| 48 | const result: u128 align(@alignOf(f128)) = abs_result | @as(u128, sign) << (dst_bits - 16); | |
| 49 | return @bitCast(f128, result); | |
| 50 | } |
lib/compiler_rt/fabs.zig+15| ... | ... | @@ -1,4 +1,19 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | const arch = builtin.cpu.arch; | |
| 4 | const common = @import("common.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | @export(__fabsh, .{ .name = "__fabsh", .linkage = common.linkage }); | |
| 10 | @export(fabsf, .{ .name = "fabsf", .linkage = common.linkage }); | |
| 11 | @export(fabs, .{ .name = "fabs", .linkage = common.linkage }); | |
| 12 | @export(__fabsx, .{ .name = "__fabsx", .linkage = common.linkage }); | |
| 13 | const fabsq_sym_name = if (common.want_ppc_abi) "fabsf128" else "fabsq"; | |
| 14 | @export(fabsq, .{ .name = fabsq_sym_name, .linkage = common.linkage }); | |
| 15 | @export(fabsl, .{ .name = "fabsl", .linkage = common.linkage }); | |
| 16 | } | |
| 2 | 17 | |
| 3 | 18 | pub fn __fabsh(a: f16) callconv(.C) f16 { |
| 4 | 19 | return generic_fabs(a); |
lib/compiler_rt/fixXfYi.zig deleted-224| ... | ... | @@ -1,224 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const math = std.math; | |
| 3 | const Log2Int = math.Log2Int; | |
| 4 | const is_test = @import("builtin").is_test; | |
| 5 | ||
| 6 | pub inline fn fixXfYi(comptime I: type, a: anytype) I { | |
| 7 | @setRuntimeSafety(is_test); | |
| 8 | ||
| 9 | const F = @TypeOf(a); | |
| 10 | const float_bits = @typeInfo(F).Float.bits; | |
| 11 | const int_bits = @typeInfo(I).Int.bits; | |
| 12 | const rep_t = std.meta.Int(.unsigned, float_bits); | |
| 13 | const sig_bits = math.floatMantissaBits(F); | |
| 14 | const exp_bits = math.floatExponentBits(F); | |
| 15 | const fractional_bits = math.floatFractionalBits(F); | |
| 16 | ||
| 17 | const implicit_bit = if (F != f80) (@as(rep_t, 1) << sig_bits) else 0; | |
| 18 | const max_exp = (1 << (exp_bits - 1)); | |
| 19 | const exp_bias = max_exp - 1; | |
| 20 | const sig_mask = (@as(rep_t, 1) << sig_bits) - 1; | |
| 21 | ||
| 22 | // Break a into sign, exponent, significand | |
| 23 | const a_rep: rep_t = @bitCast(rep_t, a); | |
| 24 | const negative = (a_rep >> (float_bits - 1)) != 0; | |
| 25 | const exponent = @intCast(i32, (a_rep << 1) >> (sig_bits + 1)) - exp_bias; | |
| 26 | const significand: rep_t = (a_rep & sig_mask) | implicit_bit; | |
| 27 | ||
| 28 | // If the exponent is negative, the result rounds to zero. | |
| 29 | if (exponent < 0) return 0; | |
| 30 | ||
| 31 | // If the value is too large for the integer type, saturate. | |
| 32 | switch (@typeInfo(I).Int.signedness) { | |
| 33 | .unsigned => { | |
| 34 | if (negative) return 0; | |
| 35 | if (@intCast(c_uint, exponent) >= @minimum(int_bits, max_exp)) return math.maxInt(I); | |
| 36 | }, | |
| 37 | .signed => if (@intCast(c_uint, exponent) >= @minimum(int_bits - 1, max_exp)) { | |
| 38 | return if (negative) math.minInt(I) else math.maxInt(I); | |
| 39 | }, | |
| 40 | } | |
| 41 | ||
| 42 | // If 0 <= exponent < sig_bits, right shift to get the result. | |
| 43 | // Otherwise, shift left. | |
| 44 | var result: I = undefined; | |
| 45 | if (exponent < fractional_bits) { | |
| 46 | result = @intCast(I, significand >> @intCast(Log2Int(rep_t), fractional_bits - exponent)); | |
| 47 | } else { | |
| 48 | result = @intCast(I, significand) << @intCast(Log2Int(I), exponent - fractional_bits); | |
| 49 | } | |
| 50 | ||
| 51 | if ((@typeInfo(I).Int.signedness == .signed) and negative) | |
| 52 | return ~result +% 1; | |
| 53 | return result; | |
| 54 | } | |
| 55 | ||
| 56 | // Conversion from f16 | |
| 57 | ||
| 58 | pub fn __fixhfsi(a: f16) callconv(.C) i32 { | |
| 59 | return fixXfYi(i32, a); | |
| 60 | } | |
| 61 | ||
| 62 | pub fn __fixunshfsi(a: f16) callconv(.C) u32 { | |
| 63 | return fixXfYi(u32, a); | |
| 64 | } | |
| 65 | ||
| 66 | pub fn __fixhfdi(a: f16) callconv(.C) i64 { | |
| 67 | return fixXfYi(i64, a); | |
| 68 | } | |
| 69 | ||
| 70 | pub fn __fixunshfdi(a: f16) callconv(.C) u64 { | |
| 71 | return fixXfYi(u64, a); | |
| 72 | } | |
| 73 | ||
| 74 | pub fn __fixhfti(a: f16) callconv(.C) i128 { | |
| 75 | return fixXfYi(i128, a); | |
| 76 | } | |
| 77 | ||
| 78 | pub fn __fixunshfti(a: f16) callconv(.C) u128 { | |
| 79 | return fixXfYi(u128, a); | |
| 80 | } | |
| 81 | ||
| 82 | // Conversion from f32 | |
| 83 | ||
| 84 | pub fn __fixsfsi(a: f32) callconv(.C) i32 { | |
| 85 | return fixXfYi(i32, a); | |
| 86 | } | |
| 87 | ||
| 88 | pub fn __fixunssfsi(a: f32) callconv(.C) u32 { | |
| 89 | return fixXfYi(u32, a); | |
| 90 | } | |
| 91 | ||
| 92 | pub fn __fixsfdi(a: f32) callconv(.C) i64 { | |
| 93 | return fixXfYi(i64, a); | |
| 94 | } | |
| 95 | ||
| 96 | pub fn __fixunssfdi(a: f32) callconv(.C) u64 { | |
| 97 | return fixXfYi(u64, a); | |
| 98 | } | |
| 99 | ||
| 100 | pub fn __fixsfti(a: f32) callconv(.C) i128 { | |
| 101 | return fixXfYi(i128, a); | |
| 102 | } | |
| 103 | ||
| 104 | pub fn __fixunssfti(a: f32) callconv(.C) u128 { | |
| 105 | return fixXfYi(u128, a); | |
| 106 | } | |
| 107 | ||
| 108 | // Conversion from f64 | |
| 109 | ||
| 110 | pub fn __fixdfsi(a: f64) callconv(.C) i32 { | |
| 111 | return fixXfYi(i32, a); | |
| 112 | } | |
| 113 | ||
| 114 | pub fn __fixunsdfsi(a: f64) callconv(.C) u32 { | |
| 115 | return fixXfYi(u32, a); | |
| 116 | } | |
| 117 | ||
| 118 | pub fn __fixdfdi(a: f64) callconv(.C) i64 { | |
| 119 | return fixXfYi(i64, a); | |
| 120 | } | |
| 121 | ||
| 122 | pub fn __fixunsdfdi(a: f64) callconv(.C) u64 { | |
| 123 | return fixXfYi(u64, a); | |
| 124 | } | |
| 125 | ||
| 126 | pub fn __fixdfti(a: f64) callconv(.C) i128 { | |
| 127 | return fixXfYi(i128, a); | |
| 128 | } | |
| 129 | ||
| 130 | pub fn __fixunsdfti(a: f64) callconv(.C) u128 { | |
| 131 | return fixXfYi(u128, a); | |
| 132 | } | |
| 133 | ||
| 134 | // Conversion from f80 | |
| 135 | ||
| 136 | pub fn __fixxfsi(a: f80) callconv(.C) i32 { | |
| 137 | return fixXfYi(i32, a); | |
| 138 | } | |
| 139 | ||
| 140 | pub fn __fixunsxfsi(a: f80) callconv(.C) u32 { | |
| 141 | return fixXfYi(u32, a); | |
| 142 | } | |
| 143 | ||
| 144 | pub fn __fixxfdi(a: f80) callconv(.C) i64 { | |
| 145 | return fixXfYi(i64, a); | |
| 146 | } | |
| 147 | ||
| 148 | pub fn __fixunsxfdi(a: f80) callconv(.C) u64 { | |
| 149 | return fixXfYi(u64, a); | |
| 150 | } | |
| 151 | ||
| 152 | pub fn __fixxfti(a: f80) callconv(.C) i128 { | |
| 153 | return fixXfYi(i128, a); | |
| 154 | } | |
| 155 | ||
| 156 | pub fn __fixunsxfti(a: f80) callconv(.C) u128 { | |
| 157 | return fixXfYi(u128, a); | |
| 158 | } | |
| 159 | ||
| 160 | // Conversion from f128 | |
| 161 | ||
| 162 | pub fn __fixtfsi(a: f128) callconv(.C) i32 { | |
| 163 | return fixXfYi(i32, a); | |
| 164 | } | |
| 165 | ||
| 166 | pub fn __fixunstfsi(a: f128) callconv(.C) u32 { | |
| 167 | return fixXfYi(u32, a); | |
| 168 | } | |
| 169 | ||
| 170 | pub fn __fixtfdi(a: f128) callconv(.C) i64 { | |
| 171 | return fixXfYi(i64, a); | |
| 172 | } | |
| 173 | ||
| 174 | pub fn __fixunstfdi(a: f128) callconv(.C) u64 { | |
| 175 | return fixXfYi(u64, a); | |
| 176 | } | |
| 177 | ||
| 178 | pub fn __fixtfti(a: f128) callconv(.C) i128 { | |
| 179 | return fixXfYi(i128, a); | |
| 180 | } | |
| 181 | ||
| 182 | pub fn __fixunstfti(a: f128) callconv(.C) u128 { | |
| 183 | return fixXfYi(u128, a); | |
| 184 | } | |
| 185 | ||
| 186 | // Conversion from f32 | |
| 187 | ||
| 188 | pub fn __aeabi_f2iz(a: f32) callconv(.AAPCS) i32 { | |
| 189 | return fixXfYi(i32, a); | |
| 190 | } | |
| 191 | ||
| 192 | pub fn __aeabi_f2uiz(a: f32) callconv(.AAPCS) u32 { | |
| 193 | return fixXfYi(u32, a); | |
| 194 | } | |
| 195 | ||
| 196 | pub fn __aeabi_f2lz(a: f32) callconv(.AAPCS) i64 { | |
| 197 | return fixXfYi(i64, a); | |
| 198 | } | |
| 199 | ||
| 200 | pub fn __aeabi_f2ulz(a: f32) callconv(.AAPCS) u64 { | |
| 201 | return fixXfYi(u64, a); | |
| 202 | } | |
| 203 | ||
| 204 | // Conversion from f64 | |
| 205 | ||
| 206 | pub fn __aeabi_d2iz(a: f64) callconv(.AAPCS) i32 { | |
| 207 | return fixXfYi(i32, a); | |
| 208 | } | |
| 209 | ||
| 210 | pub fn __aeabi_d2uiz(a: f64) callconv(.AAPCS) u32 { | |
| 211 | return fixXfYi(u32, a); | |
| 212 | } | |
| 213 | ||
| 214 | pub fn __aeabi_d2lz(a: f64) callconv(.AAPCS) i64 { | |
| 215 | return fixXfYi(i64, a); | |
| 216 | } | |
| 217 | ||
| 218 | pub fn __aeabi_d2ulz(a: f64) callconv(.AAPCS) u64 { | |
| 219 | return fixXfYi(u64, a); | |
| 220 | } | |
| 221 | ||
| 222 | test { | |
| 223 | _ = @import("fixXfYi_test.zig"); | |
| 224 | } |
lib/compiler_rt/fixXfYi_test.zig deleted-948| ... | ... | @@ -1,948 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const testing = std.testing; | |
| 3 | const math = std.math; | |
| 4 | const fixXfYi = @import("fixXfYi.zig").fixXfYi; | |
| 5 | ||
| 6 | // Conversion from f32 | |
| 7 | const __fixsfsi = @import("fixXfYi.zig").__fixsfsi; | |
| 8 | const __fixunssfsi = @import("fixXfYi.zig").__fixunssfsi; | |
| 9 | const __fixsfdi = @import("fixXfYi.zig").__fixsfdi; | |
| 10 | const __fixunssfdi = @import("fixXfYi.zig").__fixunssfdi; | |
| 11 | const __fixsfti = @import("fixXfYi.zig").__fixsfti; | |
| 12 | const __fixunssfti = @import("fixXfYi.zig").__fixunssfti; | |
| 13 | ||
| 14 | // Conversion from f64 | |
| 15 | const __fixdfsi = @import("fixXfYi.zig").__fixdfsi; | |
| 16 | const __fixunsdfsi = @import("fixXfYi.zig").__fixunsdfsi; | |
| 17 | const __fixdfdi = @import("fixXfYi.zig").__fixdfdi; | |
| 18 | const __fixunsdfdi = @import("fixXfYi.zig").__fixunsdfdi; | |
| 19 | const __fixdfti = @import("fixXfYi.zig").__fixdfti; | |
| 20 | const __fixunsdfti = @import("fixXfYi.zig").__fixunsdfti; | |
| 21 | ||
| 22 | // Conversion from f128 | |
| 23 | const __fixtfsi = @import("fixXfYi.zig").__fixtfsi; | |
| 24 | const __fixunstfsi = @import("fixXfYi.zig").__fixunstfsi; | |
| 25 | const __fixtfdi = @import("fixXfYi.zig").__fixtfdi; | |
| 26 | const __fixunstfdi = @import("fixXfYi.zig").__fixunstfdi; | |
| 27 | const __fixtfti = @import("fixXfYi.zig").__fixtfti; | |
| 28 | const __fixunstfti = @import("fixXfYi.zig").__fixunstfti; | |
| 29 | ||
| 30 | fn test__fixsfsi(a: f32, expected: i32) !void { | |
| 31 | const x = __fixsfsi(a); | |
| 32 | try testing.expect(x == expected); | |
| 33 | } | |
| 34 | ||
| 35 | fn test__fixunssfsi(a: f32, expected: u32) !void { | |
| 36 | const x = __fixunssfsi(a); | |
| 37 | try testing.expect(x == expected); | |
| 38 | } | |
| 39 | ||
| 40 | test "fixsfsi" { | |
| 41 | try test__fixsfsi(-math.floatMax(f32), math.minInt(i32)); | |
| 42 | ||
| 43 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 44 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 45 | ||
| 46 | try test__fixsfsi(-0x1.0000000000000p+127, -0x80000000); | |
| 47 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 48 | try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 49 | ||
| 50 | try test__fixsfsi(-0x1.0000000000001p+63, -0x80000000); | |
| 51 | try test__fixsfsi(-0x1.0000000000000p+63, -0x80000000); | |
| 52 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 53 | try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 54 | ||
| 55 | try test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000); | |
| 56 | try test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000); | |
| 57 | ||
| 58 | try test__fixsfsi(-0x1.000000p+31, -0x80000000); | |
| 59 | try test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000); | |
| 60 | try test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 61 | try test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 62 | ||
| 63 | try test__fixsfsi(-2.01, -2); | |
| 64 | try test__fixsfsi(-2.0, -2); | |
| 65 | try test__fixsfsi(-1.99, -1); | |
| 66 | try test__fixsfsi(-1.0, -1); | |
| 67 | try test__fixsfsi(-0.99, 0); | |
| 68 | try test__fixsfsi(-0.5, 0); | |
| 69 | try test__fixsfsi(-math.floatMin(f32), 0); | |
| 70 | try test__fixsfsi(0.0, 0); | |
| 71 | try test__fixsfsi(math.floatMin(f32), 0); | |
| 72 | try test__fixsfsi(0.5, 0); | |
| 73 | try test__fixsfsi(0.99, 0); | |
| 74 | try test__fixsfsi(1.0, 1); | |
| 75 | try test__fixsfsi(1.5, 1); | |
| 76 | try test__fixsfsi(1.99, 1); | |
| 77 | try test__fixsfsi(2.0, 2); | |
| 78 | try test__fixsfsi(2.01, 2); | |
| 79 | ||
| 80 | try test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 81 | try test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 82 | try test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF); | |
| 83 | try test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF); | |
| 84 | ||
| 85 | try test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 86 | try test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 87 | ||
| 88 | try test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 89 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 90 | try test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 91 | try test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 92 | ||
| 93 | try test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 94 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 95 | try test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 96 | ||
| 97 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 98 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 99 | ||
| 100 | try test__fixsfsi(math.floatMax(f32), math.maxInt(i32)); | |
| 101 | } | |
| 102 | ||
| 103 | test "fixunssfsi" { | |
| 104 | try test__fixunssfsi(0.0, 0); | |
| 105 | ||
| 106 | try test__fixunssfsi(0.5, 0); | |
| 107 | try test__fixunssfsi(0.99, 0); | |
| 108 | try test__fixunssfsi(1.0, 1); | |
| 109 | try test__fixunssfsi(1.5, 1); | |
| 110 | try test__fixunssfsi(1.99, 1); | |
| 111 | try test__fixunssfsi(2.0, 2); | |
| 112 | try test__fixunssfsi(2.01, 2); | |
| 113 | try test__fixunssfsi(-0.5, 0); | |
| 114 | try test__fixunssfsi(-0.99, 0); | |
| 115 | ||
| 116 | try test__fixunssfsi(-1.0, 0); | |
| 117 | try test__fixunssfsi(-1.5, 0); | |
| 118 | try test__fixunssfsi(-1.99, 0); | |
| 119 | try test__fixunssfsi(-2.0, 0); | |
| 120 | try test__fixunssfsi(-2.01, 0); | |
| 121 | ||
| 122 | try test__fixunssfsi(0x1.000000p+31, 0x80000000); | |
| 123 | try test__fixunssfsi(0x1.000000p+32, 0xFFFFFFFF); | |
| 124 | try test__fixunssfsi(0x1.FFFFFEp+31, 0xFFFFFF00); | |
| 125 | try test__fixunssfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 126 | try test__fixunssfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 127 | ||
| 128 | try test__fixunssfsi(-0x1.FFFFFEp+30, 0); | |
| 129 | try test__fixunssfsi(-0x1.FFFFFCp+30, 0); | |
| 130 | } | |
| 131 | ||
| 132 | fn test__fixsfdi(a: f32, expected: i64) !void { | |
| 133 | const x = __fixsfdi(a); | |
| 134 | try testing.expect(x == expected); | |
| 135 | } | |
| 136 | ||
| 137 | fn test__fixunssfdi(a: f32, expected: u64) !void { | |
| 138 | const x = __fixunssfdi(a); | |
| 139 | try testing.expect(x == expected); | |
| 140 | } | |
| 141 | ||
| 142 | test "fixsfdi" { | |
| 143 | try test__fixsfdi(-math.floatMax(f32), math.minInt(i64)); | |
| 144 | ||
| 145 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 146 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 147 | ||
| 148 | try test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 149 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 150 | try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 151 | ||
| 152 | try test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 153 | try test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 154 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | |
| 155 | try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | |
| 156 | ||
| 157 | try test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000); | |
| 158 | try test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 159 | try test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 160 | ||
| 161 | try test__fixsfdi(-2.01, -2); | |
| 162 | try test__fixsfdi(-2.0, -2); | |
| 163 | try test__fixsfdi(-1.99, -1); | |
| 164 | try test__fixsfdi(-1.0, -1); | |
| 165 | try test__fixsfdi(-0.99, 0); | |
| 166 | try test__fixsfdi(-0.5, 0); | |
| 167 | try test__fixsfdi(-math.floatMin(f32), 0); | |
| 168 | try test__fixsfdi(0.0, 0); | |
| 169 | try test__fixsfdi(math.floatMin(f32), 0); | |
| 170 | try test__fixsfdi(0.5, 0); | |
| 171 | try test__fixsfdi(0.99, 0); | |
| 172 | try test__fixsfdi(1.0, 1); | |
| 173 | try test__fixsfdi(1.5, 1); | |
| 174 | try test__fixsfdi(1.99, 1); | |
| 175 | try test__fixsfdi(2.0, 2); | |
| 176 | try test__fixsfdi(2.01, 2); | |
| 177 | ||
| 178 | try test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 179 | try test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 180 | try test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | |
| 181 | ||
| 182 | try test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF); | |
| 183 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | |
| 184 | try test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 185 | try test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 186 | ||
| 187 | try test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 188 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 189 | try test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 190 | ||
| 191 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 192 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 193 | ||
| 194 | try test__fixsfdi(math.floatMax(f32), math.maxInt(i64)); | |
| 195 | } | |
| 196 | ||
| 197 | test "fixunssfdi" { | |
| 198 | try test__fixunssfdi(0.0, 0); | |
| 199 | ||
| 200 | try test__fixunssfdi(0.5, 0); | |
| 201 | try test__fixunssfdi(0.99, 0); | |
| 202 | try test__fixunssfdi(1.0, 1); | |
| 203 | try test__fixunssfdi(1.5, 1); | |
| 204 | try test__fixunssfdi(1.99, 1); | |
| 205 | try test__fixunssfdi(2.0, 2); | |
| 206 | try test__fixunssfdi(2.01, 2); | |
| 207 | try test__fixunssfdi(-0.5, 0); | |
| 208 | try test__fixunssfdi(-0.99, 0); | |
| 209 | ||
| 210 | try test__fixunssfdi(-1.0, 0); | |
| 211 | try test__fixunssfdi(-1.5, 0); | |
| 212 | try test__fixunssfdi(-1.99, 0); | |
| 213 | try test__fixunssfdi(-2.0, 0); | |
| 214 | try test__fixunssfdi(-2.01, 0); | |
| 215 | ||
| 216 | try test__fixunssfdi(0x1.FFFFFEp+63, 0xFFFFFF0000000000); | |
| 217 | try test__fixunssfdi(0x1.000000p+63, 0x8000000000000000); | |
| 218 | try test__fixunssfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 219 | try test__fixunssfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 220 | ||
| 221 | try test__fixunssfdi(-0x1.FFFFFEp+62, 0x0000000000000000); | |
| 222 | try test__fixunssfdi(-0x1.FFFFFCp+62, 0x0000000000000000); | |
| 223 | } | |
| 224 | ||
| 225 | fn test__fixsfti(a: f32, expected: i128) !void { | |
| 226 | const x = __fixsfti(a); | |
| 227 | try testing.expect(x == expected); | |
| 228 | } | |
| 229 | ||
| 230 | fn test__fixunssfti(a: f32, expected: u128) !void { | |
| 231 | const x = __fixunssfti(a); | |
| 232 | try testing.expect(x == expected); | |
| 233 | } | |
| 234 | ||
| 235 | test "fixsfti" { | |
| 236 | try test__fixsfti(-math.floatMax(f32), math.minInt(i128)); | |
| 237 | ||
| 238 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 239 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 240 | ||
| 241 | try test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 242 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000); | |
| 243 | try test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000); | |
| 244 | try test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000); | |
| 245 | try test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000); | |
| 246 | try test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000); | |
| 247 | ||
| 248 | try test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 249 | try test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 250 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | |
| 251 | try test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | |
| 252 | ||
| 253 | try test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000); | |
| 254 | try test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 255 | try test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 256 | ||
| 257 | try test__fixsfti(-0x1.000000p+31, -0x80000000); | |
| 258 | try test__fixsfti(-0x1.FFFFFFp+30, -0x80000000); | |
| 259 | try test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 260 | try test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 261 | ||
| 262 | try test__fixsfti(-2.01, -2); | |
| 263 | try test__fixsfti(-2.0, -2); | |
| 264 | try test__fixsfti(-1.99, -1); | |
| 265 | try test__fixsfti(-1.0, -1); | |
| 266 | try test__fixsfti(-0.99, 0); | |
| 267 | try test__fixsfti(-0.5, 0); | |
| 268 | try test__fixsfti(-math.floatMin(f32), 0); | |
| 269 | try test__fixsfti(0.0, 0); | |
| 270 | try test__fixsfti(math.floatMin(f32), 0); | |
| 271 | try test__fixsfti(0.5, 0); | |
| 272 | try test__fixsfti(0.99, 0); | |
| 273 | try test__fixsfti(1.0, 1); | |
| 274 | try test__fixsfti(1.5, 1); | |
| 275 | try test__fixsfti(1.99, 1); | |
| 276 | try test__fixsfti(2.0, 2); | |
| 277 | try test__fixsfti(2.01, 2); | |
| 278 | ||
| 279 | try test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 280 | try test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 281 | try test__fixsfti(0x1.FFFFFFp+30, 0x80000000); | |
| 282 | try test__fixsfti(0x1.000000p+31, 0x80000000); | |
| 283 | ||
| 284 | try test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 285 | try test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 286 | try test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000); | |
| 287 | ||
| 288 | try test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000); | |
| 289 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000); | |
| 290 | try test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 291 | try test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000); | |
| 292 | ||
| 293 | try test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000); | |
| 294 | try test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000); | |
| 295 | try test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 296 | try test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 297 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 298 | try test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 299 | ||
| 300 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 301 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 302 | ||
| 303 | try test__fixsfti(math.floatMax(f32), math.maxInt(i128)); | |
| 304 | } | |
| 305 | ||
| 306 | test "fixunssfti" { | |
| 307 | try test__fixunssfti(0.0, 0); | |
| 308 | ||
| 309 | try test__fixunssfti(0.5, 0); | |
| 310 | try test__fixunssfti(0.99, 0); | |
| 311 | try test__fixunssfti(1.0, 1); | |
| 312 | try test__fixunssfti(1.5, 1); | |
| 313 | try test__fixunssfti(1.99, 1); | |
| 314 | try test__fixunssfti(2.0, 2); | |
| 315 | try test__fixunssfti(2.01, 2); | |
| 316 | try test__fixunssfti(-0.5, 0); | |
| 317 | try test__fixunssfti(-0.99, 0); | |
| 318 | ||
| 319 | try test__fixunssfti(-1.0, 0); | |
| 320 | try test__fixunssfti(-1.5, 0); | |
| 321 | try test__fixunssfti(-1.99, 0); | |
| 322 | try test__fixunssfti(-2.0, 0); | |
| 323 | try test__fixunssfti(-2.01, 0); | |
| 324 | ||
| 325 | try test__fixunssfti(0x1.FFFFFEp+63, 0xFFFFFF0000000000); | |
| 326 | try test__fixunssfti(0x1.000000p+63, 0x8000000000000000); | |
| 327 | try test__fixunssfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 328 | try test__fixunssfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 329 | try test__fixunssfti(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000); | |
| 330 | try test__fixunssfti(0x1.000000p+127, 0x80000000000000000000000000000000); | |
| 331 | try test__fixunssfti(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000); | |
| 332 | try test__fixunssfti(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000); | |
| 333 | ||
| 334 | try test__fixunssfti(-0x1.FFFFFEp+62, 0x0000000000000000); | |
| 335 | try test__fixunssfti(-0x1.FFFFFCp+62, 0x0000000000000000); | |
| 336 | try test__fixunssfti(-0x1.FFFFFEp+126, 0x0000000000000000); | |
| 337 | try test__fixunssfti(-0x1.FFFFFCp+126, 0x0000000000000000); | |
| 338 | try test__fixunssfti(math.floatMax(f32), 0xffffff00000000000000000000000000); | |
| 339 | try test__fixunssfti(math.inf(f32), math.maxInt(u128)); | |
| 340 | } | |
| 341 | ||
| 342 | fn test__fixdfsi(a: f64, expected: i32) !void { | |
| 343 | const x = __fixdfsi(a); | |
| 344 | try testing.expect(x == expected); | |
| 345 | } | |
| 346 | ||
| 347 | fn test__fixunsdfsi(a: f64, expected: u32) !void { | |
| 348 | const x = __fixunsdfsi(a); | |
| 349 | try testing.expect(x == expected); | |
| 350 | } | |
| 351 | ||
| 352 | test "fixdfsi" { | |
| 353 | try test__fixdfsi(-math.floatMax(f64), math.minInt(i32)); | |
| 354 | ||
| 355 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 356 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 357 | ||
| 358 | try test__fixdfsi(-0x1.0000000000000p+127, -0x80000000); | |
| 359 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 360 | try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 361 | ||
| 362 | try test__fixdfsi(-0x1.0000000000001p+63, -0x80000000); | |
| 363 | try test__fixdfsi(-0x1.0000000000000p+63, -0x80000000); | |
| 364 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 365 | try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 366 | ||
| 367 | try test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000); | |
| 368 | try test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000); | |
| 369 | ||
| 370 | try test__fixdfsi(-0x1.000000p+31, -0x80000000); | |
| 371 | try test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 372 | try test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 373 | ||
| 374 | try test__fixdfsi(-2.01, -2); | |
| 375 | try test__fixdfsi(-2.0, -2); | |
| 376 | try test__fixdfsi(-1.99, -1); | |
| 377 | try test__fixdfsi(-1.0, -1); | |
| 378 | try test__fixdfsi(-0.99, 0); | |
| 379 | try test__fixdfsi(-0.5, 0); | |
| 380 | try test__fixdfsi(-math.floatMin(f64), 0); | |
| 381 | try test__fixdfsi(0.0, 0); | |
| 382 | try test__fixdfsi(math.floatMin(f64), 0); | |
| 383 | try test__fixdfsi(0.5, 0); | |
| 384 | try test__fixdfsi(0.99, 0); | |
| 385 | try test__fixdfsi(1.0, 1); | |
| 386 | try test__fixdfsi(1.5, 1); | |
| 387 | try test__fixdfsi(1.99, 1); | |
| 388 | try test__fixdfsi(2.0, 2); | |
| 389 | try test__fixdfsi(2.01, 2); | |
| 390 | ||
| 391 | try test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 392 | try test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 393 | try test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF); | |
| 394 | ||
| 395 | try test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 396 | try test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 397 | ||
| 398 | try test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 399 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 400 | try test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 401 | try test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 402 | ||
| 403 | try test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 404 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 405 | try test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 406 | ||
| 407 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 408 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 409 | ||
| 410 | try test__fixdfsi(math.floatMax(f64), math.maxInt(i32)); | |
| 411 | } | |
| 412 | ||
| 413 | test "fixunsdfsi" { | |
| 414 | try test__fixunsdfsi(0.0, 0); | |
| 415 | ||
| 416 | try test__fixunsdfsi(0.5, 0); | |
| 417 | try test__fixunsdfsi(0.99, 0); | |
| 418 | try test__fixunsdfsi(1.0, 1); | |
| 419 | try test__fixunsdfsi(1.5, 1); | |
| 420 | try test__fixunsdfsi(1.99, 1); | |
| 421 | try test__fixunsdfsi(2.0, 2); | |
| 422 | try test__fixunsdfsi(2.01, 2); | |
| 423 | try test__fixunsdfsi(-0.5, 0); | |
| 424 | try test__fixunsdfsi(-0.99, 0); | |
| 425 | try test__fixunsdfsi(-1.0, 0); | |
| 426 | try test__fixunsdfsi(-1.5, 0); | |
| 427 | try test__fixunsdfsi(-1.99, 0); | |
| 428 | try test__fixunsdfsi(-2.0, 0); | |
| 429 | try test__fixunsdfsi(-2.01, 0); | |
| 430 | ||
| 431 | try test__fixunsdfsi(0x1.000000p+31, 0x80000000); | |
| 432 | try test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF); | |
| 433 | try test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00); | |
| 434 | try test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 435 | try test__fixunsdfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 436 | ||
| 437 | try test__fixunsdfsi(-0x1.FFFFFEp+30, 0); | |
| 438 | try test__fixunsdfsi(-0x1.FFFFFCp+30, 0); | |
| 439 | ||
| 440 | try test__fixunsdfsi(0x1.FFFFFFFEp+31, 0xFFFFFFFF); | |
| 441 | try test__fixunsdfsi(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF); | |
| 442 | try test__fixunsdfsi(0x1.FFFFFFF800000p+30, 0x7FFFFFFE); | |
| 443 | } | |
| 444 | ||
| 445 | fn test__fixdfdi(a: f64, expected: i64) !void { | |
| 446 | const x = __fixdfdi(a); | |
| 447 | try testing.expect(x == expected); | |
| 448 | } | |
| 449 | ||
| 450 | fn test__fixunsdfdi(a: f64, expected: u64) !void { | |
| 451 | const x = __fixunsdfdi(a); | |
| 452 | try testing.expect(x == expected); | |
| 453 | } | |
| 454 | ||
| 455 | test "fixdfdi" { | |
| 456 | try test__fixdfdi(-math.floatMax(f64), math.minInt(i64)); | |
| 457 | ||
| 458 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 459 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 460 | ||
| 461 | try test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 462 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 463 | try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 464 | ||
| 465 | try test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 466 | try test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 467 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 468 | try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 469 | ||
| 470 | try test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 471 | try test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 472 | ||
| 473 | try test__fixdfdi(-2.01, -2); | |
| 474 | try test__fixdfdi(-2.0, -2); | |
| 475 | try test__fixdfdi(-1.99, -1); | |
| 476 | try test__fixdfdi(-1.0, -1); | |
| 477 | try test__fixdfdi(-0.99, 0); | |
| 478 | try test__fixdfdi(-0.5, 0); | |
| 479 | try test__fixdfdi(-math.floatMin(f64), 0); | |
| 480 | try test__fixdfdi(0.0, 0); | |
| 481 | try test__fixdfdi(math.floatMin(f64), 0); | |
| 482 | try test__fixdfdi(0.5, 0); | |
| 483 | try test__fixdfdi(0.99, 0); | |
| 484 | try test__fixdfdi(1.0, 1); | |
| 485 | try test__fixdfdi(1.5, 1); | |
| 486 | try test__fixdfdi(1.99, 1); | |
| 487 | try test__fixdfdi(2.0, 2); | |
| 488 | try test__fixdfdi(2.01, 2); | |
| 489 | ||
| 490 | try test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 491 | try test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 492 | ||
| 493 | try test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 494 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 495 | try test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 496 | try test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 497 | ||
| 498 | try test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 499 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 500 | try test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 501 | ||
| 502 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 503 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 504 | ||
| 505 | try test__fixdfdi(math.floatMax(f64), math.maxInt(i64)); | |
| 506 | } | |
| 507 | ||
| 508 | test "fixunsdfdi" { | |
| 509 | try test__fixunsdfdi(0.0, 0); | |
| 510 | try test__fixunsdfdi(0.5, 0); | |
| 511 | try test__fixunsdfdi(0.99, 0); | |
| 512 | try test__fixunsdfdi(1.0, 1); | |
| 513 | try test__fixunsdfdi(1.5, 1); | |
| 514 | try test__fixunsdfdi(1.99, 1); | |
| 515 | try test__fixunsdfdi(2.0, 2); | |
| 516 | try test__fixunsdfdi(2.01, 2); | |
| 517 | try test__fixunsdfdi(-0.5, 0); | |
| 518 | try test__fixunsdfdi(-0.99, 0); | |
| 519 | try test__fixunsdfdi(-1.0, 0); | |
| 520 | try test__fixunsdfdi(-1.5, 0); | |
| 521 | try test__fixunsdfdi(-1.99, 0); | |
| 522 | try test__fixunsdfdi(-2.0, 0); | |
| 523 | try test__fixunsdfdi(-2.01, 0); | |
| 524 | ||
| 525 | try test__fixunsdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 526 | try test__fixunsdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 527 | ||
| 528 | try test__fixunsdfdi(-0x1.FFFFFEp+62, 0); | |
| 529 | try test__fixunsdfdi(-0x1.FFFFFCp+62, 0); | |
| 530 | ||
| 531 | try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); | |
| 532 | try test__fixunsdfdi(0x1.0000000000000p+63, 0x8000000000000000); | |
| 533 | try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 534 | try test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 535 | ||
| 536 | try test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 537 | try test__fixunsdfdi(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 538 | } | |
| 539 | ||
| 540 | fn test__fixdfti(a: f64, expected: i128) !void { | |
| 541 | const x = __fixdfti(a); | |
| 542 | try testing.expect(x == expected); | |
| 543 | } | |
| 544 | ||
| 545 | fn test__fixunsdfti(a: f64, expected: u128) !void { | |
| 546 | const x = __fixunsdfti(a); | |
| 547 | try testing.expect(x == expected); | |
| 548 | } | |
| 549 | ||
| 550 | test "fixdfti" { | |
| 551 | try test__fixdfti(-math.floatMax(f64), math.minInt(i128)); | |
| 552 | ||
| 553 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 554 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 555 | ||
| 556 | try test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 557 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | |
| 558 | try test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | |
| 559 | ||
| 560 | try test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800); | |
| 561 | try test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 562 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 563 | try test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 564 | ||
| 565 | try test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 566 | try test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 567 | ||
| 568 | try test__fixdfti(-2.01, -2); | |
| 569 | try test__fixdfti(-2.0, -2); | |
| 570 | try test__fixdfti(-1.99, -1); | |
| 571 | try test__fixdfti(-1.0, -1); | |
| 572 | try test__fixdfti(-0.99, 0); | |
| 573 | try test__fixdfti(-0.5, 0); | |
| 574 | try test__fixdfti(-math.floatMin(f64), 0); | |
| 575 | try test__fixdfti(0.0, 0); | |
| 576 | try test__fixdfti(math.floatMin(f64), 0); | |
| 577 | try test__fixdfti(0.5, 0); | |
| 578 | try test__fixdfti(0.99, 0); | |
| 579 | try test__fixdfti(1.0, 1); | |
| 580 | try test__fixdfti(1.5, 1); | |
| 581 | try test__fixdfti(1.99, 1); | |
| 582 | try test__fixdfti(2.0, 2); | |
| 583 | try test__fixdfti(2.01, 2); | |
| 584 | ||
| 585 | try test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 586 | try test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 587 | ||
| 588 | try test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 589 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 590 | try test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 591 | try test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800); | |
| 592 | ||
| 593 | try test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 594 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 595 | try test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 596 | ||
| 597 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 598 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 599 | ||
| 600 | try test__fixdfti(math.floatMax(f64), math.maxInt(i128)); | |
| 601 | } | |
| 602 | ||
| 603 | test "fixunsdfti" { | |
| 604 | try test__fixunsdfti(0.0, 0); | |
| 605 | ||
| 606 | try test__fixunsdfti(0.5, 0); | |
| 607 | try test__fixunsdfti(0.99, 0); | |
| 608 | try test__fixunsdfti(1.0, 1); | |
| 609 | try test__fixunsdfti(1.5, 1); | |
| 610 | try test__fixunsdfti(1.99, 1); | |
| 611 | try test__fixunsdfti(2.0, 2); | |
| 612 | try test__fixunsdfti(2.01, 2); | |
| 613 | try test__fixunsdfti(-0.5, 0); | |
| 614 | try test__fixunsdfti(-0.99, 0); | |
| 615 | try test__fixunsdfti(-1.0, 0); | |
| 616 | try test__fixunsdfti(-1.5, 0); | |
| 617 | try test__fixunsdfti(-1.99, 0); | |
| 618 | try test__fixunsdfti(-2.0, 0); | |
| 619 | try test__fixunsdfti(-2.01, 0); | |
| 620 | ||
| 621 | try test__fixunsdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 622 | try test__fixunsdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 623 | ||
| 624 | try test__fixunsdfti(-0x1.FFFFFEp+62, 0); | |
| 625 | try test__fixunsdfti(-0x1.FFFFFCp+62, 0); | |
| 626 | ||
| 627 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); | |
| 628 | try test__fixunsdfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 629 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 630 | try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 631 | ||
| 632 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000); | |
| 633 | try test__fixunsdfti(0x1.0000000000000p+127, 0x80000000000000000000000000000000); | |
| 634 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 635 | try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 636 | try test__fixunsdfti(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 637 | ||
| 638 | try test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 639 | try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 640 | } | |
| 641 | ||
| 642 | fn test__fixtfsi(a: f128, expected: i32) !void { | |
| 643 | const x = __fixtfsi(a); | |
| 644 | try testing.expect(x == expected); | |
| 645 | } | |
| 646 | ||
| 647 | fn test__fixunstfsi(a: f128, expected: u32) !void { | |
| 648 | const x = __fixunstfsi(a); | |
| 649 | try testing.expect(x == expected); | |
| 650 | } | |
| 651 | ||
| 652 | test "fixtfsi" { | |
| 653 | try test__fixtfsi(-math.floatMax(f128), math.minInt(i32)); | |
| 654 | ||
| 655 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 656 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 657 | ||
| 658 | try test__fixtfsi(-0x1.0000000000000p+127, -0x80000000); | |
| 659 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 660 | try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 661 | ||
| 662 | try test__fixtfsi(-0x1.0000000000001p+63, -0x80000000); | |
| 663 | try test__fixtfsi(-0x1.0000000000000p+63, -0x80000000); | |
| 664 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 665 | try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 666 | ||
| 667 | try test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000); | |
| 668 | try test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000); | |
| 669 | ||
| 670 | try test__fixtfsi(-0x1.000000p+31, -0x80000000); | |
| 671 | try test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 672 | try test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 673 | try test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 674 | ||
| 675 | try test__fixtfsi(-2.01, -2); | |
| 676 | try test__fixtfsi(-2.0, -2); | |
| 677 | try test__fixtfsi(-1.99, -1); | |
| 678 | try test__fixtfsi(-1.0, -1); | |
| 679 | try test__fixtfsi(-0.99, 0); | |
| 680 | try test__fixtfsi(-0.5, 0); | |
| 681 | try test__fixtfsi(-math.floatMin(f32), 0); | |
| 682 | try test__fixtfsi(0.0, 0); | |
| 683 | try test__fixtfsi(math.floatMin(f32), 0); | |
| 684 | try test__fixtfsi(0.5, 0); | |
| 685 | try test__fixtfsi(0.99, 0); | |
| 686 | try test__fixtfsi(1.0, 1); | |
| 687 | try test__fixtfsi(1.5, 1); | |
| 688 | try test__fixtfsi(1.99, 1); | |
| 689 | try test__fixtfsi(2.0, 2); | |
| 690 | try test__fixtfsi(2.01, 2); | |
| 691 | ||
| 692 | try test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 693 | try test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 694 | try test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 695 | try test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF); | |
| 696 | ||
| 697 | try test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 698 | try test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 699 | ||
| 700 | try test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 701 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 702 | try test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 703 | try test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 704 | ||
| 705 | try test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 706 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 707 | try test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 708 | ||
| 709 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 710 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 711 | ||
| 712 | try test__fixtfsi(math.floatMax(f128), math.maxInt(i32)); | |
| 713 | } | |
| 714 | ||
| 715 | test "fixunstfsi" { | |
| 716 | try test__fixunstfsi(math.inf(f128), 0xffffffff); | |
| 717 | try test__fixunstfsi(0, 0x0); | |
| 718 | try test__fixunstfsi(0x1.23456789abcdefp+5, 0x24); | |
| 719 | try test__fixunstfsi(0x1.23456789abcdefp-3, 0x0); | |
| 720 | try test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456); | |
| 721 | try test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff); | |
| 722 | try test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff); | |
| 723 | try test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0); | |
| 724 | ||
| 725 | try test__fixunstfsi(0x1p+32, 0xFFFFFFFF); | |
| 726 | } | |
| 727 | ||
| 728 | fn test__fixtfdi(a: f128, expected: i64) !void { | |
| 729 | const x = __fixtfdi(a); | |
| 730 | try testing.expect(x == expected); | |
| 731 | } | |
| 732 | ||
| 733 | fn test__fixunstfdi(a: f128, expected: u64) !void { | |
| 734 | const x = __fixunstfdi(a); | |
| 735 | try testing.expect(x == expected); | |
| 736 | } | |
| 737 | ||
| 738 | test "fixtfdi" { | |
| 739 | try test__fixtfdi(-math.floatMax(f128), math.minInt(i64)); | |
| 740 | ||
| 741 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 742 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 743 | ||
| 744 | try test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 745 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 746 | try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 747 | ||
| 748 | try test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 749 | try test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 750 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 751 | try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 752 | ||
| 753 | try test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000); | |
| 754 | try test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000); | |
| 755 | ||
| 756 | try test__fixtfdi(-0x1.000000p+31, -0x80000000); | |
| 757 | try test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 758 | try test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 759 | try test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 760 | ||
| 761 | try test__fixtfdi(-2.01, -2); | |
| 762 | try test__fixtfdi(-2.0, -2); | |
| 763 | try test__fixtfdi(-1.99, -1); | |
| 764 | try test__fixtfdi(-1.0, -1); | |
| 765 | try test__fixtfdi(-0.99, 0); | |
| 766 | try test__fixtfdi(-0.5, 0); | |
| 767 | try test__fixtfdi(-math.floatMin(f64), 0); | |
| 768 | try test__fixtfdi(0.0, 0); | |
| 769 | try test__fixtfdi(math.floatMin(f64), 0); | |
| 770 | try test__fixtfdi(0.5, 0); | |
| 771 | try test__fixtfdi(0.99, 0); | |
| 772 | try test__fixtfdi(1.0, 1); | |
| 773 | try test__fixtfdi(1.5, 1); | |
| 774 | try test__fixtfdi(1.99, 1); | |
| 775 | try test__fixtfdi(2.0, 2); | |
| 776 | try test__fixtfdi(2.01, 2); | |
| 777 | ||
| 778 | try test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 779 | try test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 780 | try test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 781 | try test__fixtfdi(0x1.000000p+31, 0x80000000); | |
| 782 | ||
| 783 | try test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 784 | try test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 785 | ||
| 786 | try test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 787 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 788 | try test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 789 | try test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 790 | ||
| 791 | try test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 792 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 793 | try test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 794 | ||
| 795 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 796 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 797 | ||
| 798 | try test__fixtfdi(math.floatMax(f128), math.maxInt(i64)); | |
| 799 | } | |
| 800 | ||
| 801 | test "fixunstfdi" { | |
| 802 | try test__fixunstfdi(0.0, 0); | |
| 803 | ||
| 804 | try test__fixunstfdi(0.5, 0); | |
| 805 | try test__fixunstfdi(0.99, 0); | |
| 806 | try test__fixunstfdi(1.0, 1); | |
| 807 | try test__fixunstfdi(1.5, 1); | |
| 808 | try test__fixunstfdi(1.99, 1); | |
| 809 | try test__fixunstfdi(2.0, 2); | |
| 810 | try test__fixunstfdi(2.01, 2); | |
| 811 | try test__fixunstfdi(-0.5, 0); | |
| 812 | try test__fixunstfdi(-0.99, 0); | |
| 813 | try test__fixunstfdi(-1.0, 0); | |
| 814 | try test__fixunstfdi(-1.5, 0); | |
| 815 | try test__fixunstfdi(-1.99, 0); | |
| 816 | try test__fixunstfdi(-2.0, 0); | |
| 817 | try test__fixunstfdi(-2.01, 0); | |
| 818 | ||
| 819 | try test__fixunstfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 820 | try test__fixunstfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 821 | ||
| 822 | try test__fixunstfdi(-0x1.FFFFFEp+62, 0); | |
| 823 | try test__fixunstfdi(-0x1.FFFFFCp+62, 0); | |
| 824 | ||
| 825 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 826 | try test__fixunstfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 827 | ||
| 828 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 829 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 830 | ||
| 831 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); | |
| 832 | try test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001); | |
| 833 | try test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000); | |
| 834 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); | |
| 835 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); | |
| 836 | try test__fixunstfdi(0x1p+64, 0xFFFFFFFFFFFFFFFF); | |
| 837 | ||
| 838 | try test__fixunstfdi(-0x1.0000000000000000p+63, 0); | |
| 839 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0); | |
| 840 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0); | |
| 841 | } | |
| 842 | ||
| 843 | fn test__fixtfti(a: f128, expected: i128) !void { | |
| 844 | const x = __fixtfti(a); | |
| 845 | try testing.expect(x == expected); | |
| 846 | } | |
| 847 | ||
| 848 | fn test__fixunstfti(a: f128, expected: u128) !void { | |
| 849 | const x = __fixunstfti(a); | |
| 850 | try testing.expect(x == expected); | |
| 851 | } | |
| 852 | ||
| 853 | test "fixtfti" { | |
| 854 | try test__fixtfti(-math.floatMax(f128), math.minInt(i128)); | |
| 855 | ||
| 856 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 857 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 858 | ||
| 859 | try test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 860 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | |
| 861 | try test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | |
| 862 | ||
| 863 | try test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800); | |
| 864 | try test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 865 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 866 | try test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 867 | ||
| 868 | try test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 869 | try test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 870 | ||
| 871 | try test__fixtfti(-2.01, -2); | |
| 872 | try test__fixtfti(-2.0, -2); | |
| 873 | try test__fixtfti(-1.99, -1); | |
| 874 | try test__fixtfti(-1.0, -1); | |
| 875 | try test__fixtfti(-0.99, 0); | |
| 876 | try test__fixtfti(-0.5, 0); | |
| 877 | try test__fixtfti(-math.floatMin(f128), 0); | |
| 878 | try test__fixtfti(0.0, 0); | |
| 879 | try test__fixtfti(math.floatMin(f128), 0); | |
| 880 | try test__fixtfti(0.5, 0); | |
| 881 | try test__fixtfti(0.99, 0); | |
| 882 | try test__fixtfti(1.0, 1); | |
| 883 | try test__fixtfti(1.5, 1); | |
| 884 | try test__fixtfti(1.99, 1); | |
| 885 | try test__fixtfti(2.0, 2); | |
| 886 | try test__fixtfti(2.01, 2); | |
| 887 | ||
| 888 | try test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 889 | try test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 890 | ||
| 891 | try test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 892 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 893 | try test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 894 | try test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800); | |
| 895 | ||
| 896 | try test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 897 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 898 | try test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 899 | ||
| 900 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 901 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 902 | ||
| 903 | try test__fixtfti(math.floatMax(f128), math.maxInt(i128)); | |
| 904 | } | |
| 905 | ||
| 906 | test "fixunstfti" { | |
| 907 | try test__fixunstfti(math.inf(f128), 0xffffffffffffffffffffffffffffffff); | |
| 908 | ||
| 909 | try test__fixunstfti(0.0, 0); | |
| 910 | ||
| 911 | try test__fixunstfti(0.5, 0); | |
| 912 | try test__fixunstfti(0.99, 0); | |
| 913 | try test__fixunstfti(1.0, 1); | |
| 914 | try test__fixunstfti(1.5, 1); | |
| 915 | try test__fixunstfti(1.99, 1); | |
| 916 | try test__fixunstfti(2.0, 2); | |
| 917 | try test__fixunstfti(2.01, 2); | |
| 918 | try test__fixunstfti(-0.01, 0); | |
| 919 | try test__fixunstfti(-0.99, 0); | |
| 920 | ||
| 921 | try test__fixunstfti(0x1p+128, 0xffffffffffffffffffffffffffffffff); | |
| 922 | ||
| 923 | try test__fixunstfti(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000); | |
| 924 | try test__fixunstfti(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000); | |
| 925 | try test__fixunstfti(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff); | |
| 926 | try test__fixunstfti(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff); | |
| 927 | } | |
| 928 | ||
| 929 | fn test__fixunshfti(a: f16, expected: u128) !void { | |
| 930 | const x = fixXfYi(u128, a); | |
| 931 | try testing.expect(x == expected); | |
| 932 | } | |
| 933 | ||
| 934 | test "fixXfYi for f16" { | |
| 935 | try test__fixunshfti(math.inf(f16), math.maxInt(u128)); | |
| 936 | try test__fixunshfti(math.floatMax(f16), 65504); | |
| 937 | } | |
| 938 | ||
| 939 | fn test__fixunsxfti(a: f80, expected: u128) !void { | |
| 940 | const x = fixXfYi(u128, a); | |
| 941 | try testing.expect(x == expected); | |
| 942 | } | |
| 943 | ||
| 944 | test "fixXfYi for f80" { | |
| 945 | try test__fixunsxfti(math.inf(f80), math.maxInt(u128)); | |
| 946 | try test__fixunsxfti(math.floatMax(f80), math.maxInt(u128)); | |
| 947 | try test__fixunsxfti(math.maxInt(u64), math.maxInt(u64)); | |
| 948 | } |
lib/compiler_rt/fixdfdi.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_d2lz, .{ .name = "__aeabi_d2lz", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__fixdfdi, .{ .name = "__fixdfdi", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __fixdfdi(a: f64) callconv(.C) i64 { | |
| 15 | return floatToInt(i64, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_d2lz(a: f64) callconv(.AAPCS) i64 { | |
| 19 | return floatToInt(i64, a); | |
| 20 | } |
lib/compiler_rt/fixdfsi.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_d2iz, .{ .name = "__aeabi_d2iz", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__fixdfsi, .{ .name = "__fixdfsi", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __fixdfsi(a: f64) callconv(.C) i32 { | |
| 15 | return floatToInt(i32, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_d2iz(a: f64) callconv(.AAPCS) i32 { | |
| 19 | return floatToInt(i32, a); | |
| 20 | } |
lib/compiler_rt/fixdfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixdfti, .{ .name = "__fixdfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixdfti(a: f64) callconv(.C) i128 { | |
| 11 | return floatToInt(i128, a); | |
| 12 | } |
lib/compiler_rt/fixhfdi.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixhfdi, .{ .name = "__fixhfdi", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixhfdi(a: f16) callconv(.C) i64 { | |
| 11 | return floatToInt(i64, a); | |
| 12 | } |
lib/compiler_rt/fixhfsi.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixhfsi, .{ .name = "__fixhfsi", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixhfsi(a: f16) callconv(.C) i32 { | |
| 11 | return floatToInt(i32, a); | |
| 12 | } |
lib/compiler_rt/fixhfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixhfti, .{ .name = "__fixhfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixhfti(a: f16) callconv(.C) i128 { | |
| 11 | return floatToInt(i128, a); | |
| 12 | } |
lib/compiler_rt/fixsfdi.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_f2lz, .{ .name = "__aeabi_f2lz", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__fixsfdi, .{ .name = "__fixsfdi", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __fixsfdi(a: f32) callconv(.C) i64 { | |
| 15 | return floatToInt(i64, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_f2lz(a: f32) callconv(.AAPCS) i64 { | |
| 19 | return floatToInt(i64, a); | |
| 20 | } |
lib/compiler_rt/fixsfsi.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_f2iz, .{ .name = "__aeabi_f2iz", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__fixsfsi, .{ .name = "__fixsfsi", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __fixsfsi(a: f32) callconv(.C) i32 { | |
| 15 | return floatToInt(i32, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_f2iz(a: f32) callconv(.AAPCS) i32 { | |
| 19 | return floatToInt(i32, a); | |
| 20 | } |
lib/compiler_rt/fixsfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixsfti, .{ .name = "__fixsfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixsfti(a: f32) callconv(.C) i128 { | |
| 11 | return floatToInt(i128, a); | |
| 12 | } |
lib/compiler_rt/fixtfdi.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__fixkfdi, .{ .name = "__fixkfdi", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_qtox, .{ .name = "_Qp_qtox", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __fixtfdi(a: f128) callconv(.C) i64 { | |
| 17 | return floatToInt(i64, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __fixkfdi(a: f128) callconv(.C) i64 { | |
| 21 | return floatToInt(i64, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_qtox(a: *const f128) callconv(.C) i64 { | |
| 25 | return floatToInt(i64, a.*); | |
| 26 | } |
lib/compiler_rt/fixtfsi.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__fixkfsi, .{ .name = "__fixkfsi", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_qtoi, .{ .name = "_Qp_qtoi", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __fixtfsi(a: f128) callconv(.C) i32 { | |
| 17 | return floatToInt(i32, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __fixkfsi(a: f128) callconv(.C) i32 { | |
| 21 | return floatToInt(i32, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_qtoi(a: *const f128) callconv(.C) i32 { | |
| 25 | return floatToInt(i32, a.*); | |
| 26 | } |
lib/compiler_rt/fixtfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixtfti, .{ .name = "__fixtfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixtfti(a: f128) callconv(.C) i128 { | |
| 11 | return floatToInt(i128, a); | |
| 12 | } |
lib/compiler_rt/fixunsdfdi.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_d2ulz, .{ .name = "__aeabi_d2ulz", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __fixunsdfdi(a: f64) callconv(.C) u64 { | |
| 15 | return floatToInt(u64, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_d2ulz(a: f64) callconv(.AAPCS) u64 { | |
| 19 | return floatToInt(u64, a); | |
| 20 | } |
lib/compiler_rt/fixunsdfsi.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_d2uiz, .{ .name = "__aeabi_d2uiz", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__fixunsdfsi, .{ .name = "__fixunsdfsi", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __fixunsdfsi(a: f64) callconv(.C) u32 { | |
| 15 | return floatToInt(u32, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_d2uiz(a: f64) callconv(.AAPCS) u32 { | |
| 19 | return floatToInt(u32, a); | |
| 20 | } |
lib/compiler_rt/fixunsdfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixunsdfti(a: f64) callconv(.C) u128 { | |
| 11 | return floatToInt(u128, a); | |
| 12 | } |
lib/compiler_rt/fixunshfdi.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixunshfdi, .{ .name = "__fixunshfdi", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixunshfdi(a: f16) callconv(.C) u64 { | |
| 11 | return floatToInt(u64, a); | |
| 12 | } |
lib/compiler_rt/fixunshfsi.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixunshfsi, .{ .name = "__fixunshfsi", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixunshfsi(a: f16) callconv(.C) u32 { | |
| 11 | return floatToInt(u32, a); | |
| 12 | } |
lib/compiler_rt/fixunshfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixunshfti, .{ .name = "__fixunshfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixunshfti(a: f16) callconv(.C) u128 { | |
| 11 | return floatToInt(u128, a); | |
| 12 | } |
lib/compiler_rt/fixunssfdi.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_f2ulz, .{ .name = "__aeabi_f2ulz", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __fixunssfdi(a: f32) callconv(.C) u64 { | |
| 15 | return floatToInt(u64, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_f2ulz(a: f32) callconv(.AAPCS) u64 { | |
| 19 | return floatToInt(u64, a); | |
| 20 | } |
lib/compiler_rt/fixunssfsi.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_f2uiz, .{ .name = "__aeabi_f2uiz", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__fixunssfsi, .{ .name = "__fixunssfsi", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __fixunssfsi(a: f32) callconv(.C) u32 { | |
| 15 | return floatToInt(u32, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_f2uiz(a: f32) callconv(.AAPCS) u32 { | |
| 19 | return floatToInt(u32, a); | |
| 20 | } |
lib/compiler_rt/fixunssfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixunssfti(a: f32) callconv(.C) u128 { | |
| 11 | return floatToInt(u128, a); | |
| 12 | } |
lib/compiler_rt/fixunstfdi.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__fixunskfdi, .{ .name = "__fixunskfdi", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_qtoux, .{ .name = "_Qp_qtoux", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __fixunstfdi(a: f128) callconv(.C) u64 { | |
| 17 | return floatToInt(u64, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __fixunskfdi(a: f128) callconv(.C) u64 { | |
| 21 | return floatToInt(u64, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_qtoux(a: *const f128) callconv(.C) u64 { | |
| 25 | return floatToInt(u64, a.*); | |
| 26 | } |
lib/compiler_rt/fixunstfsi.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__fixunskfsi, .{ .name = "__fixunskfsi", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_qtoui, .{ .name = "_Qp_qtoui", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __fixunstfsi(a: f128) callconv(.C) u32 { | |
| 17 | return floatToInt(u32, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __fixunskfsi(a: f128) callconv(.C) u32 { | |
| 21 | return floatToInt(u32, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_qtoui(a: *const f128) callconv(.C) u32 { | |
| 25 | return floatToInt(u32, a.*); | |
| 26 | } |
lib/compiler_rt/fixunstfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixunstfti(a: f128) callconv(.C) u128 { | |
| 11 | return floatToInt(u128, a); | |
| 12 | } |
lib/compiler_rt/fixunsxfdi.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixunsxfdi, .{ .name = "__fixunsxfdi", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixunsxfdi(a: f80) callconv(.C) u64 { | |
| 11 | return floatToInt(u64, a); | |
| 12 | } |
lib/compiler_rt/fixunsxfsi.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixunsxfsi, .{ .name = "__fixunsxfsi", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixunsxfsi(a: f80) callconv(.C) u32 { | |
| 11 | return floatToInt(u32, a); | |
| 12 | } |
lib/compiler_rt/fixunsxfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixunsxfti, .{ .name = "__fixunsxfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixunsxfti(a: f80) callconv(.C) u128 { | |
| 11 | return floatToInt(u128, a); | |
| 12 | } |
lib/compiler_rt/fixxfdi.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixxfdi, .{ .name = "__fixxfdi", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixxfdi(a: f80) callconv(.C) i64 { | |
| 11 | return floatToInt(i64, a); | |
| 12 | } |
lib/compiler_rt/fixxfsi.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixxfsi, .{ .name = "__fixxfsi", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixxfsi(a: f80) callconv(.C) i32 { | |
| 11 | return floatToInt(i32, a); | |
| 12 | } |
lib/compiler_rt/fixxfti.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const floatToInt = @import("./float_to_int.zig").floatToInt; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__fixxfti, .{ .name = "__fixxfti", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __fixxfti(a: f80) callconv(.C) i128 { | |
| 11 | return floatToInt(i128, a); | |
| 12 | } |
lib/compiler_rt/floatXiYf.zig deleted-222| ... | ... | @@ -1,222 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const is_test = builtin.is_test; | |
| 3 | const std = @import("std"); | |
| 4 | const math = std.math; | |
| 5 | const expect = std.testing.expect; | |
| 6 | ||
| 7 | pub fn floatXiYf(comptime T: type, x: anytype) T { | |
| 8 | @setRuntimeSafety(is_test); | |
| 9 | ||
| 10 | if (x == 0) return 0; | |
| 11 | ||
| 12 | // Various constants whose values follow from the type parameters. | |
| 13 | // Any reasonable optimizer will fold and propagate all of these. | |
| 14 | const Z = std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(x))); | |
| 15 | const uT = std.meta.Int(.unsigned, @bitSizeOf(T)); | |
| 16 | const inf = math.inf(T); | |
| 17 | const float_bits = @bitSizeOf(T); | |
| 18 | const int_bits = @bitSizeOf(@TypeOf(x)); | |
| 19 | const exp_bits = math.floatExponentBits(T); | |
| 20 | const fractional_bits = math.floatFractionalBits(T); | |
| 21 | const exp_bias = math.maxInt(std.meta.Int(.unsigned, exp_bits - 1)); | |
| 22 | const implicit_bit = if (T != f80) @as(uT, 1) << fractional_bits else 0; | |
| 23 | const max_exp = exp_bias; | |
| 24 | ||
| 25 | // Sign | |
| 26 | var abs_val = math.absCast(x); | |
| 27 | const sign_bit = if (x < 0) @as(uT, 1) << (float_bits - 1) else 0; | |
| 28 | var result: uT = sign_bit; | |
| 29 | ||
| 30 | // Compute significand | |
| 31 | var exp = int_bits - @clz(Z, abs_val) - 1; | |
| 32 | if (int_bits <= fractional_bits or exp <= fractional_bits) { | |
| 33 | const shift_amt = fractional_bits - @intCast(math.Log2Int(uT), exp); | |
| 34 | ||
| 35 | // Shift up result to line up with the significand - no rounding required | |
| 36 | result = (@intCast(uT, abs_val) << shift_amt); | |
| 37 | result ^= implicit_bit; // Remove implicit integer bit | |
| 38 | } else { | |
| 39 | var shift_amt = @intCast(math.Log2Int(Z), exp - fractional_bits); | |
| 40 | const exact_tie: bool = @ctz(Z, abs_val) == shift_amt - 1; | |
| 41 | ||
| 42 | // Shift down result and remove implicit integer bit | |
| 43 | result = @intCast(uT, (abs_val >> (shift_amt - 1))) ^ (implicit_bit << 1); | |
| 44 | ||
| 45 | // Round result, including round-to-even for exact ties | |
| 46 | result = ((result + 1) >> 1) & ~@as(uT, @boolToInt(exact_tie)); | |
| 47 | } | |
| 48 | ||
| 49 | // Compute exponent | |
| 50 | if ((int_bits > max_exp) and (exp > max_exp)) // If exponent too large, overflow to infinity | |
| 51 | return @bitCast(T, sign_bit | @bitCast(uT, inf)); | |
| 52 | ||
| 53 | result += (@as(uT, exp) + exp_bias) << math.floatMantissaBits(T); | |
| 54 | ||
| 55 | // If the result included a carry, we need to restore the explicit integer bit | |
| 56 | if (T == f80) result |= 1 << fractional_bits; | |
| 57 | ||
| 58 | return @bitCast(T, sign_bit | result); | |
| 59 | } | |
| 60 | ||
| 61 | // Conversion to f16 | |
| 62 | pub fn __floatsihf(a: i32) callconv(.C) f16 { | |
| 63 | return floatXiYf(f16, a); | |
| 64 | } | |
| 65 | ||
| 66 | pub fn __floatunsihf(a: u32) callconv(.C) f16 { | |
| 67 | return floatXiYf(f16, a); | |
| 68 | } | |
| 69 | ||
| 70 | pub fn __floatdihf(a: i64) callconv(.C) f16 { | |
| 71 | return floatXiYf(f16, a); | |
| 72 | } | |
| 73 | ||
| 74 | pub fn __floatundihf(a: u64) callconv(.C) f16 { | |
| 75 | return floatXiYf(f16, a); | |
| 76 | } | |
| 77 | ||
| 78 | pub fn __floattihf(a: i128) callconv(.C) f16 { | |
| 79 | return floatXiYf(f16, a); | |
| 80 | } | |
| 81 | ||
| 82 | pub fn __floatuntihf(a: u128) callconv(.C) f16 { | |
| 83 | return floatXiYf(f16, a); | |
| 84 | } | |
| 85 | ||
| 86 | // Conversion to f32 | |
| 87 | pub fn __floatsisf(a: i32) callconv(.C) f32 { | |
| 88 | return floatXiYf(f32, a); | |
| 89 | } | |
| 90 | ||
| 91 | pub fn __floatunsisf(a: u32) callconv(.C) f32 { | |
| 92 | return floatXiYf(f32, a); | |
| 93 | } | |
| 94 | ||
| 95 | pub fn __floatdisf(a: i64) callconv(.C) f32 { | |
| 96 | return floatXiYf(f32, a); | |
| 97 | } | |
| 98 | ||
| 99 | pub fn __floatundisf(a: u64) callconv(.C) f32 { | |
| 100 | return floatXiYf(f32, a); | |
| 101 | } | |
| 102 | ||
| 103 | pub fn __floattisf(a: i128) callconv(.C) f32 { | |
| 104 | return floatXiYf(f32, a); | |
| 105 | } | |
| 106 | ||
| 107 | pub fn __floatuntisf(a: u128) callconv(.C) f32 { | |
| 108 | return floatXiYf(f32, a); | |
| 109 | } | |
| 110 | ||
| 111 | // Conversion to f64 | |
| 112 | pub fn __floatsidf(a: i32) callconv(.C) f64 { | |
| 113 | return floatXiYf(f64, a); | |
| 114 | } | |
| 115 | ||
| 116 | pub fn __floatunsidf(a: u32) callconv(.C) f64 { | |
| 117 | return floatXiYf(f64, a); | |
| 118 | } | |
| 119 | ||
| 120 | pub fn __floatdidf(a: i64) callconv(.C) f64 { | |
| 121 | return floatXiYf(f64, a); | |
| 122 | } | |
| 123 | ||
| 124 | pub fn __floatundidf(a: u64) callconv(.C) f64 { | |
| 125 | return floatXiYf(f64, a); | |
| 126 | } | |
| 127 | ||
| 128 | pub fn __floattidf(a: i128) callconv(.C) f64 { | |
| 129 | return floatXiYf(f64, a); | |
| 130 | } | |
| 131 | ||
| 132 | pub fn __floatuntidf(a: u128) callconv(.C) f64 { | |
| 133 | return floatXiYf(f64, a); | |
| 134 | } | |
| 135 | ||
| 136 | // Conversion to f80 | |
| 137 | pub fn __floatsixf(a: i32) callconv(.C) f80 { | |
| 138 | return floatXiYf(f80, a); | |
| 139 | } | |
| 140 | ||
| 141 | pub fn __floatunsixf(a: u32) callconv(.C) f80 { | |
| 142 | return floatXiYf(f80, a); | |
| 143 | } | |
| 144 | ||
| 145 | pub fn __floatdixf(a: i64) callconv(.C) f80 { | |
| 146 | return floatXiYf(f80, a); | |
| 147 | } | |
| 148 | ||
| 149 | pub fn __floatundixf(a: u64) callconv(.C) f80 { | |
| 150 | return floatXiYf(f80, a); | |
| 151 | } | |
| 152 | ||
| 153 | pub fn __floattixf(a: i128) callconv(.C) f80 { | |
| 154 | return floatXiYf(f80, a); | |
| 155 | } | |
| 156 | ||
| 157 | pub fn __floatuntixf(a: u128) callconv(.C) f80 { | |
| 158 | return floatXiYf(f80, a); | |
| 159 | } | |
| 160 | ||
| 161 | // Conversion to f128 | |
| 162 | pub fn __floatsitf(a: i32) callconv(.C) f128 { | |
| 163 | return floatXiYf(f128, a); | |
| 164 | } | |
| 165 | ||
| 166 | pub fn __floatunsitf(a: u32) callconv(.C) f128 { | |
| 167 | return floatXiYf(f128, a); | |
| 168 | } | |
| 169 | ||
| 170 | pub fn __floatditf(a: i64) callconv(.C) f128 { | |
| 171 | return floatXiYf(f128, a); | |
| 172 | } | |
| 173 | ||
| 174 | pub fn __floatunditf(a: u64) callconv(.C) f128 { | |
| 175 | return floatXiYf(f128, a); | |
| 176 | } | |
| 177 | ||
| 178 | pub fn __floattitf(a: i128) callconv(.C) f128 { | |
| 179 | return floatXiYf(f128, a); | |
| 180 | } | |
| 181 | ||
| 182 | pub fn __floatuntitf(a: u128) callconv(.C) f128 { | |
| 183 | return floatXiYf(f128, a); | |
| 184 | } | |
| 185 | ||
| 186 | // Conversion to f32 | |
| 187 | pub fn __aeabi_ui2f(arg: u32) callconv(.AAPCS) f32 { | |
| 188 | return floatXiYf(f32, arg); | |
| 189 | } | |
| 190 | ||
| 191 | pub fn __aeabi_i2f(arg: i32) callconv(.AAPCS) f32 { | |
| 192 | return floatXiYf(f32, arg); | |
| 193 | } | |
| 194 | ||
| 195 | pub fn __aeabi_ul2f(arg: u64) callconv(.AAPCS) f32 { | |
| 196 | return floatXiYf(f32, arg); | |
| 197 | } | |
| 198 | ||
| 199 | pub fn __aeabi_l2f(arg: i64) callconv(.AAPCS) f32 { | |
| 200 | return floatXiYf(f32, arg); | |
| 201 | } | |
| 202 | ||
| 203 | // Conversion to f64 | |
| 204 | pub fn __aeabi_ui2d(arg: u32) callconv(.AAPCS) f64 { | |
| 205 | return floatXiYf(f64, arg); | |
| 206 | } | |
| 207 | ||
| 208 | pub fn __aeabi_i2d(arg: i32) callconv(.AAPCS) f64 { | |
| 209 | return floatXiYf(f64, arg); | |
| 210 | } | |
| 211 | ||
| 212 | pub fn __aeabi_ul2d(arg: u64) callconv(.AAPCS) f64 { | |
| 213 | return floatXiYf(f64, arg); | |
| 214 | } | |
| 215 | ||
| 216 | pub fn __aeabi_l2d(arg: i64) callconv(.AAPCS) f64 { | |
| 217 | return floatXiYf(f64, arg); | |
| 218 | } | |
| 219 | ||
| 220 | test { | |
| 221 | _ = @import("floatXiYf_test.zig"); | |
| 222 | } |
lib/compiler_rt/floatXiYf_test.zig deleted-835| ... | ... | @@ -1,835 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const testing = std.testing; | |
| 4 | const math = std.math; | |
| 5 | const floatXiYf = @import("floatXiYf.zig").floatXiYf; | |
| 6 | ||
| 7 | // Conversion to f32 | |
| 8 | const __floatsisf = @import("floatXiYf.zig").__floatsisf; | |
| 9 | const __floatunsisf = @import("floatXiYf.zig").__floatunsisf; | |
| 10 | const __floatdisf = @import("floatXiYf.zig").__floatdisf; | |
| 11 | const __floatundisf = @import("floatXiYf.zig").__floatundisf; | |
| 12 | const __floattisf = @import("floatXiYf.zig").__floattisf; | |
| 13 | const __floatuntisf = @import("floatXiYf.zig").__floatuntisf; | |
| 14 | ||
| 15 | // Conversion to f64 | |
| 16 | const __floatsidf = @import("floatXiYf.zig").__floatsidf; | |
| 17 | const __floatunsidf = @import("floatXiYf.zig").__floatunsidf; | |
| 18 | const __floatdidf = @import("floatXiYf.zig").__floatdidf; | |
| 19 | const __floatundidf = @import("floatXiYf.zig").__floatundidf; | |
| 20 | const __floattidf = @import("floatXiYf.zig").__floattidf; | |
| 21 | const __floatuntidf = @import("floatXiYf.zig").__floatuntidf; | |
| 22 | ||
| 23 | // Conversion to f128 | |
| 24 | const __floatsitf = @import("floatXiYf.zig").__floatsitf; | |
| 25 | const __floatunsitf = @import("floatXiYf.zig").__floatunsitf; | |
| 26 | const __floatditf = @import("floatXiYf.zig").__floatditf; | |
| 27 | const __floatunditf = @import("floatXiYf.zig").__floatunditf; | |
| 28 | const __floattitf = @import("floatXiYf.zig").__floattitf; | |
| 29 | const __floatuntitf = @import("floatXiYf.zig").__floatuntitf; | |
| 30 | ||
| 31 | fn test__floatsisf(a: i32, expected: u32) !void { | |
| 32 | const r = __floatsisf(a); | |
| 33 | try std.testing.expect(@bitCast(u32, r) == expected); | |
| 34 | } | |
| 35 | ||
| 36 | fn test_one_floatunsisf(a: u32, expected: u32) !void { | |
| 37 | const r = __floatunsisf(a); | |
| 38 | try std.testing.expect(@bitCast(u32, r) == expected); | |
| 39 | } | |
| 40 | ||
| 41 | test "floatsisf" { | |
| 42 | try test__floatsisf(0, 0x00000000); | |
| 43 | try test__floatsisf(1, 0x3f800000); | |
| 44 | try test__floatsisf(-1, 0xbf800000); | |
| 45 | try test__floatsisf(0x7FFFFFFF, 0x4f000000); | |
| 46 | try test__floatsisf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xcf000000); | |
| 47 | } | |
| 48 | ||
| 49 | test "floatunsisf" { | |
| 50 | // Test the produced bit pattern | |
| 51 | try test_one_floatunsisf(0, 0); | |
| 52 | try test_one_floatunsisf(1, 0x3f800000); | |
| 53 | try test_one_floatunsisf(0x7FFFFFFF, 0x4f000000); | |
| 54 | try test_one_floatunsisf(0x80000000, 0x4f000000); | |
| 55 | try test_one_floatunsisf(0xFFFFFFFF, 0x4f800000); | |
| 56 | } | |
| 57 | ||
| 58 | fn test__floatdisf(a: i64, expected: f32) !void { | |
| 59 | const x = __floatdisf(a); | |
| 60 | try testing.expect(x == expected); | |
| 61 | } | |
| 62 | ||
| 63 | fn test__floatundisf(a: u64, expected: f32) !void { | |
| 64 | try std.testing.expectEqual(expected, __floatundisf(a)); | |
| 65 | } | |
| 66 | ||
| 67 | test "floatdisf" { | |
| 68 | try test__floatdisf(0, 0.0); | |
| 69 | try test__floatdisf(1, 1.0); | |
| 70 | try test__floatdisf(2, 2.0); | |
| 71 | try test__floatdisf(-1, -1.0); | |
| 72 | try test__floatdisf(-2, -2.0); | |
| 73 | try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 74 | try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 75 | try test__floatdisf(@bitCast(i64, @as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); | |
| 76 | try test__floatdisf(@bitCast(i64, @as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); | |
| 77 | try test__floatdisf(@bitCast(i64, @as(u64, 0x8000000000000000)), -0x1.000000p+63); | |
| 78 | try test__floatdisf(@bitCast(i64, @as(u64, 0x8000000000000001)), -0x1.000000p+63); | |
| 79 | try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 80 | try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 81 | try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 82 | try test__floatdisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 83 | try test__floatdisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 84 | try test__floatdisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 85 | try test__floatdisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 86 | try test__floatdisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 87 | try test__floatdisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 88 | try test__floatdisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 89 | try test__floatdisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 90 | } | |
| 91 | ||
| 92 | test "floatundisf" { | |
| 93 | try test__floatundisf(0, 0.0); | |
| 94 | try test__floatundisf(1, 1.0); | |
| 95 | try test__floatundisf(2, 2.0); | |
| 96 | try test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 97 | try test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 98 | try test__floatundisf(0x8000008000000000, 0x1p+63); | |
| 99 | try test__floatundisf(0x8000010000000000, 0x1.000002p+63); | |
| 100 | try test__floatundisf(0x8000000000000000, 0x1p+63); | |
| 101 | try test__floatundisf(0x8000000000000001, 0x1p+63); | |
| 102 | try test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); | |
| 103 | try test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); | |
| 104 | try test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 105 | try test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 106 | try test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 107 | try test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 108 | try test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 109 | try test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 110 | try test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 111 | try test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 112 | try test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 113 | try test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 114 | try test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 115 | } | |
| 116 | ||
| 117 | fn test__floattisf(a: i128, expected: f32) !void { | |
| 118 | const x = __floattisf(a); | |
| 119 | try testing.expect(x == expected); | |
| 120 | } | |
| 121 | ||
| 122 | fn test__floatuntisf(a: u128, expected: f32) !void { | |
| 123 | const x = __floatuntisf(a); | |
| 124 | try testing.expect(x == expected); | |
| 125 | } | |
| 126 | ||
| 127 | test "floattisf" { | |
| 128 | try test__floattisf(0, 0.0); | |
| 129 | ||
| 130 | try test__floattisf(1, 1.0); | |
| 131 | try test__floattisf(2, 2.0); | |
| 132 | try test__floattisf(-1, -1.0); | |
| 133 | try test__floattisf(-2, -2.0); | |
| 134 | ||
| 135 | try test__floattisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 136 | try test__floattisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 137 | ||
| 138 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62); | |
| 139 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62); | |
| 140 | ||
| 141 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63); | |
| 142 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63); | |
| 143 | ||
| 144 | try test__floattisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 145 | ||
| 146 | try test__floattisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 147 | try test__floattisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 148 | try test__floattisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 149 | try test__floattisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 150 | try test__floattisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 151 | ||
| 152 | try test__floattisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 153 | try test__floattisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 154 | try test__floattisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 155 | try test__floattisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 156 | try test__floattisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 157 | ||
| 158 | try test__floattisf(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114); | |
| 159 | ||
| 160 | try test__floattisf(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114); | |
| 161 | try test__floattisf(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114); | |
| 162 | try test__floattisf(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114); | |
| 163 | try test__floattisf(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114); | |
| 164 | try test__floattisf(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114); | |
| 165 | ||
| 166 | try test__floattisf(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114); | |
| 167 | try test__floattisf(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114); | |
| 168 | try test__floattisf(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114); | |
| 169 | try test__floattisf(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114); | |
| 170 | try test__floattisf(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114); | |
| 171 | } | |
| 172 | ||
| 173 | test "floatuntisf" { | |
| 174 | try test__floatuntisf(0, 0.0); | |
| 175 | ||
| 176 | try test__floatuntisf(1, 1.0); | |
| 177 | try test__floatuntisf(2, 2.0); | |
| 178 | try test__floatuntisf(20, 20.0); | |
| 179 | ||
| 180 | try test__floatuntisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 181 | try test__floatuntisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 182 | ||
| 183 | try test__floatuntisf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); | |
| 184 | try test__floatuntisf(make_uti(0x8000000000000800, 0), 0x1.0p+127); | |
| 185 | try test__floatuntisf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); | |
| 186 | ||
| 187 | try test__floatuntisf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); | |
| 188 | ||
| 189 | try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 190 | ||
| 191 | try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 192 | try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 193 | ||
| 194 | try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 195 | ||
| 196 | try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 197 | try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 198 | try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 199 | ||
| 200 | try test__floatuntisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); | |
| 201 | try test__floatuntisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); | |
| 202 | ||
| 203 | try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 204 | ||
| 205 | try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 206 | try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 207 | try test__floatuntisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 208 | try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 209 | try test__floatuntisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 210 | ||
| 211 | try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 212 | try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 213 | try test__floatuntisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 214 | try test__floatuntisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 215 | try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 216 | ||
| 217 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76); | |
| 218 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76); | |
| 219 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76); | |
| 220 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76); | |
| 221 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76); | |
| 222 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76); | |
| 223 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76); | |
| 224 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76); | |
| 225 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76); | |
| 226 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76); | |
| 227 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76); | |
| 228 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76); | |
| 229 | ||
| 230 | // Test overflow to infinity | |
| 231 | try test__floatuntisf(@as(u128, math.maxInt(u128)), @bitCast(f32, math.inf(f32))); | |
| 232 | } | |
| 233 | ||
| 234 | fn test_one_floatsidf(a: i32, expected: u64) !void { | |
| 235 | const r = __floatsidf(a); | |
| 236 | try std.testing.expect(@bitCast(u64, r) == expected); | |
| 237 | } | |
| 238 | ||
| 239 | fn test_one_floatunsidf(a: u32, expected: u64) !void { | |
| 240 | const r = __floatunsidf(a); | |
| 241 | try std.testing.expect(@bitCast(u64, r) == expected); | |
| 242 | } | |
| 243 | ||
| 244 | test "floatsidf" { | |
| 245 | try test_one_floatsidf(0, 0x0000000000000000); | |
| 246 | try test_one_floatsidf(1, 0x3ff0000000000000); | |
| 247 | try test_one_floatsidf(-1, 0xbff0000000000000); | |
| 248 | try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000); | |
| 249 | try test_one_floatsidf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc1e0000000000000); | |
| 250 | } | |
| 251 | ||
| 252 | test "floatunsidf" { | |
| 253 | try test_one_floatunsidf(0, 0x0000000000000000); | |
| 254 | try test_one_floatunsidf(1, 0x3ff0000000000000); | |
| 255 | try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000); | |
| 256 | try test_one_floatunsidf(@intCast(u32, 0x80000000), 0x41e0000000000000); | |
| 257 | try test_one_floatunsidf(@intCast(u32, 0xFFFFFFFF), 0x41efffffffe00000); | |
| 258 | } | |
| 259 | ||
| 260 | fn test__floatdidf(a: i64, expected: f64) !void { | |
| 261 | const r = __floatdidf(a); | |
| 262 | try testing.expect(r == expected); | |
| 263 | } | |
| 264 | ||
| 265 | fn test__floatundidf(a: u64, expected: f64) !void { | |
| 266 | const r = __floatundidf(a); | |
| 267 | try testing.expect(r == expected); | |
| 268 | } | |
| 269 | ||
| 270 | test "floatdidf" { | |
| 271 | try test__floatdidf(0, 0.0); | |
| 272 | try test__floatdidf(1, 1.0); | |
| 273 | try test__floatdidf(2, 2.0); | |
| 274 | try test__floatdidf(20, 20.0); | |
| 275 | try test__floatdidf(-1, -1.0); | |
| 276 | try test__floatdidf(-2, -2.0); | |
| 277 | try test__floatdidf(-20, -20.0); | |
| 278 | try test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 279 | try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 280 | try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 281 | try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 282 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); | |
| 283 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000800)), -0x1.FFFFFFFFFFFFEp+62); | |
| 284 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); | |
| 285 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000001000)), -0x1.FFFFFFFFFFFFCp+62); | |
| 286 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000000)), -0x1.000000p+63); | |
| 287 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000001)), -0x1.000000p+63); // 0x8000000000000001 | |
| 288 | try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 289 | try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 290 | try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 291 | try test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 292 | try test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 293 | try test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 294 | try test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 295 | try test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 296 | try test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 297 | try test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 298 | try test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 299 | try test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 300 | try test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 301 | try test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 302 | try test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 303 | try test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 304 | try test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 305 | try test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 306 | try test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 307 | try test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 308 | try test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 309 | try test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 310 | try test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 311 | try test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 312 | try test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 313 | try test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 314 | } | |
| 315 | ||
| 316 | test "floatundidf" { | |
| 317 | try test__floatundidf(0, 0.0); | |
| 318 | try test__floatundidf(1, 1.0); | |
| 319 | try test__floatundidf(2, 2.0); | |
| 320 | try test__floatundidf(20, 20.0); | |
| 321 | try test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 322 | try test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 323 | try test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 324 | try test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 325 | try test__floatundidf(0x8000008000000000, 0x1.000001p+63); | |
| 326 | try test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63); | |
| 327 | try test__floatundidf(0x8000010000000000, 0x1.000002p+63); | |
| 328 | try test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63); | |
| 329 | try test__floatundidf(0x8000000000000000, 0x1p+63); | |
| 330 | try test__floatundidf(0x8000000000000001, 0x1p+63); | |
| 331 | try test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 332 | try test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 333 | try test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 334 | try test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 335 | try test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 336 | try test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 337 | try test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 338 | try test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 339 | try test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 340 | try test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 341 | try test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 342 | try test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 343 | try test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 344 | try test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 345 | try test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 346 | try test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 347 | try test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 348 | try test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 349 | try test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 350 | try test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 351 | try test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 352 | try test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 353 | try test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 354 | try test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 355 | try test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 356 | try test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 357 | } | |
| 358 | ||
| 359 | fn test__floattidf(a: i128, expected: f64) !void { | |
| 360 | const x = __floattidf(a); | |
| 361 | try testing.expect(x == expected); | |
| 362 | } | |
| 363 | ||
| 364 | fn test__floatuntidf(a: u128, expected: f64) !void { | |
| 365 | const x = __floatuntidf(a); | |
| 366 | try testing.expect(x == expected); | |
| 367 | } | |
| 368 | ||
| 369 | test "floattidf" { | |
| 370 | try test__floattidf(0, 0.0); | |
| 371 | ||
| 372 | try test__floattidf(1, 1.0); | |
| 373 | try test__floattidf(2, 2.0); | |
| 374 | try test__floattidf(20, 20.0); | |
| 375 | try test__floattidf(-1, -1.0); | |
| 376 | try test__floattidf(-2, -2.0); | |
| 377 | try test__floattidf(-20, -20.0); | |
| 378 | ||
| 379 | try test__floattidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 380 | try test__floattidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 381 | try test__floattidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 382 | try test__floattidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 383 | ||
| 384 | try test__floattidf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); | |
| 385 | try test__floattidf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); | |
| 386 | try test__floattidf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); | |
| 387 | try test__floattidf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); | |
| 388 | ||
| 389 | try test__floattidf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); | |
| 390 | try test__floattidf(make_ti(0x8000000000000001, 0), -0x1.000000p+127); | |
| 391 | ||
| 392 | try test__floattidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 393 | ||
| 394 | try test__floattidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 395 | try test__floattidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 396 | try test__floattidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 397 | try test__floattidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 398 | try test__floattidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 399 | ||
| 400 | try test__floattidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 401 | try test__floattidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 402 | try test__floattidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 403 | try test__floattidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 404 | try test__floattidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 405 | ||
| 406 | try test__floattidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 407 | try test__floattidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 408 | try test__floattidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 409 | try test__floattidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 410 | try test__floattidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 411 | try test__floattidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 412 | try test__floattidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 413 | try test__floattidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 414 | try test__floattidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 415 | try test__floattidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 416 | try test__floattidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 417 | try test__floattidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 418 | try test__floattidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 419 | try test__floattidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 420 | try test__floattidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 421 | ||
| 422 | try test__floattidf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 423 | try test__floattidf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); | |
| 424 | try test__floattidf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); | |
| 425 | try test__floattidf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); | |
| 426 | try test__floattidf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); | |
| 427 | try test__floattidf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); | |
| 428 | try test__floattidf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); | |
| 429 | try test__floattidf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); | |
| 430 | try test__floattidf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); | |
| 431 | try test__floattidf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); | |
| 432 | try test__floattidf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); | |
| 433 | try test__floattidf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); | |
| 434 | try test__floattidf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); | |
| 435 | try test__floattidf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); | |
| 436 | try test__floattidf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 437 | } | |
| 438 | ||
| 439 | test "floatuntidf" { | |
| 440 | try test__floatuntidf(0, 0.0); | |
| 441 | ||
| 442 | try test__floatuntidf(1, 1.0); | |
| 443 | try test__floatuntidf(2, 2.0); | |
| 444 | try test__floatuntidf(20, 20.0); | |
| 445 | ||
| 446 | try test__floatuntidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 447 | try test__floatuntidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 448 | try test__floatuntidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 449 | try test__floatuntidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 450 | ||
| 451 | try test__floatuntidf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); | |
| 452 | try test__floatuntidf(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127); | |
| 453 | try test__floatuntidf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); | |
| 454 | try test__floatuntidf(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127); | |
| 455 | ||
| 456 | try test__floatuntidf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); | |
| 457 | try test__floatuntidf(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127); | |
| 458 | ||
| 459 | try test__floatuntidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 460 | ||
| 461 | try test__floatuntidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 462 | try test__floatuntidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 463 | try test__floatuntidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 464 | try test__floatuntidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 465 | try test__floatuntidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 466 | ||
| 467 | try test__floatuntidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 468 | try test__floatuntidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 469 | try test__floatuntidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 470 | try test__floatuntidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 471 | try test__floatuntidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 472 | ||
| 473 | try test__floatuntidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 474 | try test__floatuntidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 475 | try test__floatuntidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 476 | try test__floatuntidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 477 | try test__floatuntidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 478 | try test__floatuntidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 479 | try test__floatuntidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 480 | try test__floatuntidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 481 | try test__floatuntidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 482 | try test__floatuntidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 483 | try test__floatuntidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 484 | try test__floatuntidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 485 | try test__floatuntidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 486 | try test__floatuntidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 487 | try test__floatuntidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 488 | ||
| 489 | try test__floatuntidf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 490 | try test__floatuntidf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); | |
| 491 | try test__floatuntidf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); | |
| 492 | try test__floatuntidf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); | |
| 493 | try test__floatuntidf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); | |
| 494 | try test__floatuntidf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); | |
| 495 | try test__floatuntidf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); | |
| 496 | try test__floatuntidf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); | |
| 497 | try test__floatuntidf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); | |
| 498 | try test__floatuntidf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); | |
| 499 | try test__floatuntidf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); | |
| 500 | try test__floatuntidf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); | |
| 501 | try test__floatuntidf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); | |
| 502 | try test__floatuntidf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); | |
| 503 | try test__floatuntidf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 504 | } | |
| 505 | ||
| 506 | fn test__floatsitf(a: i32, expected: u128) !void { | |
| 507 | const r = __floatsitf(a); | |
| 508 | try std.testing.expect(@bitCast(u128, r) == expected); | |
| 509 | } | |
| 510 | ||
| 511 | test "floatsitf" { | |
| 512 | try test__floatsitf(0, 0); | |
| 513 | try test__floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000); | |
| 514 | try test__floatsitf(0x12345678, 0x401b2345678000000000000000000000); | |
| 515 | try test__floatsitf(-0x12345678, 0xc01b2345678000000000000000000000); | |
| 516 | try test__floatsitf(@bitCast(i32, @intCast(u32, 0xffffffff)), 0xbfff0000000000000000000000000000); | |
| 517 | try test__floatsitf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc01e0000000000000000000000000000); | |
| 518 | } | |
| 519 | ||
| 520 | fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void { | |
| 521 | const x = __floatunsitf(a); | |
| 522 | ||
| 523 | const x_repr = @bitCast(u128, x); | |
| 524 | const x_hi = @intCast(u64, x_repr >> 64); | |
| 525 | const x_lo = @truncate(u64, x_repr); | |
| 526 | ||
| 527 | if (x_hi == expected_hi and x_lo == expected_lo) { | |
| 528 | return; | |
| 529 | } | |
| 530 | // nan repr | |
| 531 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 532 | if ((x_hi & 0x7fff000000000000) == 0x7fff000000000000 and ((x_hi & 0xffffffffffff) > 0 or x_lo > 0)) { | |
| 533 | return; | |
| 534 | } | |
| 535 | } | |
| 536 | ||
| 537 | @panic("__floatunsitf test failure"); | |
| 538 | } | |
| 539 | ||
| 540 | test "floatunsitf" { | |
| 541 | try test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0); | |
| 542 | try test__floatunsitf(0, 0x0, 0x0); | |
| 543 | try test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0); | |
| 544 | try test__floatunsitf(0x12345678, 0x401b234567800000, 0x0); | |
| 545 | } | |
| 546 | ||
| 547 | fn test__floatditf(a: i64, expected: f128) !void { | |
| 548 | const x = __floatditf(a); | |
| 549 | try testing.expect(x == expected); | |
| 550 | } | |
| 551 | ||
| 552 | fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void { | |
| 553 | const x = __floatunditf(a); | |
| 554 | ||
| 555 | const x_repr = @bitCast(u128, x); | |
| 556 | const x_hi = @intCast(u64, x_repr >> 64); | |
| 557 | const x_lo = @truncate(u64, x_repr); | |
| 558 | ||
| 559 | if (x_hi == expected_hi and x_lo == expected_lo) { | |
| 560 | return; | |
| 561 | } | |
| 562 | // nan repr | |
| 563 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 564 | if ((x_hi & 0x7fff000000000000) == 0x7fff000000000000 and ((x_hi & 0xffffffffffff) > 0 or x_lo > 0)) { | |
| 565 | return; | |
| 566 | } | |
| 567 | } | |
| 568 | ||
| 569 | @panic("__floatunditf test failure"); | |
| 570 | } | |
| 571 | ||
| 572 | test "floatditf" { | |
| 573 | try test__floatditf(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000)); | |
| 574 | try test__floatditf(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000)); | |
| 575 | try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0)); | |
| 576 | try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0)); | |
| 577 | try test__floatditf(0x0, make_tf(0x0, 0x0)); | |
| 578 | try test__floatditf(@bitCast(i64, @as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0)); | |
| 579 | try test__floatditf(@bitCast(i64, @as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0)); | |
| 580 | try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000)); | |
| 581 | try test__floatditf(@bitCast(i64, @as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0)); | |
| 582 | } | |
| 583 | ||
| 584 | test "floatunditf" { | |
| 585 | try test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000); | |
| 586 | try test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000); | |
| 587 | try test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0); | |
| 588 | try test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000); | |
| 589 | try test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000); | |
| 590 | try test__floatunditf(0x2, 0x4000000000000000, 0x0); | |
| 591 | try test__floatunditf(0x1, 0x3fff000000000000, 0x0); | |
| 592 | try test__floatunditf(0x0, 0x0, 0x0); | |
| 593 | } | |
| 594 | ||
| 595 | fn test__floattitf(a: i128, expected: f128) !void { | |
| 596 | const x = __floattitf(a); | |
| 597 | try testing.expect(x == expected); | |
| 598 | } | |
| 599 | ||
| 600 | fn test__floatuntitf(a: u128, expected: f128) !void { | |
| 601 | const x = __floatuntitf(a); | |
| 602 | try testing.expect(x == expected); | |
| 603 | } | |
| 604 | ||
| 605 | test "floattitf" { | |
| 606 | try test__floattitf(0, 0.0); | |
| 607 | ||
| 608 | try test__floattitf(1, 1.0); | |
| 609 | try test__floattitf(2, 2.0); | |
| 610 | try test__floattitf(20, 20.0); | |
| 611 | try test__floattitf(-1, -1.0); | |
| 612 | try test__floattitf(-2, -2.0); | |
| 613 | try test__floattitf(-20, -20.0); | |
| 614 | ||
| 615 | try test__floattitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 616 | try test__floattitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 617 | try test__floattitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 618 | try test__floattitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 619 | ||
| 620 | try test__floattitf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); | |
| 621 | try test__floattitf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); | |
| 622 | try test__floattitf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); | |
| 623 | try test__floattitf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); | |
| 624 | ||
| 625 | try test__floattitf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); | |
| 626 | try test__floattitf(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126); | |
| 627 | ||
| 628 | try test__floattitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 629 | ||
| 630 | try test__floattitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 631 | try test__floattitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 632 | try test__floattitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 633 | try test__floattitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 634 | try test__floattitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 635 | ||
| 636 | try test__floattitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 637 | try test__floattitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 638 | try test__floattitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 639 | try test__floattitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 640 | try test__floattitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 641 | ||
| 642 | try test__floattitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 643 | try test__floattitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); | |
| 644 | try test__floattitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); | |
| 645 | try test__floattitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); | |
| 646 | try test__floattitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); | |
| 647 | try test__floattitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); | |
| 648 | try test__floattitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); | |
| 649 | try test__floattitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); | |
| 650 | try test__floattitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); | |
| 651 | try test__floattitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); | |
| 652 | try test__floattitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); | |
| 653 | try test__floattitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); | |
| 654 | try test__floattitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); | |
| 655 | try test__floattitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); | |
| 656 | try test__floattitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 657 | ||
| 658 | try test__floattitf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 659 | try test__floattitf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); | |
| 660 | try test__floattitf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); | |
| 661 | try test__floattitf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); | |
| 662 | try test__floattitf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); | |
| 663 | try test__floattitf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); | |
| 664 | try test__floattitf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); | |
| 665 | try test__floattitf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); | |
| 666 | try test__floattitf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); | |
| 667 | try test__floattitf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); | |
| 668 | try test__floattitf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); | |
| 669 | try test__floattitf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); | |
| 670 | try test__floattitf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); | |
| 671 | try test__floattitf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); | |
| 672 | try test__floattitf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 673 | ||
| 674 | try test__floattitf(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); | |
| 675 | ||
| 676 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 677 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 678 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 679 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 680 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 681 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 682 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 683 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 684 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 685 | } | |
| 686 | ||
| 687 | test "floatuntitf" { | |
| 688 | try test__floatuntitf(0, 0.0); | |
| 689 | ||
| 690 | try test__floatuntitf(1, 1.0); | |
| 691 | try test__floatuntitf(2, 2.0); | |
| 692 | try test__floatuntitf(20, 20.0); | |
| 693 | ||
| 694 | try test__floatuntitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 695 | try test__floatuntitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 696 | try test__floatuntitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 697 | try test__floatuntitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 698 | try test__floatuntitf(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59); | |
| 699 | try test__floatuntitf(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60); | |
| 700 | try test__floatuntitf(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60); | |
| 701 | ||
| 702 | try test__floatuntitf(0x8000008000000000, 0x8.000008p+60); | |
| 703 | try test__floatuntitf(0x8000000000000800, 0x8.0000000000008p+60); | |
| 704 | try test__floatuntitf(0x8000010000000000, 0x8.00001p+60); | |
| 705 | try test__floatuntitf(0x8000000000001000, 0x8.000000000001p+60); | |
| 706 | ||
| 707 | try test__floatuntitf(0x8000000000000000, 0x8p+60); | |
| 708 | try test__floatuntitf(0x8000000000000001, 0x8.000000000000001p+60); | |
| 709 | ||
| 710 | try test__floatuntitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 711 | ||
| 712 | try test__floatuntitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 713 | try test__floatuntitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 714 | try test__floatuntitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 715 | try test__floatuntitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 716 | try test__floatuntitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 717 | ||
| 718 | try test__floatuntitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 719 | try test__floatuntitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 720 | try test__floatuntitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 721 | try test__floatuntitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 722 | try test__floatuntitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 723 | ||
| 724 | try test__floatuntitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 725 | try test__floatuntitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); | |
| 726 | try test__floatuntitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); | |
| 727 | try test__floatuntitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); | |
| 728 | try test__floatuntitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); | |
| 729 | try test__floatuntitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); | |
| 730 | try test__floatuntitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); | |
| 731 | try test__floatuntitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); | |
| 732 | try test__floatuntitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); | |
| 733 | try test__floatuntitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); | |
| 734 | try test__floatuntitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); | |
| 735 | try test__floatuntitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); | |
| 736 | try test__floatuntitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); | |
| 737 | try test__floatuntitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); | |
| 738 | try test__floatuntitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 739 | ||
| 740 | try test__floatuntitf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 741 | try test__floatuntitf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); | |
| 742 | try test__floatuntitf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); | |
| 743 | try test__floatuntitf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); | |
| 744 | try test__floatuntitf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); | |
| 745 | try test__floatuntitf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); | |
| 746 | try test__floatuntitf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); | |
| 747 | try test__floatuntitf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); | |
| 748 | try test__floatuntitf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); | |
| 749 | try test__floatuntitf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); | |
| 750 | try test__floatuntitf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); | |
| 751 | try test__floatuntitf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); | |
| 752 | try test__floatuntitf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); | |
| 753 | try test__floatuntitf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); | |
| 754 | try test__floatuntitf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 755 | ||
| 756 | try test__floatuntitf(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); | |
| 757 | ||
| 758 | try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127); | |
| 759 | try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128); | |
| 760 | ||
| 761 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 762 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 763 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 764 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 765 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 766 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 767 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 768 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 769 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 770 | } | |
| 771 | ||
| 772 | fn make_ti(high: u64, low: u64) i128 { | |
| 773 | var result: u128 = high; | |
| 774 | result <<= 64; | |
| 775 | result |= low; | |
| 776 | return @bitCast(i128, result); | |
| 777 | } | |
| 778 | ||
| 779 | fn make_uti(high: u64, low: u64) u128 { | |
| 780 | var result: u128 = high; | |
| 781 | result <<= 64; | |
| 782 | result |= low; | |
| 783 | return result; | |
| 784 | } | |
| 785 | ||
| 786 | fn make_tf(high: u64, low: u64) f128 { | |
| 787 | var result: u128 = high; | |
| 788 | result <<= 64; | |
| 789 | result |= low; | |
| 790 | return @bitCast(f128, result); | |
| 791 | } | |
| 792 | ||
| 793 | test "conversion to f16" { | |
| 794 | try testing.expect(floatXiYf(f16, @as(u32, 0)) == 0.0); | |
| 795 | try testing.expect(floatXiYf(f16, @as(u32, 1)) == 1.0); | |
| 796 | try testing.expect(floatXiYf(f16, @as(u32, 65504)) == 65504); | |
| 797 | try testing.expect(floatXiYf(f16, @as(u32, 65504 + (1 << 4))) == math.inf(f16)); | |
| 798 | } | |
| 799 | ||
| 800 | test "conversion to f32" { | |
| 801 | try testing.expect(floatXiYf(f32, @as(u32, 0)) == 0.0); | |
| 802 | try testing.expect(floatXiYf(f32, @as(u32, math.maxInt(u32))) != 1.0); | |
| 803 | try testing.expect(floatXiYf(f32, @as(i32, math.minInt(i32))) != 1.0); | |
| 804 | try testing.expect(floatXiYf(f32, @as(u32, math.maxInt(u24))) == math.maxInt(u24)); | |
| 805 | try testing.expect(floatXiYf(f32, @as(u32, math.maxInt(u24)) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact | |
| 806 | try testing.expect(floatXiYf(f32, @as(u32, math.maxInt(u24)) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even | |
| 807 | try testing.expect(floatXiYf(f32, @as(u32, math.maxInt(u24)) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact | |
| 808 | try testing.expect(floatXiYf(f32, @as(u32, math.maxInt(u24)) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even | |
| 809 | try testing.expect(floatXiYf(f32, @as(u32, math.maxInt(u24)) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact | |
| 810 | } | |
| 811 | ||
| 812 | test "conversion to f80" { | |
| 813 | if (builtin.zig_backend == .stage1 and builtin.cpu.arch != .x86_64) | |
| 814 | return error.SkipZigTest; // https://github.com/ziglang/zig/issues/11408 | |
| 815 | ||
| 816 | try testing.expect(floatXiYf(f80, @as(i80, -12)) == -12); | |
| 817 | try testing.expect(@floatToInt(u80, floatXiYf(f80, @as(u64, math.maxInt(u64)) + 0)) == math.maxInt(u64) + 0); | |
| 818 | try testing.expect(@floatToInt(u80, floatXiYf(f80, @as(u80, math.maxInt(u64)) + 1)) == math.maxInt(u64) + 1); | |
| 819 | ||
| 820 | try testing.expect(floatXiYf(f80, @as(u32, 0)) == 0.0); | |
| 821 | try testing.expect(floatXiYf(f80, @as(u32, 1)) == 1.0); | |
| 822 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u32, math.maxInt(u24)) + 0)) == math.maxInt(u24)); | |
| 823 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u64)) + 0)) == math.maxInt(u64)); | |
| 824 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u64)) + 1)) == math.maxInt(u64) + 1); // Exact | |
| 825 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u64)) + 2)) == math.maxInt(u64) + 1); // Rounds down | |
| 826 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u64)) + 3)) == math.maxInt(u64) + 3); // Tie - Exact | |
| 827 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u64)) + 4)) == math.maxInt(u64) + 5); // Rounds up | |
| 828 | ||
| 829 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u65)) + 0)) == math.maxInt(u65) + 1); // Rounds up | |
| 830 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u65)) + 1)) == math.maxInt(u65) + 1); // Exact | |
| 831 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u65)) + 2)) == math.maxInt(u65) + 1); // Rounds down | |
| 832 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u65)) + 3)) == math.maxInt(u65) + 1); // Tie - Rounds down | |
| 833 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u65)) + 4)) == math.maxInt(u65) + 5); // Rounds up | |
| 834 | try testing.expect(@floatToInt(u128, floatXiYf(f80, @as(u80, math.maxInt(u65)) + 5)) == math.maxInt(u65) + 5); // Exact | |
| 835 | } |
lib/compiler_rt/float_to_int.zig created+55| ... | ... | @@ -0,0 +1,55 @@ |
| 1 | const Int = @import("std").meta.Int; | |
| 2 | const math = @import("std").math; | |
| 3 | const Log2Int = math.Log2Int; | |
| 4 | ||
| 5 | pub inline fn floatToInt(comptime I: type, a: anytype) I { | |
| 6 | const F = @TypeOf(a); | |
| 7 | const float_bits = @typeInfo(F).Float.bits; | |
| 8 | const int_bits = @typeInfo(I).Int.bits; | |
| 9 | const rep_t = Int(.unsigned, float_bits); | |
| 10 | const sig_bits = math.floatMantissaBits(F); | |
| 11 | const exp_bits = math.floatExponentBits(F); | |
| 12 | const fractional_bits = math.floatFractionalBits(F); | |
| 13 | ||
| 14 | const implicit_bit = if (F != f80) (@as(rep_t, 1) << sig_bits) else 0; | |
| 15 | const max_exp = (1 << (exp_bits - 1)); | |
| 16 | const exp_bias = max_exp - 1; | |
| 17 | const sig_mask = (@as(rep_t, 1) << sig_bits) - 1; | |
| 18 | ||
| 19 | // Break a into sign, exponent, significand | |
| 20 | const a_rep: rep_t = @bitCast(rep_t, a); | |
| 21 | const negative = (a_rep >> (float_bits - 1)) != 0; | |
| 22 | const exponent = @intCast(i32, (a_rep << 1) >> (sig_bits + 1)) - exp_bias; | |
| 23 | const significand: rep_t = (a_rep & sig_mask) | implicit_bit; | |
| 24 | ||
| 25 | // If the exponent is negative, the result rounds to zero. | |
| 26 | if (exponent < 0) return 0; | |
| 27 | ||
| 28 | // If the value is too large for the integer type, saturate. | |
| 29 | switch (@typeInfo(I).Int.signedness) { | |
| 30 | .unsigned => { | |
| 31 | if (negative) return 0; | |
| 32 | if (@intCast(c_uint, exponent) >= @minimum(int_bits, max_exp)) return math.maxInt(I); | |
| 33 | }, | |
| 34 | .signed => if (@intCast(c_uint, exponent) >= @minimum(int_bits - 1, max_exp)) { | |
| 35 | return if (negative) math.minInt(I) else math.maxInt(I); | |
| 36 | }, | |
| 37 | } | |
| 38 | ||
| 39 | // If 0 <= exponent < sig_bits, right shift to get the result. | |
| 40 | // Otherwise, shift left. | |
| 41 | var result: I = undefined; | |
| 42 | if (exponent < fractional_bits) { | |
| 43 | result = @intCast(I, significand >> @intCast(Log2Int(rep_t), fractional_bits - exponent)); | |
| 44 | } else { | |
| 45 | result = @intCast(I, significand) << @intCast(Log2Int(I), exponent - fractional_bits); | |
| 46 | } | |
| 47 | ||
| 48 | if ((@typeInfo(I).Int.signedness == .signed) and negative) | |
| 49 | return ~result +% 1; | |
| 50 | return result; | |
| 51 | } | |
| 52 | ||
| 53 | test { | |
| 54 | _ = @import("float_to_int_test.zig"); | |
| 55 | } |
lib/compiler_rt/float_to_int_test.zig created+950| ... | ... | @@ -0,0 +1,950 @@ |
| 1 | const std = @import("std"); | |
| 2 | const testing = std.testing; | |
| 3 | const math = std.math; | |
| 4 | ||
| 5 | const __fixunshfti = @import("fixunshfti.zig").__fixunshfti; | |
| 6 | const __fixunsxfti = @import("fixunsxfti.zig").__fixunsxfti; | |
| 7 | ||
| 8 | // Conversion from f32 | |
| 9 | const __fixsfsi = @import("fixsfsi.zig").__fixsfsi; | |
| 10 | const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; | |
| 11 | const __fixsfdi = @import("fixsfdi.zig").__fixsfdi; | |
| 12 | const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; | |
| 13 | const __fixsfti = @import("fixsfti.zig").__fixsfti; | |
| 14 | const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; | |
| 15 | ||
| 16 | // Conversion from f64 | |
| 17 | const __fixdfsi = @import("fixdfsi.zig").__fixdfsi; | |
| 18 | const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; | |
| 19 | const __fixdfdi = @import("fixdfdi.zig").__fixdfdi; | |
| 20 | const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; | |
| 21 | const __fixdfti = @import("fixdfti.zig").__fixdfti; | |
| 22 | const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; | |
| 23 | ||
| 24 | // Conversion from f128 | |
| 25 | const __fixtfsi = @import("fixtfsi.zig").__fixtfsi; | |
| 26 | const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; | |
| 27 | const __fixtfdi = @import("fixtfdi.zig").__fixtfdi; | |
| 28 | const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; | |
| 29 | const __fixtfti = @import("fixtfti.zig").__fixtfti; | |
| 30 | const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; | |
| 31 | ||
| 32 | fn test__fixsfsi(a: f32, expected: i32) !void { | |
| 33 | const x = __fixsfsi(a); | |
| 34 | try testing.expect(x == expected); | |
| 35 | } | |
| 36 | ||
| 37 | fn test__fixunssfsi(a: f32, expected: u32) !void { | |
| 38 | const x = __fixunssfsi(a); | |
| 39 | try testing.expect(x == expected); | |
| 40 | } | |
| 41 | ||
| 42 | test "fixsfsi" { | |
| 43 | try test__fixsfsi(-math.floatMax(f32), math.minInt(i32)); | |
| 44 | ||
| 45 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 46 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 47 | ||
| 48 | try test__fixsfsi(-0x1.0000000000000p+127, -0x80000000); | |
| 49 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 50 | try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 51 | ||
| 52 | try test__fixsfsi(-0x1.0000000000001p+63, -0x80000000); | |
| 53 | try test__fixsfsi(-0x1.0000000000000p+63, -0x80000000); | |
| 54 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 55 | try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 56 | ||
| 57 | try test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000); | |
| 58 | try test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000); | |
| 59 | ||
| 60 | try test__fixsfsi(-0x1.000000p+31, -0x80000000); | |
| 61 | try test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000); | |
| 62 | try test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 63 | try test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 64 | ||
| 65 | try test__fixsfsi(-2.01, -2); | |
| 66 | try test__fixsfsi(-2.0, -2); | |
| 67 | try test__fixsfsi(-1.99, -1); | |
| 68 | try test__fixsfsi(-1.0, -1); | |
| 69 | try test__fixsfsi(-0.99, 0); | |
| 70 | try test__fixsfsi(-0.5, 0); | |
| 71 | try test__fixsfsi(-math.floatMin(f32), 0); | |
| 72 | try test__fixsfsi(0.0, 0); | |
| 73 | try test__fixsfsi(math.floatMin(f32), 0); | |
| 74 | try test__fixsfsi(0.5, 0); | |
| 75 | try test__fixsfsi(0.99, 0); | |
| 76 | try test__fixsfsi(1.0, 1); | |
| 77 | try test__fixsfsi(1.5, 1); | |
| 78 | try test__fixsfsi(1.99, 1); | |
| 79 | try test__fixsfsi(2.0, 2); | |
| 80 | try test__fixsfsi(2.01, 2); | |
| 81 | ||
| 82 | try test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 83 | try test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 84 | try test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF); | |
| 85 | try test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF); | |
| 86 | ||
| 87 | try test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 88 | try test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 89 | ||
| 90 | try test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 91 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 92 | try test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 93 | try test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 94 | ||
| 95 | try test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 96 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 97 | try test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 98 | ||
| 99 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 100 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 101 | ||
| 102 | try test__fixsfsi(math.floatMax(f32), math.maxInt(i32)); | |
| 103 | } | |
| 104 | ||
| 105 | test "fixunssfsi" { | |
| 106 | try test__fixunssfsi(0.0, 0); | |
| 107 | ||
| 108 | try test__fixunssfsi(0.5, 0); | |
| 109 | try test__fixunssfsi(0.99, 0); | |
| 110 | try test__fixunssfsi(1.0, 1); | |
| 111 | try test__fixunssfsi(1.5, 1); | |
| 112 | try test__fixunssfsi(1.99, 1); | |
| 113 | try test__fixunssfsi(2.0, 2); | |
| 114 | try test__fixunssfsi(2.01, 2); | |
| 115 | try test__fixunssfsi(-0.5, 0); | |
| 116 | try test__fixunssfsi(-0.99, 0); | |
| 117 | ||
| 118 | try test__fixunssfsi(-1.0, 0); | |
| 119 | try test__fixunssfsi(-1.5, 0); | |
| 120 | try test__fixunssfsi(-1.99, 0); | |
| 121 | try test__fixunssfsi(-2.0, 0); | |
| 122 | try test__fixunssfsi(-2.01, 0); | |
| 123 | ||
| 124 | try test__fixunssfsi(0x1.000000p+31, 0x80000000); | |
| 125 | try test__fixunssfsi(0x1.000000p+32, 0xFFFFFFFF); | |
| 126 | try test__fixunssfsi(0x1.FFFFFEp+31, 0xFFFFFF00); | |
| 127 | try test__fixunssfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 128 | try test__fixunssfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 129 | ||
| 130 | try test__fixunssfsi(-0x1.FFFFFEp+30, 0); | |
| 131 | try test__fixunssfsi(-0x1.FFFFFCp+30, 0); | |
| 132 | } | |
| 133 | ||
| 134 | fn test__fixsfdi(a: f32, expected: i64) !void { | |
| 135 | const x = __fixsfdi(a); | |
| 136 | try testing.expect(x == expected); | |
| 137 | } | |
| 138 | ||
| 139 | fn test__fixunssfdi(a: f32, expected: u64) !void { | |
| 140 | const x = __fixunssfdi(a); | |
| 141 | try testing.expect(x == expected); | |
| 142 | } | |
| 143 | ||
| 144 | test "fixsfdi" { | |
| 145 | try test__fixsfdi(-math.floatMax(f32), math.minInt(i64)); | |
| 146 | ||
| 147 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 148 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 149 | ||
| 150 | try test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 151 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 152 | try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 153 | ||
| 154 | try test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 155 | try test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 156 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | |
| 157 | try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | |
| 158 | ||
| 159 | try test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000); | |
| 160 | try test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 161 | try test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 162 | ||
| 163 | try test__fixsfdi(-2.01, -2); | |
| 164 | try test__fixsfdi(-2.0, -2); | |
| 165 | try test__fixsfdi(-1.99, -1); | |
| 166 | try test__fixsfdi(-1.0, -1); | |
| 167 | try test__fixsfdi(-0.99, 0); | |
| 168 | try test__fixsfdi(-0.5, 0); | |
| 169 | try test__fixsfdi(-math.floatMin(f32), 0); | |
| 170 | try test__fixsfdi(0.0, 0); | |
| 171 | try test__fixsfdi(math.floatMin(f32), 0); | |
| 172 | try test__fixsfdi(0.5, 0); | |
| 173 | try test__fixsfdi(0.99, 0); | |
| 174 | try test__fixsfdi(1.0, 1); | |
| 175 | try test__fixsfdi(1.5, 1); | |
| 176 | try test__fixsfdi(1.99, 1); | |
| 177 | try test__fixsfdi(2.0, 2); | |
| 178 | try test__fixsfdi(2.01, 2); | |
| 179 | ||
| 180 | try test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 181 | try test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 182 | try test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | |
| 183 | ||
| 184 | try test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF); | |
| 185 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | |
| 186 | try test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 187 | try test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 188 | ||
| 189 | try test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 190 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 191 | try test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 192 | ||
| 193 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 194 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 195 | ||
| 196 | try test__fixsfdi(math.floatMax(f32), math.maxInt(i64)); | |
| 197 | } | |
| 198 | ||
| 199 | test "fixunssfdi" { | |
| 200 | try test__fixunssfdi(0.0, 0); | |
| 201 | ||
| 202 | try test__fixunssfdi(0.5, 0); | |
| 203 | try test__fixunssfdi(0.99, 0); | |
| 204 | try test__fixunssfdi(1.0, 1); | |
| 205 | try test__fixunssfdi(1.5, 1); | |
| 206 | try test__fixunssfdi(1.99, 1); | |
| 207 | try test__fixunssfdi(2.0, 2); | |
| 208 | try test__fixunssfdi(2.01, 2); | |
| 209 | try test__fixunssfdi(-0.5, 0); | |
| 210 | try test__fixunssfdi(-0.99, 0); | |
| 211 | ||
| 212 | try test__fixunssfdi(-1.0, 0); | |
| 213 | try test__fixunssfdi(-1.5, 0); | |
| 214 | try test__fixunssfdi(-1.99, 0); | |
| 215 | try test__fixunssfdi(-2.0, 0); | |
| 216 | try test__fixunssfdi(-2.01, 0); | |
| 217 | ||
| 218 | try test__fixunssfdi(0x1.FFFFFEp+63, 0xFFFFFF0000000000); | |
| 219 | try test__fixunssfdi(0x1.000000p+63, 0x8000000000000000); | |
| 220 | try test__fixunssfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 221 | try test__fixunssfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 222 | ||
| 223 | try test__fixunssfdi(-0x1.FFFFFEp+62, 0x0000000000000000); | |
| 224 | try test__fixunssfdi(-0x1.FFFFFCp+62, 0x0000000000000000); | |
| 225 | } | |
| 226 | ||
| 227 | fn test__fixsfti(a: f32, expected: i128) !void { | |
| 228 | const x = __fixsfti(a); | |
| 229 | try testing.expect(x == expected); | |
| 230 | } | |
| 231 | ||
| 232 | fn test__fixunssfti(a: f32, expected: u128) !void { | |
| 233 | const x = __fixunssfti(a); | |
| 234 | try testing.expect(x == expected); | |
| 235 | } | |
| 236 | ||
| 237 | test "fixsfti" { | |
| 238 | try test__fixsfti(-math.floatMax(f32), math.minInt(i128)); | |
| 239 | ||
| 240 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 241 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 242 | ||
| 243 | try test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 244 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000); | |
| 245 | try test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000); | |
| 246 | try test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000); | |
| 247 | try test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000); | |
| 248 | try test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000); | |
| 249 | ||
| 250 | try test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 251 | try test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 252 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | |
| 253 | try test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | |
| 254 | ||
| 255 | try test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000); | |
| 256 | try test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 257 | try test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 258 | ||
| 259 | try test__fixsfti(-0x1.000000p+31, -0x80000000); | |
| 260 | try test__fixsfti(-0x1.FFFFFFp+30, -0x80000000); | |
| 261 | try test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 262 | try test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 263 | ||
| 264 | try test__fixsfti(-2.01, -2); | |
| 265 | try test__fixsfti(-2.0, -2); | |
| 266 | try test__fixsfti(-1.99, -1); | |
| 267 | try test__fixsfti(-1.0, -1); | |
| 268 | try test__fixsfti(-0.99, 0); | |
| 269 | try test__fixsfti(-0.5, 0); | |
| 270 | try test__fixsfti(-math.floatMin(f32), 0); | |
| 271 | try test__fixsfti(0.0, 0); | |
| 272 | try test__fixsfti(math.floatMin(f32), 0); | |
| 273 | try test__fixsfti(0.5, 0); | |
| 274 | try test__fixsfti(0.99, 0); | |
| 275 | try test__fixsfti(1.0, 1); | |
| 276 | try test__fixsfti(1.5, 1); | |
| 277 | try test__fixsfti(1.99, 1); | |
| 278 | try test__fixsfti(2.0, 2); | |
| 279 | try test__fixsfti(2.01, 2); | |
| 280 | ||
| 281 | try test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 282 | try test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 283 | try test__fixsfti(0x1.FFFFFFp+30, 0x80000000); | |
| 284 | try test__fixsfti(0x1.000000p+31, 0x80000000); | |
| 285 | ||
| 286 | try test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 287 | try test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 288 | try test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000); | |
| 289 | ||
| 290 | try test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000); | |
| 291 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000); | |
| 292 | try test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 293 | try test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000); | |
| 294 | ||
| 295 | try test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000); | |
| 296 | try test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000); | |
| 297 | try test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 298 | try test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 299 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 300 | try test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 301 | ||
| 302 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 303 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 304 | ||
| 305 | try test__fixsfti(math.floatMax(f32), math.maxInt(i128)); | |
| 306 | } | |
| 307 | ||
| 308 | test "fixunssfti" { | |
| 309 | try test__fixunssfti(0.0, 0); | |
| 310 | ||
| 311 | try test__fixunssfti(0.5, 0); | |
| 312 | try test__fixunssfti(0.99, 0); | |
| 313 | try test__fixunssfti(1.0, 1); | |
| 314 | try test__fixunssfti(1.5, 1); | |
| 315 | try test__fixunssfti(1.99, 1); | |
| 316 | try test__fixunssfti(2.0, 2); | |
| 317 | try test__fixunssfti(2.01, 2); | |
| 318 | try test__fixunssfti(-0.5, 0); | |
| 319 | try test__fixunssfti(-0.99, 0); | |
| 320 | ||
| 321 | try test__fixunssfti(-1.0, 0); | |
| 322 | try test__fixunssfti(-1.5, 0); | |
| 323 | try test__fixunssfti(-1.99, 0); | |
| 324 | try test__fixunssfti(-2.0, 0); | |
| 325 | try test__fixunssfti(-2.01, 0); | |
| 326 | ||
| 327 | try test__fixunssfti(0x1.FFFFFEp+63, 0xFFFFFF0000000000); | |
| 328 | try test__fixunssfti(0x1.000000p+63, 0x8000000000000000); | |
| 329 | try test__fixunssfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 330 | try test__fixunssfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 331 | try test__fixunssfti(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000); | |
| 332 | try test__fixunssfti(0x1.000000p+127, 0x80000000000000000000000000000000); | |
| 333 | try test__fixunssfti(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000); | |
| 334 | try test__fixunssfti(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000); | |
| 335 | ||
| 336 | try test__fixunssfti(-0x1.FFFFFEp+62, 0x0000000000000000); | |
| 337 | try test__fixunssfti(-0x1.FFFFFCp+62, 0x0000000000000000); | |
| 338 | try test__fixunssfti(-0x1.FFFFFEp+126, 0x0000000000000000); | |
| 339 | try test__fixunssfti(-0x1.FFFFFCp+126, 0x0000000000000000); | |
| 340 | try test__fixunssfti(math.floatMax(f32), 0xffffff00000000000000000000000000); | |
| 341 | try test__fixunssfti(math.inf(f32), math.maxInt(u128)); | |
| 342 | } | |
| 343 | ||
| 344 | fn test__fixdfsi(a: f64, expected: i32) !void { | |
| 345 | const x = __fixdfsi(a); | |
| 346 | try testing.expect(x == expected); | |
| 347 | } | |
| 348 | ||
| 349 | fn test__fixunsdfsi(a: f64, expected: u32) !void { | |
| 350 | const x = __fixunsdfsi(a); | |
| 351 | try testing.expect(x == expected); | |
| 352 | } | |
| 353 | ||
| 354 | test "fixdfsi" { | |
| 355 | try test__fixdfsi(-math.floatMax(f64), math.minInt(i32)); | |
| 356 | ||
| 357 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 358 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 359 | ||
| 360 | try test__fixdfsi(-0x1.0000000000000p+127, -0x80000000); | |
| 361 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 362 | try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 363 | ||
| 364 | try test__fixdfsi(-0x1.0000000000001p+63, -0x80000000); | |
| 365 | try test__fixdfsi(-0x1.0000000000000p+63, -0x80000000); | |
| 366 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 367 | try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 368 | ||
| 369 | try test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000); | |
| 370 | try test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000); | |
| 371 | ||
| 372 | try test__fixdfsi(-0x1.000000p+31, -0x80000000); | |
| 373 | try test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 374 | try test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 375 | ||
| 376 | try test__fixdfsi(-2.01, -2); | |
| 377 | try test__fixdfsi(-2.0, -2); | |
| 378 | try test__fixdfsi(-1.99, -1); | |
| 379 | try test__fixdfsi(-1.0, -1); | |
| 380 | try test__fixdfsi(-0.99, 0); | |
| 381 | try test__fixdfsi(-0.5, 0); | |
| 382 | try test__fixdfsi(-math.floatMin(f64), 0); | |
| 383 | try test__fixdfsi(0.0, 0); | |
| 384 | try test__fixdfsi(math.floatMin(f64), 0); | |
| 385 | try test__fixdfsi(0.5, 0); | |
| 386 | try test__fixdfsi(0.99, 0); | |
| 387 | try test__fixdfsi(1.0, 1); | |
| 388 | try test__fixdfsi(1.5, 1); | |
| 389 | try test__fixdfsi(1.99, 1); | |
| 390 | try test__fixdfsi(2.0, 2); | |
| 391 | try test__fixdfsi(2.01, 2); | |
| 392 | ||
| 393 | try test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 394 | try test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 395 | try test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF); | |
| 396 | ||
| 397 | try test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 398 | try test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 399 | ||
| 400 | try test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 401 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 402 | try test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 403 | try test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 404 | ||
| 405 | try test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 406 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 407 | try test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 408 | ||
| 409 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 410 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 411 | ||
| 412 | try test__fixdfsi(math.floatMax(f64), math.maxInt(i32)); | |
| 413 | } | |
| 414 | ||
| 415 | test "fixunsdfsi" { | |
| 416 | try test__fixunsdfsi(0.0, 0); | |
| 417 | ||
| 418 | try test__fixunsdfsi(0.5, 0); | |
| 419 | try test__fixunsdfsi(0.99, 0); | |
| 420 | try test__fixunsdfsi(1.0, 1); | |
| 421 | try test__fixunsdfsi(1.5, 1); | |
| 422 | try test__fixunsdfsi(1.99, 1); | |
| 423 | try test__fixunsdfsi(2.0, 2); | |
| 424 | try test__fixunsdfsi(2.01, 2); | |
| 425 | try test__fixunsdfsi(-0.5, 0); | |
| 426 | try test__fixunsdfsi(-0.99, 0); | |
| 427 | try test__fixunsdfsi(-1.0, 0); | |
| 428 | try test__fixunsdfsi(-1.5, 0); | |
| 429 | try test__fixunsdfsi(-1.99, 0); | |
| 430 | try test__fixunsdfsi(-2.0, 0); | |
| 431 | try test__fixunsdfsi(-2.01, 0); | |
| 432 | ||
| 433 | try test__fixunsdfsi(0x1.000000p+31, 0x80000000); | |
| 434 | try test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF); | |
| 435 | try test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00); | |
| 436 | try test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 437 | try test__fixunsdfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 438 | ||
| 439 | try test__fixunsdfsi(-0x1.FFFFFEp+30, 0); | |
| 440 | try test__fixunsdfsi(-0x1.FFFFFCp+30, 0); | |
| 441 | ||
| 442 | try test__fixunsdfsi(0x1.FFFFFFFEp+31, 0xFFFFFFFF); | |
| 443 | try test__fixunsdfsi(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF); | |
| 444 | try test__fixunsdfsi(0x1.FFFFFFF800000p+30, 0x7FFFFFFE); | |
| 445 | } | |
| 446 | ||
| 447 | fn test__fixdfdi(a: f64, expected: i64) !void { | |
| 448 | const x = __fixdfdi(a); | |
| 449 | try testing.expect(x == expected); | |
| 450 | } | |
| 451 | ||
| 452 | fn test__fixunsdfdi(a: f64, expected: u64) !void { | |
| 453 | const x = __fixunsdfdi(a); | |
| 454 | try testing.expect(x == expected); | |
| 455 | } | |
| 456 | ||
| 457 | test "fixdfdi" { | |
| 458 | try test__fixdfdi(-math.floatMax(f64), math.minInt(i64)); | |
| 459 | ||
| 460 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 461 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 462 | ||
| 463 | try test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 464 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 465 | try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 466 | ||
| 467 | try test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 468 | try test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 469 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 470 | try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 471 | ||
| 472 | try test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 473 | try test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 474 | ||
| 475 | try test__fixdfdi(-2.01, -2); | |
| 476 | try test__fixdfdi(-2.0, -2); | |
| 477 | try test__fixdfdi(-1.99, -1); | |
| 478 | try test__fixdfdi(-1.0, -1); | |
| 479 | try test__fixdfdi(-0.99, 0); | |
| 480 | try test__fixdfdi(-0.5, 0); | |
| 481 | try test__fixdfdi(-math.floatMin(f64), 0); | |
| 482 | try test__fixdfdi(0.0, 0); | |
| 483 | try test__fixdfdi(math.floatMin(f64), 0); | |
| 484 | try test__fixdfdi(0.5, 0); | |
| 485 | try test__fixdfdi(0.99, 0); | |
| 486 | try test__fixdfdi(1.0, 1); | |
| 487 | try test__fixdfdi(1.5, 1); | |
| 488 | try test__fixdfdi(1.99, 1); | |
| 489 | try test__fixdfdi(2.0, 2); | |
| 490 | try test__fixdfdi(2.01, 2); | |
| 491 | ||
| 492 | try test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 493 | try test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 494 | ||
| 495 | try test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 496 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 497 | try test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 498 | try test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 499 | ||
| 500 | try test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 501 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 502 | try test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 503 | ||
| 504 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 505 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 506 | ||
| 507 | try test__fixdfdi(math.floatMax(f64), math.maxInt(i64)); | |
| 508 | } | |
| 509 | ||
| 510 | test "fixunsdfdi" { | |
| 511 | try test__fixunsdfdi(0.0, 0); | |
| 512 | try test__fixunsdfdi(0.5, 0); | |
| 513 | try test__fixunsdfdi(0.99, 0); | |
| 514 | try test__fixunsdfdi(1.0, 1); | |
| 515 | try test__fixunsdfdi(1.5, 1); | |
| 516 | try test__fixunsdfdi(1.99, 1); | |
| 517 | try test__fixunsdfdi(2.0, 2); | |
| 518 | try test__fixunsdfdi(2.01, 2); | |
| 519 | try test__fixunsdfdi(-0.5, 0); | |
| 520 | try test__fixunsdfdi(-0.99, 0); | |
| 521 | try test__fixunsdfdi(-1.0, 0); | |
| 522 | try test__fixunsdfdi(-1.5, 0); | |
| 523 | try test__fixunsdfdi(-1.99, 0); | |
| 524 | try test__fixunsdfdi(-2.0, 0); | |
| 525 | try test__fixunsdfdi(-2.01, 0); | |
| 526 | ||
| 527 | try test__fixunsdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 528 | try test__fixunsdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 529 | ||
| 530 | try test__fixunsdfdi(-0x1.FFFFFEp+62, 0); | |
| 531 | try test__fixunsdfdi(-0x1.FFFFFCp+62, 0); | |
| 532 | ||
| 533 | try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); | |
| 534 | try test__fixunsdfdi(0x1.0000000000000p+63, 0x8000000000000000); | |
| 535 | try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 536 | try test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 537 | ||
| 538 | try test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 539 | try test__fixunsdfdi(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 540 | } | |
| 541 | ||
| 542 | fn test__fixdfti(a: f64, expected: i128) !void { | |
| 543 | const x = __fixdfti(a); | |
| 544 | try testing.expect(x == expected); | |
| 545 | } | |
| 546 | ||
| 547 | fn test__fixunsdfti(a: f64, expected: u128) !void { | |
| 548 | const x = __fixunsdfti(a); | |
| 549 | try testing.expect(x == expected); | |
| 550 | } | |
| 551 | ||
| 552 | test "fixdfti" { | |
| 553 | try test__fixdfti(-math.floatMax(f64), math.minInt(i128)); | |
| 554 | ||
| 555 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 556 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 557 | ||
| 558 | try test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 559 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | |
| 560 | try test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | |
| 561 | ||
| 562 | try test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800); | |
| 563 | try test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 564 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 565 | try test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 566 | ||
| 567 | try test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 568 | try test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 569 | ||
| 570 | try test__fixdfti(-2.01, -2); | |
| 571 | try test__fixdfti(-2.0, -2); | |
| 572 | try test__fixdfti(-1.99, -1); | |
| 573 | try test__fixdfti(-1.0, -1); | |
| 574 | try test__fixdfti(-0.99, 0); | |
| 575 | try test__fixdfti(-0.5, 0); | |
| 576 | try test__fixdfti(-math.floatMin(f64), 0); | |
| 577 | try test__fixdfti(0.0, 0); | |
| 578 | try test__fixdfti(math.floatMin(f64), 0); | |
| 579 | try test__fixdfti(0.5, 0); | |
| 580 | try test__fixdfti(0.99, 0); | |
| 581 | try test__fixdfti(1.0, 1); | |
| 582 | try test__fixdfti(1.5, 1); | |
| 583 | try test__fixdfti(1.99, 1); | |
| 584 | try test__fixdfti(2.0, 2); | |
| 585 | try test__fixdfti(2.01, 2); | |
| 586 | ||
| 587 | try test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 588 | try test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 589 | ||
| 590 | try test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 591 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 592 | try test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 593 | try test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800); | |
| 594 | ||
| 595 | try test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 596 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 597 | try test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 598 | ||
| 599 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 600 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 601 | ||
| 602 | try test__fixdfti(math.floatMax(f64), math.maxInt(i128)); | |
| 603 | } | |
| 604 | ||
| 605 | test "fixunsdfti" { | |
| 606 | try test__fixunsdfti(0.0, 0); | |
| 607 | ||
| 608 | try test__fixunsdfti(0.5, 0); | |
| 609 | try test__fixunsdfti(0.99, 0); | |
| 610 | try test__fixunsdfti(1.0, 1); | |
| 611 | try test__fixunsdfti(1.5, 1); | |
| 612 | try test__fixunsdfti(1.99, 1); | |
| 613 | try test__fixunsdfti(2.0, 2); | |
| 614 | try test__fixunsdfti(2.01, 2); | |
| 615 | try test__fixunsdfti(-0.5, 0); | |
| 616 | try test__fixunsdfti(-0.99, 0); | |
| 617 | try test__fixunsdfti(-1.0, 0); | |
| 618 | try test__fixunsdfti(-1.5, 0); | |
| 619 | try test__fixunsdfti(-1.99, 0); | |
| 620 | try test__fixunsdfti(-2.0, 0); | |
| 621 | try test__fixunsdfti(-2.01, 0); | |
| 622 | ||
| 623 | try test__fixunsdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 624 | try test__fixunsdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 625 | ||
| 626 | try test__fixunsdfti(-0x1.FFFFFEp+62, 0); | |
| 627 | try test__fixunsdfti(-0x1.FFFFFCp+62, 0); | |
| 628 | ||
| 629 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); | |
| 630 | try test__fixunsdfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 631 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 632 | try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 633 | ||
| 634 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000); | |
| 635 | try test__fixunsdfti(0x1.0000000000000p+127, 0x80000000000000000000000000000000); | |
| 636 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 637 | try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 638 | try test__fixunsdfti(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 639 | ||
| 640 | try test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 641 | try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 642 | } | |
| 643 | ||
| 644 | fn test__fixtfsi(a: f128, expected: i32) !void { | |
| 645 | const x = __fixtfsi(a); | |
| 646 | try testing.expect(x == expected); | |
| 647 | } | |
| 648 | ||
| 649 | fn test__fixunstfsi(a: f128, expected: u32) !void { | |
| 650 | const x = __fixunstfsi(a); | |
| 651 | try testing.expect(x == expected); | |
| 652 | } | |
| 653 | ||
| 654 | test "fixtfsi" { | |
| 655 | try test__fixtfsi(-math.floatMax(f128), math.minInt(i32)); | |
| 656 | ||
| 657 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 658 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 659 | ||
| 660 | try test__fixtfsi(-0x1.0000000000000p+127, -0x80000000); | |
| 661 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 662 | try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 663 | ||
| 664 | try test__fixtfsi(-0x1.0000000000001p+63, -0x80000000); | |
| 665 | try test__fixtfsi(-0x1.0000000000000p+63, -0x80000000); | |
| 666 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 667 | try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 668 | ||
| 669 | try test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000); | |
| 670 | try test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000); | |
| 671 | ||
| 672 | try test__fixtfsi(-0x1.000000p+31, -0x80000000); | |
| 673 | try test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 674 | try test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 675 | try test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 676 | ||
| 677 | try test__fixtfsi(-2.01, -2); | |
| 678 | try test__fixtfsi(-2.0, -2); | |
| 679 | try test__fixtfsi(-1.99, -1); | |
| 680 | try test__fixtfsi(-1.0, -1); | |
| 681 | try test__fixtfsi(-0.99, 0); | |
| 682 | try test__fixtfsi(-0.5, 0); | |
| 683 | try test__fixtfsi(-math.floatMin(f32), 0); | |
| 684 | try test__fixtfsi(0.0, 0); | |
| 685 | try test__fixtfsi(math.floatMin(f32), 0); | |
| 686 | try test__fixtfsi(0.5, 0); | |
| 687 | try test__fixtfsi(0.99, 0); | |
| 688 | try test__fixtfsi(1.0, 1); | |
| 689 | try test__fixtfsi(1.5, 1); | |
| 690 | try test__fixtfsi(1.99, 1); | |
| 691 | try test__fixtfsi(2.0, 2); | |
| 692 | try test__fixtfsi(2.01, 2); | |
| 693 | ||
| 694 | try test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 695 | try test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 696 | try test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 697 | try test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF); | |
| 698 | ||
| 699 | try test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 700 | try test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 701 | ||
| 702 | try test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 703 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 704 | try test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 705 | try test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 706 | ||
| 707 | try test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 708 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 709 | try test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 710 | ||
| 711 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 712 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 713 | ||
| 714 | try test__fixtfsi(math.floatMax(f128), math.maxInt(i32)); | |
| 715 | } | |
| 716 | ||
| 717 | test "fixunstfsi" { | |
| 718 | try test__fixunstfsi(math.inf(f128), 0xffffffff); | |
| 719 | try test__fixunstfsi(0, 0x0); | |
| 720 | try test__fixunstfsi(0x1.23456789abcdefp+5, 0x24); | |
| 721 | try test__fixunstfsi(0x1.23456789abcdefp-3, 0x0); | |
| 722 | try test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456); | |
| 723 | try test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff); | |
| 724 | try test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff); | |
| 725 | try test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0); | |
| 726 | ||
| 727 | try test__fixunstfsi(0x1p+32, 0xFFFFFFFF); | |
| 728 | } | |
| 729 | ||
| 730 | fn test__fixtfdi(a: f128, expected: i64) !void { | |
| 731 | const x = __fixtfdi(a); | |
| 732 | try testing.expect(x == expected); | |
| 733 | } | |
| 734 | ||
| 735 | fn test__fixunstfdi(a: f128, expected: u64) !void { | |
| 736 | const x = __fixunstfdi(a); | |
| 737 | try testing.expect(x == expected); | |
| 738 | } | |
| 739 | ||
| 740 | test "fixtfdi" { | |
| 741 | try test__fixtfdi(-math.floatMax(f128), math.minInt(i64)); | |
| 742 | ||
| 743 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 744 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 745 | ||
| 746 | try test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 747 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 748 | try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 749 | ||
| 750 | try test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 751 | try test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 752 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 753 | try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 754 | ||
| 755 | try test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000); | |
| 756 | try test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000); | |
| 757 | ||
| 758 | try test__fixtfdi(-0x1.000000p+31, -0x80000000); | |
| 759 | try test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 760 | try test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 761 | try test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 762 | ||
| 763 | try test__fixtfdi(-2.01, -2); | |
| 764 | try test__fixtfdi(-2.0, -2); | |
| 765 | try test__fixtfdi(-1.99, -1); | |
| 766 | try test__fixtfdi(-1.0, -1); | |
| 767 | try test__fixtfdi(-0.99, 0); | |
| 768 | try test__fixtfdi(-0.5, 0); | |
| 769 | try test__fixtfdi(-math.floatMin(f64), 0); | |
| 770 | try test__fixtfdi(0.0, 0); | |
| 771 | try test__fixtfdi(math.floatMin(f64), 0); | |
| 772 | try test__fixtfdi(0.5, 0); | |
| 773 | try test__fixtfdi(0.99, 0); | |
| 774 | try test__fixtfdi(1.0, 1); | |
| 775 | try test__fixtfdi(1.5, 1); | |
| 776 | try test__fixtfdi(1.99, 1); | |
| 777 | try test__fixtfdi(2.0, 2); | |
| 778 | try test__fixtfdi(2.01, 2); | |
| 779 | ||
| 780 | try test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 781 | try test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 782 | try test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 783 | try test__fixtfdi(0x1.000000p+31, 0x80000000); | |
| 784 | ||
| 785 | try test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 786 | try test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 787 | ||
| 788 | try test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 789 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 790 | try test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 791 | try test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 792 | ||
| 793 | try test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 794 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 795 | try test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 796 | ||
| 797 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 798 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 799 | ||
| 800 | try test__fixtfdi(math.floatMax(f128), math.maxInt(i64)); | |
| 801 | } | |
| 802 | ||
| 803 | test "fixunstfdi" { | |
| 804 | try test__fixunstfdi(0.0, 0); | |
| 805 | ||
| 806 | try test__fixunstfdi(0.5, 0); | |
| 807 | try test__fixunstfdi(0.99, 0); | |
| 808 | try test__fixunstfdi(1.0, 1); | |
| 809 | try test__fixunstfdi(1.5, 1); | |
| 810 | try test__fixunstfdi(1.99, 1); | |
| 811 | try test__fixunstfdi(2.0, 2); | |
| 812 | try test__fixunstfdi(2.01, 2); | |
| 813 | try test__fixunstfdi(-0.5, 0); | |
| 814 | try test__fixunstfdi(-0.99, 0); | |
| 815 | try test__fixunstfdi(-1.0, 0); | |
| 816 | try test__fixunstfdi(-1.5, 0); | |
| 817 | try test__fixunstfdi(-1.99, 0); | |
| 818 | try test__fixunstfdi(-2.0, 0); | |
| 819 | try test__fixunstfdi(-2.01, 0); | |
| 820 | ||
| 821 | try test__fixunstfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 822 | try test__fixunstfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 823 | ||
| 824 | try test__fixunstfdi(-0x1.FFFFFEp+62, 0); | |
| 825 | try test__fixunstfdi(-0x1.FFFFFCp+62, 0); | |
| 826 | ||
| 827 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 828 | try test__fixunstfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 829 | ||
| 830 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 831 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 832 | ||
| 833 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); | |
| 834 | try test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001); | |
| 835 | try test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000); | |
| 836 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); | |
| 837 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); | |
| 838 | try test__fixunstfdi(0x1p+64, 0xFFFFFFFFFFFFFFFF); | |
| 839 | ||
| 840 | try test__fixunstfdi(-0x1.0000000000000000p+63, 0); | |
| 841 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0); | |
| 842 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0); | |
| 843 | } | |
| 844 | ||
| 845 | fn test__fixtfti(a: f128, expected: i128) !void { | |
| 846 | const x = __fixtfti(a); | |
| 847 | try testing.expect(x == expected); | |
| 848 | } | |
| 849 | ||
| 850 | fn test__fixunstfti(a: f128, expected: u128) !void { | |
| 851 | const x = __fixunstfti(a); | |
| 852 | try testing.expect(x == expected); | |
| 853 | } | |
| 854 | ||
| 855 | test "fixtfti" { | |
| 856 | try test__fixtfti(-math.floatMax(f128), math.minInt(i128)); | |
| 857 | ||
| 858 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 859 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 860 | ||
| 861 | try test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 862 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | |
| 863 | try test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | |
| 864 | ||
| 865 | try test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800); | |
| 866 | try test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 867 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 868 | try test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 869 | ||
| 870 | try test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 871 | try test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 872 | ||
| 873 | try test__fixtfti(-2.01, -2); | |
| 874 | try test__fixtfti(-2.0, -2); | |
| 875 | try test__fixtfti(-1.99, -1); | |
| 876 | try test__fixtfti(-1.0, -1); | |
| 877 | try test__fixtfti(-0.99, 0); | |
| 878 | try test__fixtfti(-0.5, 0); | |
| 879 | try test__fixtfti(-math.floatMin(f128), 0); | |
| 880 | try test__fixtfti(0.0, 0); | |
| 881 | try test__fixtfti(math.floatMin(f128), 0); | |
| 882 | try test__fixtfti(0.5, 0); | |
| 883 | try test__fixtfti(0.99, 0); | |
| 884 | try test__fixtfti(1.0, 1); | |
| 885 | try test__fixtfti(1.5, 1); | |
| 886 | try test__fixtfti(1.99, 1); | |
| 887 | try test__fixtfti(2.0, 2); | |
| 888 | try test__fixtfti(2.01, 2); | |
| 889 | ||
| 890 | try test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 891 | try test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 892 | ||
| 893 | try test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 894 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 895 | try test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 896 | try test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800); | |
| 897 | ||
| 898 | try test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 899 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 900 | try test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 901 | ||
| 902 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 903 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 904 | ||
| 905 | try test__fixtfti(math.floatMax(f128), math.maxInt(i128)); | |
| 906 | } | |
| 907 | ||
| 908 | test "fixunstfti" { | |
| 909 | try test__fixunstfti(math.inf(f128), 0xffffffffffffffffffffffffffffffff); | |
| 910 | ||
| 911 | try test__fixunstfti(0.0, 0); | |
| 912 | ||
| 913 | try test__fixunstfti(0.5, 0); | |
| 914 | try test__fixunstfti(0.99, 0); | |
| 915 | try test__fixunstfti(1.0, 1); | |
| 916 | try test__fixunstfti(1.5, 1); | |
| 917 | try test__fixunstfti(1.99, 1); | |
| 918 | try test__fixunstfti(2.0, 2); | |
| 919 | try test__fixunstfti(2.01, 2); | |
| 920 | try test__fixunstfti(-0.01, 0); | |
| 921 | try test__fixunstfti(-0.99, 0); | |
| 922 | ||
| 923 | try test__fixunstfti(0x1p+128, 0xffffffffffffffffffffffffffffffff); | |
| 924 | ||
| 925 | try test__fixunstfti(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000); | |
| 926 | try test__fixunstfti(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000); | |
| 927 | try test__fixunstfti(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff); | |
| 928 | try test__fixunstfti(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff); | |
| 929 | } | |
| 930 | ||
| 931 | fn test__fixunshfti(a: f16, expected: u128) !void { | |
| 932 | const x = __fixunshfti(a); | |
| 933 | try testing.expect(x == expected); | |
| 934 | } | |
| 935 | ||
| 936 | test "fixunshfti for f16" { | |
| 937 | try test__fixunshfti(math.inf(f16), math.maxInt(u128)); | |
| 938 | try test__fixunshfti(math.floatMax(f16), 65504); | |
| 939 | } | |
| 940 | ||
| 941 | fn test__fixunsxfti(a: f80, expected: u128) !void { | |
| 942 | const x = __fixunsxfti(a); | |
| 943 | try testing.expect(x == expected); | |
| 944 | } | |
| 945 | ||
| 946 | test "fixunsxfti for f80" { | |
| 947 | try test__fixunsxfti(math.inf(f80), math.maxInt(u128)); | |
| 948 | try test__fixunsxfti(math.floatMax(f80), math.maxInt(u128)); | |
| 949 | try test__fixunsxfti(math.maxInt(u64), math.maxInt(u64)); | |
| 950 | } |
lib/compiler_rt/floatdidf.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__floatdidf, .{ .name = "__floatdidf", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __floatdidf(a: i64) callconv(.C) f64 { | |
| 15 | return intToFloat(f64, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_l2d(a: i64) callconv(.AAPCS) f64 { | |
| 19 | return intToFloat(f64, a); | |
| 20 | } |
lib/compiler_rt/floatdihf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatdihf, .{ .name = "__floatdihf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floatdihf(a: i64) callconv(.C) f16 { | |
| 11 | return intToFloat(f16, a); | |
| 12 | } |
lib/compiler_rt/floatdisf.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__floatdisf, .{ .name = "__floatdisf", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __floatdisf(a: i64) callconv(.C) f32 { | |
| 15 | return intToFloat(f32, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_l2f(a: i64) callconv(.AAPCS) f32 { | |
| 19 | return intToFloat(f32, a); | |
| 20 | } |
lib/compiler_rt/floatditf.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__floatdikf, .{ .name = "__floatdikf", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_xtoq, .{ .name = "_Qp_xtoq", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__floatditf, .{ .name = "__floatditf", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __floatditf(a: i64) callconv(.C) f128 { | |
| 17 | return intToFloat(f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __floatdikf(a: i64) callconv(.C) f128 { | |
| 21 | return intToFloat(f128, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_xtoq(c: *f128, a: i64) callconv(.C) void { | |
| 25 | c.* = intToFloat(f128, a); | |
| 26 | } |
lib/compiler_rt/floatdixf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatdixf, .{ .name = "__floatdixf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floatdixf(a: i64) callconv(.C) f80 { | |
| 11 | return intToFloat(f80, a); | |
| 12 | } |
lib/compiler_rt/floatsidf.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__floatsidf, .{ .name = "__floatsidf", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __floatsidf(a: i32) callconv(.C) f64 { | |
| 15 | return intToFloat(f64, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_i2d(a: i32) callconv(.AAPCS) f64 { | |
| 19 | return intToFloat(f64, a); | |
| 20 | } |
lib/compiler_rt/floatsihf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatsihf, .{ .name = "__floatsihf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floatsihf(a: i32) callconv(.C) f16 { | |
| 11 | return intToFloat(f16, a); | |
| 12 | } |
lib/compiler_rt/floatsisf.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_i2f, .{ .name = "__aeabi_i2f", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__floatsisf, .{ .name = "__floatsisf", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __floatsisf(a: i32) callconv(.C) f32 { | |
| 15 | return intToFloat(f32, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_i2f(a: i32) callconv(.AAPCS) f32 { | |
| 19 | return intToFloat(f32, a); | |
| 20 | } |
lib/compiler_rt/floatsitf.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__floatsikf, .{ .name = "__floatsikf", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_itoq, .{ .name = "_Qp_itoq", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__floatsitf, .{ .name = "__floatsitf", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __floatsitf(a: i32) callconv(.C) f128 { | |
| 17 | return intToFloat(f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __floatsikf(a: i32) callconv(.C) f128 { | |
| 21 | return intToFloat(f128, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_itoq(c: *f128, a: i32) callconv(.C) void { | |
| 25 | c.* = intToFloat(f128, a); | |
| 26 | } |
lib/compiler_rt/floatsixf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatsixf, .{ .name = "__floatsixf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floatsixf(a: i32) callconv(.C) f80 { | |
| 11 | return intToFloat(f80, a); | |
| 12 | } |
lib/compiler_rt/floattidf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floattidf, .{ .name = "__floattidf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floattidf(a: i128) callconv(.C) f64 { | |
| 11 | return intToFloat(f64, a); | |
| 12 | } |
lib/compiler_rt/floattihf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floattihf, .{ .name = "__floattihf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floattihf(a: i128) callconv(.C) f16 { | |
| 11 | return intToFloat(f16, a); | |
| 12 | } |
lib/compiler_rt/floattisf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floattisf, .{ .name = "__floattisf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floattisf(a: i128) callconv(.C) f32 { | |
| 11 | return intToFloat(f32, a); | |
| 12 | } |
lib/compiler_rt/floattitf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floattitf, .{ .name = "__floattitf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floattitf(a: i128) callconv(.C) f128 { | |
| 11 | return intToFloat(f128, a); | |
| 12 | } |
lib/compiler_rt/floattixf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floattixf, .{ .name = "__floattixf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floattixf(a: i128) callconv(.C) f80 { | |
| 11 | return intToFloat(f80, a); | |
| 12 | } |
lib/compiler_rt/floatundidf.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_ul2d, .{ .name = "__aeabi_ul2d", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__floatundidf, .{ .name = "__floatundidf", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __floatundidf(a: u64) callconv(.C) f64 { | |
| 15 | return intToFloat(f64, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_ul2d(a: u64) callconv(.AAPCS) f64 { | |
| 19 | return intToFloat(f64, a); | |
| 20 | } |
lib/compiler_rt/floatundihf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatundihf, .{ .name = "__floatundihf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floatundihf(a: u64) callconv(.C) f16 { | |
| 11 | return intToFloat(f16, a); | |
| 12 | } |
lib/compiler_rt/floatundisf.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_ul2f, .{ .name = "__aeabi_ul2f", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__floatundisf, .{ .name = "__floatundisf", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __floatundisf(a: u64) callconv(.C) f32 { | |
| 15 | return intToFloat(f32, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_ul2f(a: u64) callconv(.AAPCS) f32 { | |
| 19 | return intToFloat(f32, a); | |
| 20 | } |
lib/compiler_rt/floatunditf.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__floatundikf, .{ .name = "__floatundikf", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_uxtoq, .{ .name = "_Qp_uxtoq", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__floatunditf, .{ .name = "__floatunditf", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __floatunditf(a: u64) callconv(.C) f128 { | |
| 17 | return intToFloat(f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __floatundikf(a: u64) callconv(.C) f128 { | |
| 21 | return intToFloat(f128, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_uxtoq(c: *f128, a: u64) callconv(.C) void { | |
| 25 | c.* = intToFloat(f128, a); | |
| 26 | } |
lib/compiler_rt/floatundixf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatundixf, .{ .name = "__floatundixf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floatundixf(a: u64) callconv(.C) f80 { | |
| 11 | return intToFloat(f80, a); | |
| 12 | } |
lib/compiler_rt/floatunsidf.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_ui2d, .{ .name = "__aeabi_ui2d", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__floatunsidf, .{ .name = "__floatunsidf", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __floatunsidf(a: u32) callconv(.C) f64 { | |
| 15 | return intToFloat(f64, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_ui2d(a: u32) callconv(.AAPCS) f64 { | |
| 19 | return intToFloat(f64, a); | |
| 20 | } |
lib/compiler_rt/floatunsihf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatunsihf, .{ .name = "__floatunsihf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floatunsihf(a: u32) callconv(.C) f16 { | |
| 11 | return intToFloat(f16, a); | |
| 12 | } |
lib/compiler_rt/floatunsisf.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_ui2f, .{ .name = "__aeabi_ui2f", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__floatunsisf, .{ .name = "__floatunsisf", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __floatunsisf(a: u32) callconv(.C) f32 { | |
| 15 | return intToFloat(f32, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_ui2f(a: u32) callconv(.AAPCS) f32 { | |
| 19 | return intToFloat(f32, a); | |
| 20 | } |
lib/compiler_rt/floatunsitf.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__floatunsikf, .{ .name = "__floatunsikf", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_uitoq, .{ .name = "_Qp_uitoq", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __floatunsitf(a: u32) callconv(.C) f128 { | |
| 17 | return intToFloat(f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __floatunsikf(a: u32) callconv(.C) f128 { | |
| 21 | return intToFloat(f128, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_uitoq(c: *f128, a: u32) callconv(.C) void { | |
| 25 | c.* = intToFloat(f128, a); | |
| 26 | } |
lib/compiler_rt/floatunsixf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatunsixf, .{ .name = "__floatunsixf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floatunsixf(a: u32) callconv(.C) f80 { | |
| 11 | return intToFloat(f80, a); | |
| 12 | } |
lib/compiler_rt/floatuntidf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floatuntidf(a: u128) callconv(.C) f64 { | |
| 11 | return intToFloat(f64, a); | |
| 12 | } |
lib/compiler_rt/floatuntihf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatuntihf, .{ .name = "__floatuntihf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __floatuntihf(a: u128) callconv(.C) f16 { | |
| 11 | return intToFloat(f16, a); | |
| 12 | } |
lib/compiler_rt/floatuntisf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floatuntisf(a: u128) callconv(.C) f32 { | |
| 11 | return intToFloat(f32, a); | |
| 12 | } |
lib/compiler_rt/floatuntitf.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__floatuntikf, .{ .name = "__floatuntikf", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __floatuntitf(a: u128) callconv(.C) f128 { | |
| 15 | return intToFloat(f128, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __floatuntikf(a: u128) callconv(.C) f128 { | |
| 19 | return intToFloat(f128, a); | |
| 20 | } |
lib/compiler_rt/floatuntixf.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__floatuntixf, .{ .name = "__floatuntixf", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floatuntixf(a: u128) callconv(.C) f80 { | |
| 11 | return intToFloat(f80, a); | |
| 12 | } |
lib/compiler_rt/floor.zig+20-5| ... | ... | @@ -1,12 +1,27 @@ |
| 1 | // Ported from musl, which is licensed under the MIT license: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c | |
| 1 | //! Ported from musl, which is licensed under the MIT license: | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 8 | 9 | const math = std.math; |
| 9 | 10 | const expect = std.testing.expect; |
| 11 | const arch = builtin.cpu.arch; | |
| 12 | const common = @import("common.zig"); | |
| 13 | ||
| 14 | pub const panic = common.panic; | |
| 15 | ||
| 16 | comptime { | |
| 17 | @export(__floorh, .{ .name = "__floorh", .linkage = common.linkage }); | |
| 18 | @export(floorf, .{ .name = "floorf", .linkage = common.linkage }); | |
| 19 | @export(floor, .{ .name = "floor", .linkage = common.linkage }); | |
| 20 | @export(__floorx, .{ .name = "__floorx", .linkage = common.linkage }); | |
| 21 | const floorq_sym_name = if (common.want_ppc_abi) "floorf128" else "floorq"; | |
| 22 | @export(floorq, .{ .name = floorq_sym_name, .linkage = common.linkage }); | |
| 23 | @export(floorl, .{ .name = "floorl", .linkage = common.linkage }); | |
| 24 | } | |
| 10 | 25 | |
| 11 | 26 | pub fn __floorh(x: f16) callconv(.C) f16 { |
| 12 | 27 | var u = @bitCast(u16, x); |
lib/compiler_rt/fma.zig+21-6| ... | ... | @@ -1,13 +1,28 @@ |
| 1 | // Ported from musl, which is MIT licensed: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/fmal.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/fmaf.c | |
| 6 | // https://git.musl-libc.org/cgit/musl/tree/src/math/fma.c | |
| 1 | //! Ported from musl, which is MIT licensed: | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/fmal.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/fmaf.c | |
| 6 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/fma.c | |
| 7 | 7 | |
| 8 | 8 | const std = @import("std"); |
| 9 | const builtin = @import("builtin"); | |
| 9 | 10 | const math = std.math; |
| 10 | 11 | const expect = std.testing.expect; |
| 12 | const arch = builtin.cpu.arch; | |
| 13 | const common = @import("common.zig"); | |
| 14 | ||
| 15 | pub const panic = common.panic; | |
| 16 | ||
| 17 | comptime { | |
| 18 | @export(__fmah, .{ .name = "__fmah", .linkage = common.linkage }); | |
| 19 | @export(fmaf, .{ .name = "fmaf", .linkage = common.linkage }); | |
| 20 | @export(fma, .{ .name = "fma", .linkage = common.linkage }); | |
| 21 | @export(__fmax, .{ .name = "__fmax", .linkage = common.linkage }); | |
| 22 | const fmaq_sym_name = if (common.want_ppc_abi) "fmaf128" else "fmaq"; | |
| 23 | @export(fmaq, .{ .name = fmaq_sym_name, .linkage = common.linkage }); | |
| 24 | @export(fmal, .{ .name = "fmal", .linkage = common.linkage }); | |
| 25 | } | |
| 11 | 26 | |
| 12 | 27 | pub fn __fmah(x: f16, y: f16, z: f16) callconv(.C) f16 { |
| 13 | 28 | // TODO: more efficient implementation |
lib/compiler_rt/fmax.zig+15| ... | ... | @@ -1,5 +1,20 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | const math = std.math; |
| 4 | const arch = builtin.cpu.arch; | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | @export(__fmaxh, .{ .name = "__fmaxh", .linkage = common.linkage }); | |
| 11 | @export(fmaxf, .{ .name = "fmaxf", .linkage = common.linkage }); | |
| 12 | @export(fmax, .{ .name = "fmax", .linkage = common.linkage }); | |
| 13 | @export(__fmaxx, .{ .name = "__fmaxx", .linkage = common.linkage }); | |
| 14 | const fmaxq_sym_name = if (common.want_ppc_abi) "fmaxf128" else "fmaxq"; | |
| 15 | @export(fmaxq, .{ .name = fmaxq_sym_name, .linkage = common.linkage }); | |
| 16 | @export(fmaxl, .{ .name = "fmaxl", .linkage = common.linkage }); | |
| 17 | } | |
| 3 | 18 | |
| 4 | 19 | pub fn __fmaxh(x: f16, y: f16) callconv(.C) f16 { |
| 5 | 20 | return generic_fmax(f16, x, y); |
lib/compiler_rt/fmin.zig+15| ... | ... | @@ -1,5 +1,20 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | const math = std.math; |
| 4 | const arch = builtin.cpu.arch; | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | @export(__fminh, .{ .name = "__fminh", .linkage = common.linkage }); | |
| 11 | @export(fminf, .{ .name = "fminf", .linkage = common.linkage }); | |
| 12 | @export(fmin, .{ .name = "fmin", .linkage = common.linkage }); | |
| 13 | @export(__fminx, .{ .name = "__fminx", .linkage = common.linkage }); | |
| 14 | const fminq_sym_name = if (common.want_ppc_abi) "fminf128" else "fminq"; | |
| 15 | @export(fminq, .{ .name = fminq_sym_name, .linkage = common.linkage }); | |
| 16 | @export(fminl, .{ .name = "fminl", .linkage = common.linkage }); | |
| 17 | } | |
| 3 | 18 | |
| 4 | 19 | pub fn __fminh(x: f16, y: f16) callconv(.C) f16 { |
| 5 | 20 | return generic_fmin(f16, x, y); |
lib/compiler_rt/fmod.zig+15-6| ... | ... | @@ -2,7 +2,21 @@ const builtin = @import("builtin"); |
| 2 | 2 | const std = @import("std"); |
| 3 | 3 | const math = std.math; |
| 4 | 4 | const assert = std.debug.assert; |
| 5 | const normalize = @import("divdf3.zig").normalize; | |
| 5 | const arch = builtin.cpu.arch; | |
| 6 | const common = @import("common.zig"); | |
| 7 | const normalize = common.normalize; | |
| 8 | ||
| 9 | pub const panic = common.panic; | |
| 10 | ||
| 11 | comptime { | |
| 12 | @export(__fmodh, .{ .name = "__fmodh", .linkage = common.linkage }); | |
| 13 | @export(fmodf, .{ .name = "fmodf", .linkage = common.linkage }); | |
| 14 | @export(fmod, .{ .name = "fmod", .linkage = common.linkage }); | |
| 15 | @export(__fmodx, .{ .name = "__fmodx", .linkage = common.linkage }); | |
| 16 | const fmodq_sym_name = if (common.want_ppc_abi) "fmodf128" else "fmodq"; | |
| 17 | @export(fmodq, .{ .name = fmodq_sym_name, .linkage = common.linkage }); | |
| 18 | @export(fmodl, .{ .name = "fmodl", .linkage = common.linkage }); | |
| 19 | } | |
| 6 | 20 | |
| 7 | 21 | pub fn __fmodh(x: f16, y: f16) callconv(.C) f16 { |
| 8 | 22 | // TODO: more efficient implementation |
| ... | ... | @@ -20,8 +34,6 @@ pub fn fmod(x: f64, y: f64) callconv(.C) f64 { |
| 20 | 34 | /// fmodx - floating modulo large, returns the remainder of division for f80 types |
| 21 | 35 | /// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits |
| 22 | 36 | pub fn __fmodx(a: f80, b: f80) callconv(.C) f80 { |
| 23 | @setRuntimeSafety(builtin.is_test); | |
| 24 | ||
| 25 | 37 | const T = f80; |
| 26 | 38 | const Z = std.meta.Int(.unsigned, @bitSizeOf(T)); |
| 27 | 39 | |
| ... | ... | @@ -120,7 +132,6 @@ pub fn __fmodx(a: f80, b: f80) callconv(.C) f80 { |
| 120 | 132 | /// fmodq - floating modulo large, returns the remainder of division for f128 types |
| 121 | 133 | /// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits |
| 122 | 134 | pub fn fmodq(a: f128, b: f128) callconv(.C) f128 { |
| 123 | @setRuntimeSafety(builtin.is_test); | |
| 124 | 135 | var amod = a; |
| 125 | 136 | var bmod = b; |
| 126 | 137 | const aPtr_u64 = @ptrCast([*]u64, &amod); |
| ... | ... | @@ -249,8 +260,6 @@ pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.C) c_longdouble { |
| 249 | 260 | } |
| 250 | 261 | |
| 251 | 262 | inline fn generic_fmod(comptime T: type, x: T, y: T) T { |
| 252 | @setRuntimeSafety(false); | |
| 253 | ||
| 254 | 263 | const bits = @typeInfo(T).Float.bits; |
| 255 | 264 | const uint = std.meta.Int(.unsigned, bits); |
| 256 | 265 | const log2uint = math.Log2Int(uint); |
lib/compiler_rt/gedf2.zig created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | ///! The quoted behavior definitions are from | |
| 2 | ///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines | |
| 3 | const common = @import("./common.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | if (common.want_aeabi) { | |
| 10 | @export(__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = common.linkage }); | |
| 11 | @export(__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = common.linkage }); | |
| 12 | } else { | |
| 13 | @export(__gedf2, .{ .name = "__gedf2", .linkage = common.linkage }); | |
| 14 | @export(__gtdf2, .{ .name = "__gtdf2", .linkage = common.linkage }); | |
| 15 | } | |
| 16 | } | |
| 17 | ||
| 18 | /// "These functions return a value greater than or equal to zero if neither | |
| 19 | /// argument is NaN, and a is greater than or equal to b." | |
| 20 | pub fn __gedf2(a: f64, b: f64) callconv(.C) i32 { | |
| 21 | return @enumToInt(comparef.cmpf2(f64, comparef.GE, a, b)); | |
| 22 | } | |
| 23 | ||
| 24 | /// "These functions return a value greater than zero if neither argument is NaN, | |
| 25 | /// and a is strictly greater than b." | |
| 26 | pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 { | |
| 27 | return __gedf2(a, b); | |
| 28 | } | |
| 29 | ||
| 30 | fn __aeabi_dcmpge(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 31 | return @boolToInt(comparef.cmpf2(f64, comparef.GE, a, b) != .Less); | |
| 32 | } | |
| 33 | ||
| 34 | fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 35 | return @boolToInt(comparef.cmpf2(f64, comparef.GE, a, b) == .Greater); | |
| 36 | } |
lib/compiler_rt/gesf2.zig created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | ///! The quoted behavior definitions are from | |
| 2 | ///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines | |
| 3 | const common = @import("./common.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | if (common.want_aeabi) { | |
| 10 | @export(__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = common.linkage }); | |
| 11 | @export(__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = common.linkage }); | |
| 12 | } else { | |
| 13 | @export(__gesf2, .{ .name = "__gesf2", .linkage = common.linkage }); | |
| 14 | @export(__gtsf2, .{ .name = "__gtsf2", .linkage = common.linkage }); | |
| 15 | } | |
| 16 | } | |
| 17 | ||
| 18 | /// "These functions return a value greater than or equal to zero if neither | |
| 19 | /// argument is NaN, and a is greater than or equal to b." | |
| 20 | pub fn __gesf2(a: f32, b: f32) callconv(.C) i32 { | |
| 21 | return @enumToInt(comparef.cmpf2(f32, comparef.GE, a, b)); | |
| 22 | } | |
| 23 | ||
| 24 | /// "These functions return a value greater than zero if neither argument is NaN, | |
| 25 | /// and a is strictly greater than b." | |
| 26 | pub fn __gtsf2(a: f32, b: f32) callconv(.C) i32 { | |
| 27 | return __gesf2(a, b); | |
| 28 | } | |
| 29 | ||
| 30 | fn __aeabi_fcmpge(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 31 | return @boolToInt(comparef.cmpf2(f32, comparef.GE, a, b) != .Less); | |
| 32 | } | |
| 33 | ||
| 34 | fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 35 | return @boolToInt(comparef.cmpf2(f32, comparef.LE, a, b) == .Greater); | |
| 36 | } |
lib/compiler_rt/getf2.zig created+39| ... | ... | @@ -0,0 +1,39 @@ |
| 1 | ///! The quoted behavior definitions are from | |
| 2 | ///! https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gccint/Soft-float-library-routines.html#Soft-float-library-routines | |
| 3 | const common = @import("./common.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | if (common.want_ppc_abi) { | |
| 10 | @export(__gekf2, .{ .name = "__gekf2", .linkage = common.linkage }); | |
| 11 | @export(__gtkf2, .{ .name = "__gtkf2", .linkage = common.linkage }); | |
| 12 | } else if (common.want_sparc_abi) { | |
| 13 | // These exports are handled in cmptf2.zig because gt and ge on sparc | |
| 14 | // are based on calling _Qp_cmp. | |
| 15 | } else { | |
| 16 | @export(__getf2, .{ .name = "__getf2", .linkage = common.linkage }); | |
| 17 | @export(__gttf2, .{ .name = "__gttf2", .linkage = common.linkage }); | |
| 18 | } | |
| 19 | } | |
| 20 | ||
| 21 | /// "These functions return a value greater than or equal to zero if neither | |
| 22 | /// argument is NaN, and a is greater than or equal to b." | |
| 23 | fn __getf2(a: f128, b: f128) callconv(.C) i32 { | |
| 24 | return @enumToInt(comparef.cmpf2(f128, comparef.GE, a, b)); | |
| 25 | } | |
| 26 | ||
| 27 | /// "These functions return a value greater than zero if neither argument is NaN, | |
| 28 | /// and a is strictly greater than b." | |
| 29 | fn __gttf2(a: f128, b: f128) callconv(.C) i32 { | |
| 30 | return __getf2(a, b); | |
| 31 | } | |
| 32 | ||
| 33 | fn __gekf2(a: f128, b: f128) callconv(.C) i32 { | |
| 34 | return __getf2(a, b); | |
| 35 | } | |
| 36 | ||
| 37 | fn __gtkf2(a: f128, b: f128) callconv(.C) i32 { | |
| 38 | return __getf2(a, b); | |
| 39 | } |
lib/compiler_rt/gexf2.zig created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const comparef = @import("./comparef.zig"); | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__gexf2, .{ .name = "__gexf2", .linkage = common.linkage }); | |
| 8 | @export(__gtxf2, .{ .name = "__gtxf2", .linkage = common.linkage }); | |
| 9 | } | |
| 10 | ||
| 11 | fn __gexf2(a: f80, b: f80) callconv(.C) i32 { | |
| 12 | return @enumToInt(comparef.cmp_f80(comparef.GE, a, b)); | |
| 13 | } | |
| 14 | ||
| 15 | fn __gtxf2(a: f80, b: f80) callconv(.C) i32 { | |
| 16 | return __gexf2(a, b); | |
| 17 | } |
lib/compiler_rt/int.zig+42-24| ... | ... | @@ -1,22 +1,45 @@ |
| 1 | // Builtin functions that operate on integer types | |
| 1 | //! Builtin functions that operate on integer types | |
| 2 | ||
| 2 | 3 | const builtin = @import("builtin"); |
| 3 | 4 | const std = @import("std"); |
| 4 | 5 | const testing = std.testing; |
| 5 | 6 | const maxInt = std.math.maxInt; |
| 6 | 7 | const minInt = std.math.minInt; |
| 7 | ||
| 8 | const arch = builtin.cpu.arch; | |
| 9 | const is_test = builtin.is_test; | |
| 10 | const common = @import("common.zig"); | |
| 8 | 11 | const udivmod = @import("udivmod.zig").udivmod; |
| 9 | 12 | |
| 10 | pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.C) i64 { | |
| 11 | @setRuntimeSafety(builtin.is_test); | |
| 13 | pub const panic = common.panic; | |
| 14 | ||
| 15 | comptime { | |
| 16 | @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = common.linkage }); | |
| 17 | @export(__mulsi3, .{ .name = "__mulsi3", .linkage = common.linkage }); | |
| 18 | @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = common.linkage }); | |
| 19 | if (common.want_aeabi) { | |
| 20 | @export(__aeabi_idiv, .{ .name = "__aeabi_idiv", .linkage = common.linkage }); | |
| 21 | @export(__aeabi_uidiv, .{ .name = "__aeabi_uidiv", .linkage = common.linkage }); | |
| 22 | } else { | |
| 23 | @export(__divsi3, .{ .name = "__divsi3", .linkage = common.linkage }); | |
| 24 | @export(__udivsi3, .{ .name = "__udivsi3", .linkage = common.linkage }); | |
| 25 | } | |
| 26 | @export(__divdi3, .{ .name = "__divdi3", .linkage = common.linkage }); | |
| 27 | @export(__udivdi3, .{ .name = "__udivdi3", .linkage = common.linkage }); | |
| 28 | @export(__modsi3, .{ .name = "__modsi3", .linkage = common.linkage }); | |
| 29 | @export(__moddi3, .{ .name = "__moddi3", .linkage = common.linkage }); | |
| 30 | @export(__umodsi3, .{ .name = "__umodsi3", .linkage = common.linkage }); | |
| 31 | @export(__umoddi3, .{ .name = "__umoddi3", .linkage = common.linkage }); | |
| 32 | @export(__divmodsi4, .{ .name = "__divmodsi4", .linkage = common.linkage }); | |
| 33 | @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = common.linkage }); | |
| 34 | } | |
| 12 | 35 | |
| 36 | pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.C) i64 { | |
| 13 | 37 | const d = __divdi3(a, b); |
| 14 | 38 | rem.* = a -% (d *% b); |
| 15 | 39 | return d; |
| 16 | 40 | } |
| 17 | 41 | |
| 18 | 42 | pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 { |
| 19 | @setRuntimeSafety(builtin.is_test); | |
| 20 | 43 | return udivmod(u64, a, b, maybe_rem); |
| 21 | 44 | } |
| 22 | 45 | |
| ... | ... | @@ -25,8 +48,6 @@ test "test_udivmoddi4" { |
| 25 | 48 | } |
| 26 | 49 | |
| 27 | 50 | pub fn __divdi3(a: i64, b: i64) callconv(.C) i64 { |
| 28 | @setRuntimeSafety(builtin.is_test); | |
| 29 | ||
| 30 | 51 | // Set aside the sign of the quotient. |
| 31 | 52 | const sign = @bitCast(u64, (a ^ b) >> 63); |
| 32 | 53 | // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63). |
| ... | ... | @@ -64,8 +85,6 @@ fn test_one_divdi3(a: i64, b: i64, expected_q: i64) !void { |
| 64 | 85 | } |
| 65 | 86 | |
| 66 | 87 | pub fn __moddi3(a: i64, b: i64) callconv(.C) i64 { |
| 67 | @setRuntimeSafety(builtin.is_test); | |
| 68 | ||
| 69 | 88 | // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63). |
| 70 | 89 | const abs_a = (a ^ (a >> 63)) -% (a >> 63); |
| 71 | 90 | const abs_b = (b ^ (b >> 63)) -% (b >> 63); |
| ... | ... | @@ -104,13 +123,10 @@ fn test_one_moddi3(a: i64, b: i64, expected_r: i64) !void { |
| 104 | 123 | } |
| 105 | 124 | |
| 106 | 125 | pub fn __udivdi3(a: u64, b: u64) callconv(.C) u64 { |
| 107 | @setRuntimeSafety(builtin.is_test); | |
| 108 | 126 | return __udivmoddi4(a, b, null); |
| 109 | 127 | } |
| 110 | 128 | |
| 111 | 129 | pub fn __umoddi3(a: u64, b: u64) callconv(.C) u64 { |
| 112 | @setRuntimeSafety(builtin.is_test); | |
| 113 | ||
| 114 | 130 | var r: u64 = undefined; |
| 115 | 131 | _ = __udivmoddi4(a, b, &r); |
| 116 | 132 | return r; |
| ... | ... | @@ -130,8 +146,6 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) !void { |
| 130 | 146 | } |
| 131 | 147 | |
| 132 | 148 | pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.C) i32 { |
| 133 | @setRuntimeSafety(builtin.is_test); | |
| 134 | ||
| 135 | 149 | const d = __divsi3(a, b); |
| 136 | 150 | rem.* = a -% (d * b); |
| 137 | 151 | return d; |
| ... | ... | @@ -166,16 +180,20 @@ fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void { |
| 166 | 180 | } |
| 167 | 181 | |
| 168 | 182 | pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 { |
| 169 | @setRuntimeSafety(builtin.is_test); | |
| 170 | ||
| 171 | 183 | const d = __udivsi3(a, b); |
| 172 | 184 | rem.* = @bitCast(u32, @bitCast(i32, a) -% (@bitCast(i32, d) * @bitCast(i32, b))); |
| 173 | 185 | return d; |
| 174 | 186 | } |
| 175 | 187 | |
| 176 | 188 | pub fn __divsi3(n: i32, d: i32) callconv(.C) i32 { |
| 177 | @setRuntimeSafety(builtin.is_test); | |
| 189 | return div_i32(n, d); | |
| 190 | } | |
| 178 | 191 | |
| 192 | fn __aeabi_idiv(n: i32, d: i32) callconv(.AAPCS) i32 { | |
| 193 | return div_i32(n, d); | |
| 194 | } | |
| 195 | ||
| 196 | inline fn div_i32(n: i32, d: i32) i32 { | |
| 179 | 197 | // Set aside the sign of the quotient. |
| 180 | 198 | const sign = @bitCast(u32, (n ^ d) >> 31); |
| 181 | 199 | // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). |
| ... | ... | @@ -213,8 +231,14 @@ fn test_one_divsi3(a: i32, b: i32, expected_q: i32) !void { |
| 213 | 231 | } |
| 214 | 232 | |
| 215 | 233 | pub fn __udivsi3(n: u32, d: u32) callconv(.C) u32 { |
| 216 | @setRuntimeSafety(builtin.is_test); | |
| 234 | return div_u32(n, d); | |
| 235 | } | |
| 217 | 236 | |
| 237 | fn __aeabi_uidiv(n: u32, d: u32) callconv(.AAPCS) u32 { | |
| 238 | return div_u32(n, d); | |
| 239 | } | |
| 240 | ||
| 241 | inline fn div_u32(n: u32, d: u32) u32 { | |
| 218 | 242 | const n_uword_bits: c_uint = 32; |
| 219 | 243 | // special cases |
| 220 | 244 | if (d == 0) return 0; // ?! |
| ... | ... | @@ -400,8 +424,6 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void { |
| 400 | 424 | } |
| 401 | 425 | |
| 402 | 426 | pub fn __modsi3(n: i32, d: i32) callconv(.C) i32 { |
| 403 | @setRuntimeSafety(builtin.is_test); | |
| 404 | ||
| 405 | 427 | return n -% __divsi3(n, d) *% d; |
| 406 | 428 | } |
| 407 | 429 | |
| ... | ... | @@ -431,8 +453,6 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void { |
| 431 | 453 | } |
| 432 | 454 | |
| 433 | 455 | pub fn __umodsi3(n: u32, d: u32) callconv(.C) u32 { |
| 434 | @setRuntimeSafety(builtin.is_test); | |
| 435 | ||
| 436 | 456 | return n -% __udivsi3(n, d) *% d; |
| 437 | 457 | } |
| 438 | 458 | |
| ... | ... | @@ -583,8 +603,6 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void { |
| 583 | 603 | } |
| 584 | 604 | |
| 585 | 605 | pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 { |
| 586 | @setRuntimeSafety(builtin.is_test); | |
| 587 | ||
| 588 | 606 | var ua = @bitCast(u32, a); |
| 589 | 607 | var ub = @bitCast(u32, b); |
| 590 | 608 | var r: u32 = 0; |
lib/compiler_rt/int_to_float.zig created+58| ... | ... | @@ -0,0 +1,58 @@ |
| 1 | const Int = @import("std").meta.Int; | |
| 2 | const math = @import("std").math; | |
| 3 | ||
| 4 | pub fn intToFloat(comptime T: type, x: anytype) T { | |
| 5 | if (x == 0) return 0; | |
| 6 | ||
| 7 | // Various constants whose values follow from the type parameters. | |
| 8 | // Any reasonable optimizer will fold and propagate all of these. | |
| 9 | const Z = Int(.unsigned, @bitSizeOf(@TypeOf(x))); | |
| 10 | const uT = Int(.unsigned, @bitSizeOf(T)); | |
| 11 | const inf = math.inf(T); | |
| 12 | const float_bits = @bitSizeOf(T); | |
| 13 | const int_bits = @bitSizeOf(@TypeOf(x)); | |
| 14 | const exp_bits = math.floatExponentBits(T); | |
| 15 | const fractional_bits = math.floatFractionalBits(T); | |
| 16 | const exp_bias = math.maxInt(Int(.unsigned, exp_bits - 1)); | |
| 17 | const implicit_bit = if (T != f80) @as(uT, 1) << fractional_bits else 0; | |
| 18 | const max_exp = exp_bias; | |
| 19 | ||
| 20 | // Sign | |
| 21 | var abs_val = math.absCast(x); | |
| 22 | const sign_bit = if (x < 0) @as(uT, 1) << (float_bits - 1) else 0; | |
| 23 | var result: uT = sign_bit; | |
| 24 | ||
| 25 | // Compute significand | |
| 26 | var exp = int_bits - @clz(Z, abs_val) - 1; | |
| 27 | if (int_bits <= fractional_bits or exp <= fractional_bits) { | |
| 28 | const shift_amt = fractional_bits - @intCast(math.Log2Int(uT), exp); | |
| 29 | ||
| 30 | // Shift up result to line up with the significand - no rounding required | |
| 31 | result = (@intCast(uT, abs_val) << shift_amt); | |
| 32 | result ^= implicit_bit; // Remove implicit integer bit | |
| 33 | } else { | |
| 34 | var shift_amt = @intCast(math.Log2Int(Z), exp - fractional_bits); | |
| 35 | const exact_tie: bool = @ctz(Z, abs_val) == shift_amt - 1; | |
| 36 | ||
| 37 | // Shift down result and remove implicit integer bit | |
| 38 | result = @intCast(uT, (abs_val >> (shift_amt - 1))) ^ (implicit_bit << 1); | |
| 39 | ||
| 40 | // Round result, including round-to-even for exact ties | |
| 41 | result = ((result + 1) >> 1) & ~@as(uT, @boolToInt(exact_tie)); | |
| 42 | } | |
| 43 | ||
| 44 | // Compute exponent | |
| 45 | if ((int_bits > max_exp) and (exp > max_exp)) // If exponent too large, overflow to infinity | |
| 46 | return @bitCast(T, sign_bit | @bitCast(uT, inf)); | |
| 47 | ||
| 48 | result += (@as(uT, exp) + exp_bias) << math.floatMantissaBits(T); | |
| 49 | ||
| 50 | // If the result included a carry, we need to restore the explicit integer bit | |
| 51 | if (T == f80) result |= 1 << fractional_bits; | |
| 52 | ||
| 53 | return @bitCast(T, sign_bit | result); | |
| 54 | } | |
| 55 | ||
| 56 | test { | |
| 57 | _ = @import("int_to_float_test.zig"); | |
| 58 | } |
lib/compiler_rt/int_to_float_test.zig created+838| ... | ... | @@ -0,0 +1,838 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const testing = std.testing; | |
| 4 | const math = std.math; | |
| 5 | ||
| 6 | const __floatunsihf = @import("floatunsihf.zig").__floatunsihf; | |
| 7 | ||
| 8 | // Conversion to f32 | |
| 9 | const __floatsisf = @import("floatsisf.zig").__floatsisf; | |
| 10 | const __floatunsisf = @import("floatunsisf.zig").__floatunsisf; | |
| 11 | const __floatdisf = @import("floatdisf.zig").__floatdisf; | |
| 12 | const __floatundisf = @import("floatundisf.zig").__floatundisf; | |
| 13 | const __floattisf = @import("floattisf.zig").__floattisf; | |
| 14 | const __floatuntisf = @import("floatuntisf.zig").__floatuntisf; | |
| 15 | ||
| 16 | // Conversion to f64 | |
| 17 | const __floatsidf = @import("floatsidf.zig").__floatsidf; | |
| 18 | const __floatunsidf = @import("floatunsidf.zig").__floatunsidf; | |
| 19 | const __floatdidf = @import("floatdidf.zig").__floatdidf; | |
| 20 | const __floatundidf = @import("floatundidf.zig").__floatundidf; | |
| 21 | const __floattidf = @import("floattidf.zig").__floattidf; | |
| 22 | const __floatuntidf = @import("floatuntidf.zig").__floatuntidf; | |
| 23 | ||
| 24 | // Conversion to f128 | |
| 25 | const __floatsitf = @import("floatsitf.zig").__floatsitf; | |
| 26 | const __floatunsitf = @import("floatunsitf.zig").__floatunsitf; | |
| 27 | const __floatditf = @import("floatditf.zig").__floatditf; | |
| 28 | const __floatunditf = @import("floatunditf.zig").__floatunditf; | |
| 29 | const __floattitf = @import("floattitf.zig").__floattitf; | |
| 30 | const __floatuntitf = @import("floatuntitf.zig").__floatuntitf; | |
| 31 | ||
| 32 | fn test__floatsisf(a: i32, expected: u32) !void { | |
| 33 | const r = __floatsisf(a); | |
| 34 | try std.testing.expect(@bitCast(u32, r) == expected); | |
| 35 | } | |
| 36 | ||
| 37 | fn test_one_floatunsisf(a: u32, expected: u32) !void { | |
| 38 | const r = __floatunsisf(a); | |
| 39 | try std.testing.expect(@bitCast(u32, r) == expected); | |
| 40 | } | |
| 41 | ||
| 42 | test "floatsisf" { | |
| 43 | try test__floatsisf(0, 0x00000000); | |
| 44 | try test__floatsisf(1, 0x3f800000); | |
| 45 | try test__floatsisf(-1, 0xbf800000); | |
| 46 | try test__floatsisf(0x7FFFFFFF, 0x4f000000); | |
| 47 | try test__floatsisf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xcf000000); | |
| 48 | } | |
| 49 | ||
| 50 | test "floatunsisf" { | |
| 51 | // Test the produced bit pattern | |
| 52 | try test_one_floatunsisf(0, 0); | |
| 53 | try test_one_floatunsisf(1, 0x3f800000); | |
| 54 | try test_one_floatunsisf(0x7FFFFFFF, 0x4f000000); | |
| 55 | try test_one_floatunsisf(0x80000000, 0x4f000000); | |
| 56 | try test_one_floatunsisf(0xFFFFFFFF, 0x4f800000); | |
| 57 | } | |
| 58 | ||
| 59 | fn test__floatdisf(a: i64, expected: f32) !void { | |
| 60 | const x = __floatdisf(a); | |
| 61 | try testing.expect(x == expected); | |
| 62 | } | |
| 63 | ||
| 64 | fn test__floatundisf(a: u64, expected: f32) !void { | |
| 65 | try std.testing.expectEqual(expected, __floatundisf(a)); | |
| 66 | } | |
| 67 | ||
| 68 | test "floatdisf" { | |
| 69 | try test__floatdisf(0, 0.0); | |
| 70 | try test__floatdisf(1, 1.0); | |
| 71 | try test__floatdisf(2, 2.0); | |
| 72 | try test__floatdisf(-1, -1.0); | |
| 73 | try test__floatdisf(-2, -2.0); | |
| 74 | try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 75 | try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 76 | try test__floatdisf(@bitCast(i64, @as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); | |
| 77 | try test__floatdisf(@bitCast(i64, @as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); | |
| 78 | try test__floatdisf(@bitCast(i64, @as(u64, 0x8000000000000000)), -0x1.000000p+63); | |
| 79 | try test__floatdisf(@bitCast(i64, @as(u64, 0x8000000000000001)), -0x1.000000p+63); | |
| 80 | try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 81 | try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 82 | try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 83 | try test__floatdisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 84 | try test__floatdisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 85 | try test__floatdisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 86 | try test__floatdisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 87 | try test__floatdisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 88 | try test__floatdisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 89 | try test__floatdisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 90 | try test__floatdisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 91 | } | |
| 92 | ||
| 93 | test "floatundisf" { | |
| 94 | try test__floatundisf(0, 0.0); | |
| 95 | try test__floatundisf(1, 1.0); | |
| 96 | try test__floatundisf(2, 2.0); | |
| 97 | try test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 98 | try test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 99 | try test__floatundisf(0x8000008000000000, 0x1p+63); | |
| 100 | try test__floatundisf(0x8000010000000000, 0x1.000002p+63); | |
| 101 | try test__floatundisf(0x8000000000000000, 0x1p+63); | |
| 102 | try test__floatundisf(0x8000000000000001, 0x1p+63); | |
| 103 | try test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); | |
| 104 | try test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); | |
| 105 | try test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 106 | try test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 107 | try test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 108 | try test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 109 | try test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 110 | try test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 111 | try test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 112 | try test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 113 | try test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 114 | try test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 115 | try test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 116 | } | |
| 117 | ||
| 118 | fn test__floattisf(a: i128, expected: f32) !void { | |
| 119 | const x = __floattisf(a); | |
| 120 | try testing.expect(x == expected); | |
| 121 | } | |
| 122 | ||
| 123 | fn test__floatuntisf(a: u128, expected: f32) !void { | |
| 124 | const x = __floatuntisf(a); | |
| 125 | try testing.expect(x == expected); | |
| 126 | } | |
| 127 | ||
| 128 | test "floattisf" { | |
| 129 | try test__floattisf(0, 0.0); | |
| 130 | ||
| 131 | try test__floattisf(1, 1.0); | |
| 132 | try test__floattisf(2, 2.0); | |
| 133 | try test__floattisf(-1, -1.0); | |
| 134 | try test__floattisf(-2, -2.0); | |
| 135 | ||
| 136 | try test__floattisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 137 | try test__floattisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 138 | ||
| 139 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62); | |
| 140 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62); | |
| 141 | ||
| 142 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63); | |
| 143 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63); | |
| 144 | ||
| 145 | try test__floattisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 146 | ||
| 147 | try test__floattisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 148 | try test__floattisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 149 | try test__floattisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 150 | try test__floattisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 151 | try test__floattisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 152 | ||
| 153 | try test__floattisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 154 | try test__floattisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 155 | try test__floattisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 156 | try test__floattisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 157 | try test__floattisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 158 | ||
| 159 | try test__floattisf(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114); | |
| 160 | ||
| 161 | try test__floattisf(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114); | |
| 162 | try test__floattisf(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114); | |
| 163 | try test__floattisf(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114); | |
| 164 | try test__floattisf(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114); | |
| 165 | try test__floattisf(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114); | |
| 166 | ||
| 167 | try test__floattisf(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114); | |
| 168 | try test__floattisf(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114); | |
| 169 | try test__floattisf(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114); | |
| 170 | try test__floattisf(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114); | |
| 171 | try test__floattisf(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114); | |
| 172 | } | |
| 173 | ||
| 174 | test "floatuntisf" { | |
| 175 | try test__floatuntisf(0, 0.0); | |
| 176 | ||
| 177 | try test__floatuntisf(1, 1.0); | |
| 178 | try test__floatuntisf(2, 2.0); | |
| 179 | try test__floatuntisf(20, 20.0); | |
| 180 | ||
| 181 | try test__floatuntisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 182 | try test__floatuntisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 183 | ||
| 184 | try test__floatuntisf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); | |
| 185 | try test__floatuntisf(make_uti(0x8000000000000800, 0), 0x1.0p+127); | |
| 186 | try test__floatuntisf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); | |
| 187 | ||
| 188 | try test__floatuntisf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); | |
| 189 | ||
| 190 | try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 191 | ||
| 192 | try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 193 | try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 194 | ||
| 195 | try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 196 | ||
| 197 | try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 198 | try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 199 | try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 200 | ||
| 201 | try test__floatuntisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); | |
| 202 | try test__floatuntisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); | |
| 203 | ||
| 204 | try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 205 | ||
| 206 | try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 207 | try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 208 | try test__floatuntisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 209 | try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 210 | try test__floatuntisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 211 | ||
| 212 | try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 213 | try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 214 | try test__floatuntisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 215 | try test__floatuntisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 216 | try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 217 | ||
| 218 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76); | |
| 219 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76); | |
| 220 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76); | |
| 221 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76); | |
| 222 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76); | |
| 223 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76); | |
| 224 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76); | |
| 225 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76); | |
| 226 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76); | |
| 227 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76); | |
| 228 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76); | |
| 229 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76); | |
| 230 | ||
| 231 | // Test overflow to infinity | |
| 232 | try test__floatuntisf(@as(u128, math.maxInt(u128)), @bitCast(f32, math.inf(f32))); | |
| 233 | } | |
| 234 | ||
| 235 | fn test_one_floatsidf(a: i32, expected: u64) !void { | |
| 236 | const r = __floatsidf(a); | |
| 237 | try std.testing.expect(@bitCast(u64, r) == expected); | |
| 238 | } | |
| 239 | ||
| 240 | fn test_one_floatunsidf(a: u32, expected: u64) !void { | |
| 241 | const r = __floatunsidf(a); | |
| 242 | try std.testing.expect(@bitCast(u64, r) == expected); | |
| 243 | } | |
| 244 | ||
| 245 | test "floatsidf" { | |
| 246 | try test_one_floatsidf(0, 0x0000000000000000); | |
| 247 | try test_one_floatsidf(1, 0x3ff0000000000000); | |
| 248 | try test_one_floatsidf(-1, 0xbff0000000000000); | |
| 249 | try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000); | |
| 250 | try test_one_floatsidf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc1e0000000000000); | |
| 251 | } | |
| 252 | ||
| 253 | test "floatunsidf" { | |
| 254 | try test_one_floatunsidf(0, 0x0000000000000000); | |
| 255 | try test_one_floatunsidf(1, 0x3ff0000000000000); | |
| 256 | try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000); | |
| 257 | try test_one_floatunsidf(@intCast(u32, 0x80000000), 0x41e0000000000000); | |
| 258 | try test_one_floatunsidf(@intCast(u32, 0xFFFFFFFF), 0x41efffffffe00000); | |
| 259 | } | |
| 260 | ||
| 261 | fn test__floatdidf(a: i64, expected: f64) !void { | |
| 262 | const r = __floatdidf(a); | |
| 263 | try testing.expect(r == expected); | |
| 264 | } | |
| 265 | ||
| 266 | fn test__floatundidf(a: u64, expected: f64) !void { | |
| 267 | const r = __floatundidf(a); | |
| 268 | try testing.expect(r == expected); | |
| 269 | } | |
| 270 | ||
| 271 | test "floatdidf" { | |
| 272 | try test__floatdidf(0, 0.0); | |
| 273 | try test__floatdidf(1, 1.0); | |
| 274 | try test__floatdidf(2, 2.0); | |
| 275 | try test__floatdidf(20, 20.0); | |
| 276 | try test__floatdidf(-1, -1.0); | |
| 277 | try test__floatdidf(-2, -2.0); | |
| 278 | try test__floatdidf(-20, -20.0); | |
| 279 | try test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 280 | try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 281 | try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 282 | try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 283 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); | |
| 284 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000800)), -0x1.FFFFFFFFFFFFEp+62); | |
| 285 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); | |
| 286 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000001000)), -0x1.FFFFFFFFFFFFCp+62); | |
| 287 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000000)), -0x1.000000p+63); | |
| 288 | try test__floatdidf(@bitCast(i64, @intCast(u64, 0x8000000000000001)), -0x1.000000p+63); // 0x8000000000000001 | |
| 289 | try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 290 | try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 291 | try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 292 | try test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 293 | try test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 294 | try test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 295 | try test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 296 | try test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 297 | try test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 298 | try test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 299 | try test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 300 | try test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 301 | try test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 302 | try test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 303 | try test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 304 | try test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 305 | try test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 306 | try test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 307 | try test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 308 | try test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 309 | try test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 310 | try test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 311 | try test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 312 | try test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 313 | try test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 314 | try test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 315 | } | |
| 316 | ||
| 317 | test "floatundidf" { | |
| 318 | try test__floatundidf(0, 0.0); | |
| 319 | try test__floatundidf(1, 1.0); | |
| 320 | try test__floatundidf(2, 2.0); | |
| 321 | try test__floatundidf(20, 20.0); | |
| 322 | try test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 323 | try test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 324 | try test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 325 | try test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 326 | try test__floatundidf(0x8000008000000000, 0x1.000001p+63); | |
| 327 | try test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63); | |
| 328 | try test__floatundidf(0x8000010000000000, 0x1.000002p+63); | |
| 329 | try test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63); | |
| 330 | try test__floatundidf(0x8000000000000000, 0x1p+63); | |
| 331 | try test__floatundidf(0x8000000000000001, 0x1p+63); | |
| 332 | try test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 333 | try test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 334 | try test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 335 | try test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 336 | try test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 337 | try test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 338 | try test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 339 | try test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 340 | try test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 341 | try test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 342 | try test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 343 | try test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 344 | try test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 345 | try test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 346 | try test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 347 | try test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 348 | try test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 349 | try test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 350 | try test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 351 | try test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 352 | try test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 353 | try test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 354 | try test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 355 | try test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 356 | try test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 357 | try test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 358 | } | |
| 359 | ||
| 360 | fn test__floattidf(a: i128, expected: f64) !void { | |
| 361 | const x = __floattidf(a); | |
| 362 | try testing.expect(x == expected); | |
| 363 | } | |
| 364 | ||
| 365 | fn test__floatuntidf(a: u128, expected: f64) !void { | |
| 366 | const x = __floatuntidf(a); | |
| 367 | try testing.expect(x == expected); | |
| 368 | } | |
| 369 | ||
| 370 | test "floattidf" { | |
| 371 | try test__floattidf(0, 0.0); | |
| 372 | ||
| 373 | try test__floattidf(1, 1.0); | |
| 374 | try test__floattidf(2, 2.0); | |
| 375 | try test__floattidf(20, 20.0); | |
| 376 | try test__floattidf(-1, -1.0); | |
| 377 | try test__floattidf(-2, -2.0); | |
| 378 | try test__floattidf(-20, -20.0); | |
| 379 | ||
| 380 | try test__floattidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 381 | try test__floattidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 382 | try test__floattidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 383 | try test__floattidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 384 | ||
| 385 | try test__floattidf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); | |
| 386 | try test__floattidf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); | |
| 387 | try test__floattidf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); | |
| 388 | try test__floattidf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); | |
| 389 | ||
| 390 | try test__floattidf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); | |
| 391 | try test__floattidf(make_ti(0x8000000000000001, 0), -0x1.000000p+127); | |
| 392 | ||
| 393 | try test__floattidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 394 | ||
| 395 | try test__floattidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 396 | try test__floattidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 397 | try test__floattidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 398 | try test__floattidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 399 | try test__floattidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 400 | ||
| 401 | try test__floattidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 402 | try test__floattidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 403 | try test__floattidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 404 | try test__floattidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 405 | try test__floattidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 406 | ||
| 407 | try test__floattidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 408 | try test__floattidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 409 | try test__floattidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 410 | try test__floattidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 411 | try test__floattidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 412 | try test__floattidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 413 | try test__floattidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 414 | try test__floattidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 415 | try test__floattidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 416 | try test__floattidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 417 | try test__floattidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 418 | try test__floattidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 419 | try test__floattidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 420 | try test__floattidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 421 | try test__floattidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 422 | ||
| 423 | try test__floattidf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 424 | try test__floattidf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); | |
| 425 | try test__floattidf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); | |
| 426 | try test__floattidf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); | |
| 427 | try test__floattidf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); | |
| 428 | try test__floattidf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); | |
| 429 | try test__floattidf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); | |
| 430 | try test__floattidf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); | |
| 431 | try test__floattidf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); | |
| 432 | try test__floattidf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); | |
| 433 | try test__floattidf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); | |
| 434 | try test__floattidf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); | |
| 435 | try test__floattidf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); | |
| 436 | try test__floattidf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); | |
| 437 | try test__floattidf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 438 | } | |
| 439 | ||
| 440 | test "floatuntidf" { | |
| 441 | try test__floatuntidf(0, 0.0); | |
| 442 | ||
| 443 | try test__floatuntidf(1, 1.0); | |
| 444 | try test__floatuntidf(2, 2.0); | |
| 445 | try test__floatuntidf(20, 20.0); | |
| 446 | ||
| 447 | try test__floatuntidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 448 | try test__floatuntidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 449 | try test__floatuntidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 450 | try test__floatuntidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 451 | ||
| 452 | try test__floatuntidf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); | |
| 453 | try test__floatuntidf(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127); | |
| 454 | try test__floatuntidf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); | |
| 455 | try test__floatuntidf(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127); | |
| 456 | ||
| 457 | try test__floatuntidf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); | |
| 458 | try test__floatuntidf(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127); | |
| 459 | ||
| 460 | try test__floatuntidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 461 | ||
| 462 | try test__floatuntidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 463 | try test__floatuntidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 464 | try test__floatuntidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 465 | try test__floatuntidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 466 | try test__floatuntidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 467 | ||
| 468 | try test__floatuntidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 469 | try test__floatuntidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 470 | try test__floatuntidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 471 | try test__floatuntidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 472 | try test__floatuntidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 473 | ||
| 474 | try test__floatuntidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 475 | try test__floatuntidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 476 | try test__floatuntidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 477 | try test__floatuntidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 478 | try test__floatuntidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 479 | try test__floatuntidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 480 | try test__floatuntidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 481 | try test__floatuntidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 482 | try test__floatuntidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 483 | try test__floatuntidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 484 | try test__floatuntidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 485 | try test__floatuntidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 486 | try test__floatuntidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 487 | try test__floatuntidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 488 | try test__floatuntidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 489 | ||
| 490 | try test__floatuntidf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 491 | try test__floatuntidf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); | |
| 492 | try test__floatuntidf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); | |
| 493 | try test__floatuntidf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); | |
| 494 | try test__floatuntidf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); | |
| 495 | try test__floatuntidf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); | |
| 496 | try test__floatuntidf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); | |
| 497 | try test__floatuntidf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); | |
| 498 | try test__floatuntidf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); | |
| 499 | try test__floatuntidf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); | |
| 500 | try test__floatuntidf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); | |
| 501 | try test__floatuntidf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); | |
| 502 | try test__floatuntidf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); | |
| 503 | try test__floatuntidf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); | |
| 504 | try test__floatuntidf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 505 | } | |
| 506 | ||
| 507 | fn test__floatsitf(a: i32, expected: u128) !void { | |
| 508 | const r = __floatsitf(a); | |
| 509 | try std.testing.expect(@bitCast(u128, r) == expected); | |
| 510 | } | |
| 511 | ||
| 512 | test "floatsitf" { | |
| 513 | try test__floatsitf(0, 0); | |
| 514 | try test__floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000); | |
| 515 | try test__floatsitf(0x12345678, 0x401b2345678000000000000000000000); | |
| 516 | try test__floatsitf(-0x12345678, 0xc01b2345678000000000000000000000); | |
| 517 | try test__floatsitf(@bitCast(i32, @intCast(u32, 0xffffffff)), 0xbfff0000000000000000000000000000); | |
| 518 | try test__floatsitf(@bitCast(i32, @intCast(u32, 0x80000000)), 0xc01e0000000000000000000000000000); | |
| 519 | } | |
| 520 | ||
| 521 | fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void { | |
| 522 | const x = __floatunsitf(a); | |
| 523 | ||
| 524 | const x_repr = @bitCast(u128, x); | |
| 525 | const x_hi = @intCast(u64, x_repr >> 64); | |
| 526 | const x_lo = @truncate(u64, x_repr); | |
| 527 | ||
| 528 | if (x_hi == expected_hi and x_lo == expected_lo) { | |
| 529 | return; | |
| 530 | } | |
| 531 | // nan repr | |
| 532 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 533 | if ((x_hi & 0x7fff000000000000) == 0x7fff000000000000 and ((x_hi & 0xffffffffffff) > 0 or x_lo > 0)) { | |
| 534 | return; | |
| 535 | } | |
| 536 | } | |
| 537 | ||
| 538 | @panic("__floatunsitf test failure"); | |
| 539 | } | |
| 540 | ||
| 541 | test "floatunsitf" { | |
| 542 | try test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0); | |
| 543 | try test__floatunsitf(0, 0x0, 0x0); | |
| 544 | try test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0); | |
| 545 | try test__floatunsitf(0x12345678, 0x401b234567800000, 0x0); | |
| 546 | } | |
| 547 | ||
| 548 | fn test__floatditf(a: i64, expected: f128) !void { | |
| 549 | const x = __floatditf(a); | |
| 550 | try testing.expect(x == expected); | |
| 551 | } | |
| 552 | ||
| 553 | fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void { | |
| 554 | const x = __floatunditf(a); | |
| 555 | ||
| 556 | const x_repr = @bitCast(u128, x); | |
| 557 | const x_hi = @intCast(u64, x_repr >> 64); | |
| 558 | const x_lo = @truncate(u64, x_repr); | |
| 559 | ||
| 560 | if (x_hi == expected_hi and x_lo == expected_lo) { | |
| 561 | return; | |
| 562 | } | |
| 563 | // nan repr | |
| 564 | else if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { | |
| 565 | if ((x_hi & 0x7fff000000000000) == 0x7fff000000000000 and ((x_hi & 0xffffffffffff) > 0 or x_lo > 0)) { | |
| 566 | return; | |
| 567 | } | |
| 568 | } | |
| 569 | ||
| 570 | @panic("__floatunditf test failure"); | |
| 571 | } | |
| 572 | ||
| 573 | test "floatditf" { | |
| 574 | try test__floatditf(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000)); | |
| 575 | try test__floatditf(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000)); | |
| 576 | try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0)); | |
| 577 | try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0)); | |
| 578 | try test__floatditf(0x0, make_tf(0x0, 0x0)); | |
| 579 | try test__floatditf(@bitCast(i64, @as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0)); | |
| 580 | try test__floatditf(@bitCast(i64, @as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0)); | |
| 581 | try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000)); | |
| 582 | try test__floatditf(@bitCast(i64, @as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0)); | |
| 583 | } | |
| 584 | ||
| 585 | test "floatunditf" { | |
| 586 | try test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000); | |
| 587 | try test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000); | |
| 588 | try test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0); | |
| 589 | try test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000); | |
| 590 | try test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000); | |
| 591 | try test__floatunditf(0x2, 0x4000000000000000, 0x0); | |
| 592 | try test__floatunditf(0x1, 0x3fff000000000000, 0x0); | |
| 593 | try test__floatunditf(0x0, 0x0, 0x0); | |
| 594 | } | |
| 595 | ||
| 596 | fn test__floattitf(a: i128, expected: f128) !void { | |
| 597 | const x = __floattitf(a); | |
| 598 | try testing.expect(x == expected); | |
| 599 | } | |
| 600 | ||
| 601 | fn test__floatuntitf(a: u128, expected: f128) !void { | |
| 602 | const x = __floatuntitf(a); | |
| 603 | try testing.expect(x == expected); | |
| 604 | } | |
| 605 | ||
| 606 | test "floattitf" { | |
| 607 | try test__floattitf(0, 0.0); | |
| 608 | ||
| 609 | try test__floattitf(1, 1.0); | |
| 610 | try test__floattitf(2, 2.0); | |
| 611 | try test__floattitf(20, 20.0); | |
| 612 | try test__floattitf(-1, -1.0); | |
| 613 | try test__floattitf(-2, -2.0); | |
| 614 | try test__floattitf(-20, -20.0); | |
| 615 | ||
| 616 | try test__floattitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 617 | try test__floattitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 618 | try test__floattitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 619 | try test__floattitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 620 | ||
| 621 | try test__floattitf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); | |
| 622 | try test__floattitf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); | |
| 623 | try test__floattitf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); | |
| 624 | try test__floattitf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); | |
| 625 | ||
| 626 | try test__floattitf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); | |
| 627 | try test__floattitf(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126); | |
| 628 | ||
| 629 | try test__floattitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 630 | ||
| 631 | try test__floattitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 632 | try test__floattitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 633 | try test__floattitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 634 | try test__floattitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 635 | try test__floattitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 636 | ||
| 637 | try test__floattitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 638 | try test__floattitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 639 | try test__floattitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 640 | try test__floattitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 641 | try test__floattitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 642 | ||
| 643 | try test__floattitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 644 | try test__floattitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); | |
| 645 | try test__floattitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); | |
| 646 | try test__floattitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); | |
| 647 | try test__floattitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); | |
| 648 | try test__floattitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); | |
| 649 | try test__floattitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); | |
| 650 | try test__floattitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); | |
| 651 | try test__floattitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); | |
| 652 | try test__floattitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); | |
| 653 | try test__floattitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); | |
| 654 | try test__floattitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); | |
| 655 | try test__floattitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); | |
| 656 | try test__floattitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); | |
| 657 | try test__floattitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 658 | ||
| 659 | try test__floattitf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 660 | try test__floattitf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); | |
| 661 | try test__floattitf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); | |
| 662 | try test__floattitf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); | |
| 663 | try test__floattitf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); | |
| 664 | try test__floattitf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); | |
| 665 | try test__floattitf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); | |
| 666 | try test__floattitf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); | |
| 667 | try test__floattitf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); | |
| 668 | try test__floattitf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); | |
| 669 | try test__floattitf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); | |
| 670 | try test__floattitf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); | |
| 671 | try test__floattitf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); | |
| 672 | try test__floattitf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); | |
| 673 | try test__floattitf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 674 | ||
| 675 | try test__floattitf(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); | |
| 676 | ||
| 677 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 678 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 679 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 680 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 681 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 682 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 683 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 684 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 685 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 686 | } | |
| 687 | ||
| 688 | test "floatuntitf" { | |
| 689 | try test__floatuntitf(0, 0.0); | |
| 690 | ||
| 691 | try test__floatuntitf(1, 1.0); | |
| 692 | try test__floatuntitf(2, 2.0); | |
| 693 | try test__floatuntitf(20, 20.0); | |
| 694 | ||
| 695 | try test__floatuntitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 696 | try test__floatuntitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 697 | try test__floatuntitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 698 | try test__floatuntitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 699 | try test__floatuntitf(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59); | |
| 700 | try test__floatuntitf(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60); | |
| 701 | try test__floatuntitf(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60); | |
| 702 | ||
| 703 | try test__floatuntitf(0x8000008000000000, 0x8.000008p+60); | |
| 704 | try test__floatuntitf(0x8000000000000800, 0x8.0000000000008p+60); | |
| 705 | try test__floatuntitf(0x8000010000000000, 0x8.00001p+60); | |
| 706 | try test__floatuntitf(0x8000000000001000, 0x8.000000000001p+60); | |
| 707 | ||
| 708 | try test__floatuntitf(0x8000000000000000, 0x8p+60); | |
| 709 | try test__floatuntitf(0x8000000000000001, 0x8.000000000000001p+60); | |
| 710 | ||
| 711 | try test__floatuntitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 712 | ||
| 713 | try test__floatuntitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 714 | try test__floatuntitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 715 | try test__floatuntitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 716 | try test__floatuntitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 717 | try test__floatuntitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 718 | ||
| 719 | try test__floatuntitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 720 | try test__floatuntitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 721 | try test__floatuntitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 722 | try test__floatuntitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 723 | try test__floatuntitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 724 | ||
| 725 | try test__floatuntitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 726 | try test__floatuntitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); | |
| 727 | try test__floatuntitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); | |
| 728 | try test__floatuntitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); | |
| 729 | try test__floatuntitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); | |
| 730 | try test__floatuntitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); | |
| 731 | try test__floatuntitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); | |
| 732 | try test__floatuntitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); | |
| 733 | try test__floatuntitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); | |
| 734 | try test__floatuntitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); | |
| 735 | try test__floatuntitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); | |
| 736 | try test__floatuntitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); | |
| 737 | try test__floatuntitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); | |
| 738 | try test__floatuntitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); | |
| 739 | try test__floatuntitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 740 | ||
| 741 | try test__floatuntitf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 742 | try test__floatuntitf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); | |
| 743 | try test__floatuntitf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); | |
| 744 | try test__floatuntitf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); | |
| 745 | try test__floatuntitf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); | |
| 746 | try test__floatuntitf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); | |
| 747 | try test__floatuntitf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); | |
| 748 | try test__floatuntitf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); | |
| 749 | try test__floatuntitf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); | |
| 750 | try test__floatuntitf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); | |
| 751 | try test__floatuntitf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); | |
| 752 | try test__floatuntitf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); | |
| 753 | try test__floatuntitf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); | |
| 754 | try test__floatuntitf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); | |
| 755 | try test__floatuntitf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 756 | ||
| 757 | try test__floatuntitf(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); | |
| 758 | ||
| 759 | try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127); | |
| 760 | try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128); | |
| 761 | ||
| 762 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 763 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 764 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 765 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 766 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 767 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 768 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 769 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 770 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 771 | } | |
| 772 | ||
| 773 | fn make_ti(high: u64, low: u64) i128 { | |
| 774 | var result: u128 = high; | |
| 775 | result <<= 64; | |
| 776 | result |= low; | |
| 777 | return @bitCast(i128, result); | |
| 778 | } | |
| 779 | ||
| 780 | fn make_uti(high: u64, low: u64) u128 { | |
| 781 | var result: u128 = high; | |
| 782 | result <<= 64; | |
| 783 | result |= low; | |
| 784 | return result; | |
| 785 | } | |
| 786 | ||
| 787 | fn make_tf(high: u64, low: u64) f128 { | |
| 788 | var result: u128 = high; | |
| 789 | result <<= 64; | |
| 790 | result |= low; | |
| 791 | return @bitCast(f128, result); | |
| 792 | } | |
| 793 | ||
| 794 | test "conversion to f16" { | |
| 795 | try testing.expect(__floatunsihf(@as(u32, 0)) == 0.0); | |
| 796 | try testing.expect(__floatunsihf(@as(u32, 1)) == 1.0); | |
| 797 | try testing.expect(__floatunsihf(@as(u32, 65504)) == 65504); | |
| 798 | try testing.expect(__floatunsihf(@as(u32, 65504 + (1 << 4))) == math.inf(f16)); | |
| 799 | } | |
| 800 | ||
| 801 | test "conversion to f32" { | |
| 802 | try testing.expect(__floatunsisf(@as(u32, 0)) == 0.0); | |
| 803 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u32))) != 1.0); | |
| 804 | try testing.expect(__floatsisf(@as(i32, math.minInt(i32))) != 1.0); | |
| 805 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24))) == math.maxInt(u24)); | |
| 806 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact | |
| 807 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even | |
| 808 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact | |
| 809 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even | |
| 810 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact | |
| 811 | } | |
| 812 | ||
| 813 | test "conversion to f80" { | |
| 814 | if (builtin.zig_backend == .stage1 and builtin.cpu.arch != .x86_64) | |
| 815 | return error.SkipZigTest; // https://github.com/ziglang/zig/issues/11408 | |
| 816 | ||
| 817 | const intToFloat = @import("./int_to_float.zig").intToFloat; | |
| 818 | ||
| 819 | try testing.expect(intToFloat(f80, @as(i80, -12)) == -12); | |
| 820 | try testing.expect(@floatToInt(u80, intToFloat(f80, @as(u64, math.maxInt(u64)) + 0)) == math.maxInt(u64) + 0); | |
| 821 | try testing.expect(@floatToInt(u80, intToFloat(f80, @as(u80, math.maxInt(u64)) + 1)) == math.maxInt(u64) + 1); | |
| 822 | ||
| 823 | try testing.expect(intToFloat(f80, @as(u32, 0)) == 0.0); | |
| 824 | try testing.expect(intToFloat(f80, @as(u32, 1)) == 1.0); | |
| 825 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u32, math.maxInt(u24)) + 0)) == math.maxInt(u24)); | |
| 826 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u64)) + 0)) == math.maxInt(u64)); | |
| 827 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u64)) + 1)) == math.maxInt(u64) + 1); // Exact | |
| 828 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u64)) + 2)) == math.maxInt(u64) + 1); // Rounds down | |
| 829 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u64)) + 3)) == math.maxInt(u64) + 3); // Tie - Exact | |
| 830 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u64)) + 4)) == math.maxInt(u64) + 5); // Rounds up | |
| 831 | ||
| 832 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u65)) + 0)) == math.maxInt(u65) + 1); // Rounds up | |
| 833 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u65)) + 1)) == math.maxInt(u65) + 1); // Exact | |
| 834 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u65)) + 2)) == math.maxInt(u65) + 1); // Rounds down | |
| 835 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u65)) + 3)) == math.maxInt(u65) + 1); // Tie - Rounds down | |
| 836 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u65)) + 4)) == math.maxInt(u65) + 5); // Rounds up | |
| 837 | try testing.expect(@floatToInt(u128, intToFloat(f80, @as(u80, math.maxInt(u65)) + 5)) == math.maxInt(u65) + 5); // Exact | |
| 838 | } |
lib/compiler_rt/log.zig+20-5| ... | ... | @@ -1,12 +1,27 @@ |
| 1 | // Ported from musl, which is licensed under the MIT license: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/lnf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/ln.c | |
| 1 | //! Ported from musl, which is licensed under the MIT license: | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/lnf.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/ln.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 8 | 9 | const math = std.math; |
| 9 | 10 | const testing = std.testing; |
| 11 | const arch = builtin.cpu.arch; | |
| 12 | const common = @import("common.zig"); | |
| 13 | ||
| 14 | pub const panic = common.panic; | |
| 15 | ||
| 16 | comptime { | |
| 17 | @export(__logh, .{ .name = "__logh", .linkage = common.linkage }); | |
| 18 | @export(logf, .{ .name = "logf", .linkage = common.linkage }); | |
| 19 | @export(log, .{ .name = "log", .linkage = common.linkage }); | |
| 20 | @export(__logx, .{ .name = "__logx", .linkage = common.linkage }); | |
| 21 | const logq_sym_name = if (common.want_ppc_abi) "logf128" else "logq"; | |
| 22 | @export(logq, .{ .name = logq_sym_name, .linkage = common.linkage }); | |
| 23 | @export(logl, .{ .name = "logl", .linkage = common.linkage }); | |
| 24 | } | |
| 10 | 25 | |
| 11 | 26 | pub fn __logh(a: f16) callconv(.C) f16 { |
| 12 | 27 | // TODO: more efficient implementation |
lib/compiler_rt/log10.zig+20-5| ... | ... | @@ -1,13 +1,28 @@ |
| 1 | // Ported from musl, which is licensed under the MIT license: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log10f.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log10.c | |
| 1 | //! Ported from musl, which is licensed under the MIT license: | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/log10f.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/log10.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 8 | 9 | const math = std.math; |
| 9 | 10 | const testing = std.testing; |
| 10 | 11 | const maxInt = std.math.maxInt; |
| 12 | const arch = builtin.cpu.arch; | |
| 13 | const common = @import("common.zig"); | |
| 14 | ||
| 15 | pub const panic = common.panic; | |
| 16 | ||
| 17 | comptime { | |
| 18 | @export(__log10h, .{ .name = "__log10h", .linkage = common.linkage }); | |
| 19 | @export(log10f, .{ .name = "log10f", .linkage = common.linkage }); | |
| 20 | @export(log10, .{ .name = "log10", .linkage = common.linkage }); | |
| 21 | @export(__log10x, .{ .name = "__log10x", .linkage = common.linkage }); | |
| 22 | const log10q_sym_name = if (common.want_ppc_abi) "log10f128" else "log10q"; | |
| 23 | @export(log10q, .{ .name = log10q_sym_name, .linkage = common.linkage }); | |
| 24 | @export(log10l, .{ .name = "log10l", .linkage = common.linkage }); | |
| 25 | } | |
| 11 | 26 | |
| 12 | 27 | pub fn __log10h(a: f16) callconv(.C) f16 { |
| 13 | 28 | // TODO: more efficient implementation |
lib/compiler_rt/log2.zig+20-5| ... | ... | @@ -1,13 +1,28 @@ |
| 1 | // Ported from musl, which is licensed under the MIT license: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log2f.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/log2.c | |
| 1 | //! Ported from musl, which is licensed under the MIT license: | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/log2f.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/log2.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 8 | 9 | const math = std.math; |
| 9 | 10 | const expect = std.testing.expect; |
| 10 | 11 | const maxInt = std.math.maxInt; |
| 12 | const arch = builtin.cpu.arch; | |
| 13 | const common = @import("common.zig"); | |
| 14 | ||
| 15 | pub const panic = common.panic; | |
| 16 | ||
| 17 | comptime { | |
| 18 | @export(__log2h, .{ .name = "__log2h", .linkage = common.linkage }); | |
| 19 | @export(log2f, .{ .name = "log2f", .linkage = common.linkage }); | |
| 20 | @export(log2, .{ .name = "log2", .linkage = common.linkage }); | |
| 21 | @export(__log2x, .{ .name = "__log2x", .linkage = common.linkage }); | |
| 22 | const log2q_sym_name = if (common.want_ppc_abi) "log2f128" else "log2q"; | |
| 23 | @export(log2q, .{ .name = log2q_sym_name, .linkage = common.linkage }); | |
| 24 | @export(log2l, .{ .name = "log2l", .linkage = common.linkage }); | |
| 25 | } | |
| 11 | 26 | |
| 12 | 27 | pub fn __log2h(a: f16) callconv(.C) f16 { |
| 13 | 28 | // TODO: more efficient implementation |
lib/compiler_rt/modti3.zig+39-14| ... | ... | @@ -1,14 +1,47 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/modti3.c | |
| 1 | //! Ported from: | |
| 2 | //! | |
| 3 | //! https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/modti3.c | |
| 4 | 4 | |
| 5 | const udivmod = @import("udivmod.zig").udivmod; | |
| 5 | const std = @import("std"); | |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 7 | const udivmod = @import("udivmod.zig").udivmod; | |
| 8 | const arch = builtin.cpu.arch; | |
| 9 | const common = @import("common.zig"); | |
| 10 | ||
| 11 | pub const panic = common.panic; | |
| 12 | ||
| 13 | comptime { | |
| 14 | if (builtin.os.tag == .windows) { | |
| 15 | switch (arch) { | |
| 16 | .i386 => { | |
| 17 | @export(__modti3, .{ .name = "__modti3", .linkage = common.linkage }); | |
| 18 | }, | |
| 19 | .x86_64 => { | |
| 20 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | |
| 21 | // that LLVM expects compiler-rt to have. | |
| 22 | @export(__modti3_windows_x86_64, .{ .name = "__modti3", .linkage = common.linkage }); | |
| 23 | }, | |
| 24 | else => {}, | |
| 25 | } | |
| 26 | if (arch.isAARCH64()) { | |
| 27 | @export(__modti3, .{ .name = "__modti3", .linkage = common.linkage }); | |
| 28 | } | |
| 29 | } else { | |
| 30 | @export(__modti3, .{ .name = "__modti3", .linkage = common.linkage }); | |
| 31 | } | |
| 32 | } | |
| 8 | 33 | |
| 9 | 34 | pub fn __modti3(a: i128, b: i128) callconv(.C) i128 { |
| 10 | @setRuntimeSafety(builtin.is_test); | |
| 35 | return mod(a, b); | |
| 36 | } | |
| 11 | 37 | |
| 38 | const v128 = @import("std").meta.Vector(2, u64); | |
| 39 | ||
| 40 | fn __modti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 41 | return @bitCast(v128, mod(@bitCast(i128, a), @bitCast(i128, b))); | |
| 42 | } | |
| 43 | ||
| 44 | inline fn mod(a: i128, b: i128) i128 { | |
| 12 | 45 | const s_a = a >> (128 - 1); // s = a < 0 ? -1 : 0 |
| 13 | 46 | const s_b = b >> (128 - 1); // s = b < 0 ? -1 : 0 |
| 14 | 47 | |
| ... | ... | @@ -20,14 +53,6 @@ pub fn __modti3(a: i128, b: i128) callconv(.C) i128 { |
| 20 | 53 | return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -1 |
| 21 | 54 | } |
| 22 | 55 | |
| 23 | const v128 = @import("std").meta.Vector(2, u64); | |
| 24 | pub fn __modti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 25 | return @bitCast(v128, @call(.{ .modifier = .always_inline }, __modti3, .{ | |
| 26 | @bitCast(i128, a), | |
| 27 | @bitCast(i128, b), | |
| 28 | })); | |
| 29 | } | |
| 30 | ||
| 31 | 56 | test { |
| 32 | 57 | _ = @import("modti3_test.zig"); |
| 33 | 58 | } |
lib/compiler_rt/mulXf3.zig deleted-344| ... | ... | @@ -1,344 +0,0 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc | |
| 4 | ||
| 5 | const std = @import("std"); | |
| 6 | const math = std.math; | |
| 7 | const builtin = @import("builtin"); | |
| 8 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 9 | ||
| 10 | pub fn __multf3(a: f128, b: f128) callconv(.C) f128 { | |
| 11 | return mulXf3(f128, a, b); | |
| 12 | } | |
| 13 | pub fn __mulxf3(a: f80, b: f80) callconv(.C) f80 { | |
| 14 | return mulXf3(f80, a, b); | |
| 15 | } | |
| 16 | pub fn __muldf3(a: f64, b: f64) callconv(.C) f64 { | |
| 17 | return mulXf3(f64, a, b); | |
| 18 | } | |
| 19 | pub fn __mulsf3(a: f32, b: f32) callconv(.C) f32 { | |
| 20 | return mulXf3(f32, a, b); | |
| 21 | } | |
| 22 | ||
| 23 | pub fn __aeabi_fmul(a: f32, b: f32) callconv(.C) f32 { | |
| 24 | @setRuntimeSafety(false); | |
| 25 | return @call(.{ .modifier = .always_inline }, __mulsf3, .{ a, b }); | |
| 26 | } | |
| 27 | ||
| 28 | pub fn __aeabi_dmul(a: f64, b: f64) callconv(.C) f64 { | |
| 29 | @setRuntimeSafety(false); | |
| 30 | return @call(.{ .modifier = .always_inline }, __muldf3, .{ a, b }); | |
| 31 | } | |
| 32 | ||
| 33 | fn mulXf3(comptime T: type, a: T, b: T) T { | |
| 34 | @setRuntimeSafety(builtin.is_test); | |
| 35 | const typeWidth = @typeInfo(T).Float.bits; | |
| 36 | const significandBits = math.floatMantissaBits(T); | |
| 37 | const fractionalBits = math.floatFractionalBits(T); | |
| 38 | const exponentBits = math.floatExponentBits(T); | |
| 39 | ||
| 40 | const Z = std.meta.Int(.unsigned, typeWidth); | |
| 41 | ||
| 42 | // ZSignificand is large enough to contain the significand, including an explicit integer bit | |
| 43 | const ZSignificand = PowerOfTwoSignificandZ(T); | |
| 44 | const ZSignificandBits = @typeInfo(ZSignificand).Int.bits; | |
| 45 | ||
| 46 | const roundBit = (1 << (ZSignificandBits - 1)); | |
| 47 | const signBit = (@as(Z, 1) << (significandBits + exponentBits)); | |
| 48 | const maxExponent = ((1 << exponentBits) - 1); | |
| 49 | const exponentBias = (maxExponent >> 1); | |
| 50 | ||
| 51 | const integerBit = (@as(ZSignificand, 1) << fractionalBits); | |
| 52 | const quietBit = integerBit >> 1; | |
| 53 | const significandMask = (@as(Z, 1) << significandBits) - 1; | |
| 54 | ||
| 55 | const absMask = signBit - 1; | |
| 56 | const qnanRep = @bitCast(Z, math.nan(T)) | quietBit; | |
| 57 | const infRep = @bitCast(Z, math.inf(T)); | |
| 58 | const minNormalRep = @bitCast(Z, math.floatMin(T)); | |
| 59 | ||
| 60 | const aExponent = @truncate(u32, (@bitCast(Z, a) >> significandBits) & maxExponent); | |
| 61 | const bExponent = @truncate(u32, (@bitCast(Z, b) >> significandBits) & maxExponent); | |
| 62 | const productSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit; | |
| 63 | ||
| 64 | var aSignificand: ZSignificand = @intCast(ZSignificand, @bitCast(Z, a) & significandMask); | |
| 65 | var bSignificand: ZSignificand = @intCast(ZSignificand, @bitCast(Z, b) & significandMask); | |
| 66 | var scale: i32 = 0; | |
| 67 | ||
| 68 | // Detect if a or b is zero, denormal, infinity, or NaN. | |
| 69 | if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { | |
| 70 | const aAbs: Z = @bitCast(Z, a) & absMask; | |
| 71 | const bAbs: Z = @bitCast(Z, b) & absMask; | |
| 72 | ||
| 73 | // NaN * anything = qNaN | |
| 74 | if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit); | |
| 75 | // anything * NaN = qNaN | |
| 76 | if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit); | |
| 77 | ||
| 78 | if (aAbs == infRep) { | |
| 79 | // infinity * non-zero = +/- infinity | |
| 80 | if (bAbs != 0) { | |
| 81 | return @bitCast(T, aAbs | productSign); | |
| 82 | } else { | |
| 83 | // infinity * zero = NaN | |
| 84 | return @bitCast(T, qnanRep); | |
| 85 | } | |
| 86 | } | |
| 87 | ||
| 88 | if (bAbs == infRep) { | |
| 89 | //? non-zero * infinity = +/- infinity | |
| 90 | if (aAbs != 0) { | |
| 91 | return @bitCast(T, bAbs | productSign); | |
| 92 | } else { | |
| 93 | // zero * infinity = NaN | |
| 94 | return @bitCast(T, qnanRep); | |
| 95 | } | |
| 96 | } | |
| 97 | ||
| 98 | // zero * anything = +/- zero | |
| 99 | if (aAbs == 0) return @bitCast(T, productSign); | |
| 100 | // anything * zero = +/- zero | |
| 101 | if (bAbs == 0) return @bitCast(T, productSign); | |
| 102 | ||
| 103 | // one or both of a or b is denormal, the other (if applicable) is a | |
| 104 | // normal number. Renormalize one or both of a and b, and set scale to | |
| 105 | // include the necessary exponent adjustment. | |
| 106 | if (aAbs < minNormalRep) scale += normalize(T, &aSignificand); | |
| 107 | if (bAbs < minNormalRep) scale += normalize(T, &bSignificand); | |
| 108 | } | |
| 109 | ||
| 110 | // Or in the implicit significand bit. (If we fell through from the | |
| 111 | // denormal path it was already set by normalize( ), but setting it twice | |
| 112 | // won't hurt anything.) | |
| 113 | aSignificand |= integerBit; | |
| 114 | bSignificand |= integerBit; | |
| 115 | ||
| 116 | // Get the significand of a*b. Before multiplying the significands, shift | |
| 117 | // one of them left to left-align it in the field. Thus, the product will | |
| 118 | // have (exponentBits + 2) integral digits, all but two of which must be | |
| 119 | // zero. Normalizing this result is just a conditional left-shift by one | |
| 120 | // and bumping the exponent accordingly. | |
| 121 | var productHi: ZSignificand = undefined; | |
| 122 | var productLo: ZSignificand = undefined; | |
| 123 | const left_align_shift = ZSignificandBits - fractionalBits - 1; | |
| 124 | wideMultiply(ZSignificand, aSignificand, bSignificand << left_align_shift, &productHi, &productLo); | |
| 125 | ||
| 126 | var productExponent: i32 = @intCast(i32, aExponent + bExponent) - exponentBias + scale; | |
| 127 | ||
| 128 | // Normalize the significand, adjust exponent if needed. | |
| 129 | if ((productHi & integerBit) != 0) { | |
| 130 | productExponent +%= 1; | |
| 131 | } else { | |
| 132 | productHi = (productHi << 1) | (productLo >> (ZSignificandBits - 1)); | |
| 133 | productLo = productLo << 1; | |
| 134 | } | |
| 135 | ||
| 136 | // If we have overflowed the type, return +/- infinity. | |
| 137 | if (productExponent >= maxExponent) return @bitCast(T, infRep | productSign); | |
| 138 | ||
| 139 | var result: Z = undefined; | |
| 140 | if (productExponent <= 0) { | |
| 141 | // Result is denormal before rounding | |
| 142 | // | |
| 143 | // If the result is so small that it just underflows to zero, return | |
| 144 | // a zero of the appropriate sign. Mathematically there is no need to | |
| 145 | // handle this case separately, but we make it a special case to | |
| 146 | // simplify the shift logic. | |
| 147 | const shift: u32 = @truncate(u32, @as(Z, 1) -% @bitCast(u32, productExponent)); | |
| 148 | if (shift >= ZSignificandBits) return @bitCast(T, productSign); | |
| 149 | ||
| 150 | // Otherwise, shift the significand of the result so that the round | |
| 151 | // bit is the high bit of productLo. | |
| 152 | const sticky = wideShrWithTruncation(ZSignificand, &productHi, &productLo, shift); | |
| 153 | productLo |= @boolToInt(sticky); | |
| 154 | result = productHi; | |
| 155 | ||
| 156 | // We include the integer bit so that rounding will carry to the exponent, | |
| 157 | // but it will be removed later if the result is still denormal | |
| 158 | if (significandBits != fractionalBits) result |= integerBit; | |
| 159 | } else { | |
| 160 | // Result is normal before rounding; insert the exponent. | |
| 161 | result = productHi & significandMask; | |
| 162 | result |= @intCast(Z, productExponent) << significandBits; | |
| 163 | } | |
| 164 | ||
| 165 | // Final rounding. The final result may overflow to infinity, or underflow | |
| 166 | // to zero, but those are the correct results in those cases. We use the | |
| 167 | // default IEEE-754 round-to-nearest, ties-to-even rounding mode. | |
| 168 | if (productLo > roundBit) result +%= 1; | |
| 169 | if (productLo == roundBit) result +%= result & 1; | |
| 170 | ||
| 171 | // Restore any explicit integer bit, if it was rounded off | |
| 172 | if (significandBits != fractionalBits) { | |
| 173 | if ((result >> significandBits) != 0) { | |
| 174 | result |= integerBit; | |
| 175 | } else { | |
| 176 | result &= ~integerBit; | |
| 177 | } | |
| 178 | } | |
| 179 | ||
| 180 | // Insert the sign of the result: | |
| 181 | result |= productSign; | |
| 182 | ||
| 183 | return @bitCast(T, result); | |
| 184 | } | |
| 185 | ||
| 186 | fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { | |
| 187 | @setRuntimeSafety(builtin.is_test); | |
| 188 | switch (Z) { | |
| 189 | u16 => { | |
| 190 | // 16x16 --> 32 bit multiply | |
| 191 | const product = @as(u32, a) * @as(u32, b); | |
| 192 | hi.* = @intCast(u16, product >> 16); | |
| 193 | lo.* = @truncate(u16, product); | |
| 194 | }, | |
| 195 | u32 => { | |
| 196 | // 32x32 --> 64 bit multiply | |
| 197 | const product = @as(u64, a) * @as(u64, b); | |
| 198 | hi.* = @intCast(u32, product >> 32); | |
| 199 | lo.* = @truncate(u32, product); | |
| 200 | }, | |
| 201 | u64 => { | |
| 202 | const S = struct { | |
| 203 | fn loWord(x: u64) u64 { | |
| 204 | return @truncate(u32, x); | |
| 205 | } | |
| 206 | fn hiWord(x: u64) u64 { | |
| 207 | return @intCast(u32, x >> 32); | |
| 208 | } | |
| 209 | }; | |
| 210 | // 64x64 -> 128 wide multiply for platforms that don't have such an operation; | |
| 211 | // many 64-bit platforms have this operation, but they tend to have hardware | |
| 212 | // floating-point, so we don't bother with a special case for them here. | |
| 213 | // Each of the component 32x32 -> 64 products | |
| 214 | const plolo: u64 = S.loWord(a) * S.loWord(b); | |
| 215 | const plohi: u64 = S.loWord(a) * S.hiWord(b); | |
| 216 | const philo: u64 = S.hiWord(a) * S.loWord(b); | |
| 217 | const phihi: u64 = S.hiWord(a) * S.hiWord(b); | |
| 218 | // Sum terms that contribute to lo in a way that allows us to get the carry | |
| 219 | const r0: u64 = S.loWord(plolo); | |
| 220 | const r1: u64 = S.hiWord(plolo) +% S.loWord(plohi) +% S.loWord(philo); | |
| 221 | lo.* = r0 +% (r1 << 32); | |
| 222 | // Sum terms contributing to hi with the carry from lo | |
| 223 | hi.* = S.hiWord(plohi) +% S.hiWord(philo) +% S.hiWord(r1) +% phihi; | |
| 224 | }, | |
| 225 | u128 => { | |
| 226 | const Word_LoMask = @as(u64, 0x00000000ffffffff); | |
| 227 | const Word_HiMask = @as(u64, 0xffffffff00000000); | |
| 228 | const Word_FullMask = @as(u64, 0xffffffffffffffff); | |
| 229 | const S = struct { | |
| 230 | fn Word_1(x: u128) u64 { | |
| 231 | return @truncate(u32, x >> 96); | |
| 232 | } | |
| 233 | fn Word_2(x: u128) u64 { | |
| 234 | return @truncate(u32, x >> 64); | |
| 235 | } | |
| 236 | fn Word_3(x: u128) u64 { | |
| 237 | return @truncate(u32, x >> 32); | |
| 238 | } | |
| 239 | fn Word_4(x: u128) u64 { | |
| 240 | return @truncate(u32, x); | |
| 241 | } | |
| 242 | }; | |
| 243 | // 128x128 -> 256 wide multiply for platforms that don't have such an operation; | |
| 244 | // many 64-bit platforms have this operation, but they tend to have hardware | |
| 245 | // floating-point, so we don't bother with a special case for them here. | |
| 246 | ||
| 247 | const product11: u64 = S.Word_1(a) * S.Word_1(b); | |
| 248 | const product12: u64 = S.Word_1(a) * S.Word_2(b); | |
| 249 | const product13: u64 = S.Word_1(a) * S.Word_3(b); | |
| 250 | const product14: u64 = S.Word_1(a) * S.Word_4(b); | |
| 251 | const product21: u64 = S.Word_2(a) * S.Word_1(b); | |
| 252 | const product22: u64 = S.Word_2(a) * S.Word_2(b); | |
| 253 | const product23: u64 = S.Word_2(a) * S.Word_3(b); | |
| 254 | const product24: u64 = S.Word_2(a) * S.Word_4(b); | |
| 255 | const product31: u64 = S.Word_3(a) * S.Word_1(b); | |
| 256 | const product32: u64 = S.Word_3(a) * S.Word_2(b); | |
| 257 | const product33: u64 = S.Word_3(a) * S.Word_3(b); | |
| 258 | const product34: u64 = S.Word_3(a) * S.Word_4(b); | |
| 259 | const product41: u64 = S.Word_4(a) * S.Word_1(b); | |
| 260 | const product42: u64 = S.Word_4(a) * S.Word_2(b); | |
| 261 | const product43: u64 = S.Word_4(a) * S.Word_3(b); | |
| 262 | const product44: u64 = S.Word_4(a) * S.Word_4(b); | |
| 263 | ||
| 264 | const sum0: u128 = @as(u128, product44); | |
| 265 | const sum1: u128 = @as(u128, product34) +% | |
| 266 | @as(u128, product43); | |
| 267 | const sum2: u128 = @as(u128, product24) +% | |
| 268 | @as(u128, product33) +% | |
| 269 | @as(u128, product42); | |
| 270 | const sum3: u128 = @as(u128, product14) +% | |
| 271 | @as(u128, product23) +% | |
| 272 | @as(u128, product32) +% | |
| 273 | @as(u128, product41); | |
| 274 | const sum4: u128 = @as(u128, product13) +% | |
| 275 | @as(u128, product22) +% | |
| 276 | @as(u128, product31); | |
| 277 | const sum5: u128 = @as(u128, product12) +% | |
| 278 | @as(u128, product21); | |
| 279 | const sum6: u128 = @as(u128, product11); | |
| 280 | ||
| 281 | const r0: u128 = (sum0 & Word_FullMask) +% | |
| 282 | ((sum1 & Word_LoMask) << 32); | |
| 283 | const r1: u128 = (sum0 >> 64) +% | |
| 284 | ((sum1 >> 32) & Word_FullMask) +% | |
| 285 | (sum2 & Word_FullMask) +% | |
| 286 | ((sum3 << 32) & Word_HiMask); | |
| 287 | ||
| 288 | lo.* = r0 +% (r1 << 64); | |
| 289 | hi.* = (r1 >> 64) +% | |
| 290 | (sum1 >> 96) +% | |
| 291 | (sum2 >> 64) +% | |
| 292 | (sum3 >> 32) +% | |
| 293 | sum4 +% | |
| 294 | (sum5 << 32) +% | |
| 295 | (sum6 << 64); | |
| 296 | }, | |
| 297 | else => @compileError("unsupported"), | |
| 298 | } | |
| 299 | } | |
| 300 | ||
| 301 | /// Returns a power-of-two integer type that is large enough to contain | |
| 302 | /// the significand of T, including an explicit integer bit | |
| 303 | fn PowerOfTwoSignificandZ(comptime T: type) type { | |
| 304 | const bits = math.ceilPowerOfTwoAssert(u16, math.floatFractionalBits(T) + 1); | |
| 305 | return std.meta.Int(.unsigned, bits); | |
| 306 | } | |
| 307 | ||
| 308 | fn normalize(comptime T: type, significand: *PowerOfTwoSignificandZ(T)) i32 { | |
| 309 | @setRuntimeSafety(builtin.is_test); | |
| 310 | const Z = PowerOfTwoSignificandZ(T); | |
| 311 | const integerBit = @as(Z, 1) << math.floatFractionalBits(T); | |
| 312 | ||
| 313 | const shift = @clz(Z, significand.*) - @clz(Z, integerBit); | |
| 314 | significand.* <<= @intCast(math.Log2Int(Z), shift); | |
| 315 | return @as(i32, 1) - shift; | |
| 316 | } | |
| 317 | ||
| 318 | // Returns `true` if the right shift is inexact (i.e. any bit shifted out is non-zero) | |
| 319 | // | |
| 320 | // This is analogous to an shr version of `@shlWithOverflow` | |
| 321 | fn wideShrWithTruncation(comptime Z: type, hi: *Z, lo: *Z, count: u32) bool { | |
| 322 | @setRuntimeSafety(builtin.is_test); | |
| 323 | const typeWidth = @typeInfo(Z).Int.bits; | |
| 324 | const S = math.Log2Int(Z); | |
| 325 | var inexact = false; | |
| 326 | if (count < typeWidth) { | |
| 327 | inexact = (lo.* << @intCast(S, typeWidth -% count)) != 0; | |
| 328 | lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count)); | |
| 329 | hi.* = hi.* >> @intCast(S, count); | |
| 330 | } else if (count < 2 * typeWidth) { | |
| 331 | inexact = (hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*) != 0; | |
| 332 | lo.* = hi.* >> @intCast(S, count -% typeWidth); | |
| 333 | hi.* = 0; | |
| 334 | } else { | |
| 335 | inexact = (hi.* | lo.*) != 0; | |
| 336 | lo.* = 0; | |
| 337 | hi.* = 0; | |
| 338 | } | |
| 339 | return inexact; | |
| 340 | } | |
| 341 | ||
| 342 | test { | |
| 343 | _ = @import("mulXf3_test.zig"); | |
| 344 | } |
lib/compiler_rt/mulXf3_test.zig deleted-171| ... | ... | @@ -1,171 +0,0 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/test/builtins/Unit/multf3_test.c | |
| 4 | ||
| 5 | const std = @import("std"); | |
| 6 | const math = std.math; | |
| 7 | const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64); | |
| 8 | const inf128 = @bitCast(f128, @as(u128, 0x7fff000000000000) << 64); | |
| 9 | ||
| 10 | const __multf3 = @import("mulXf3.zig").__multf3; | |
| 11 | const __mulxf3 = @import("mulXf3.zig").__mulxf3; | |
| 12 | const __muldf3 = @import("mulXf3.zig").__muldf3; | |
| 13 | const __mulsf3 = @import("mulXf3.zig").__mulsf3; | |
| 14 | ||
| 15 | // return true if equal | |
| 16 | // use two 64-bit integers intead of one 128-bit integer | |
| 17 | // because 128-bit integer constant can't be assigned directly | |
| 18 | fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { | |
| 19 | const rep = @bitCast(u128, result); | |
| 20 | const hi = @intCast(u64, rep >> 64); | |
| 21 | const lo = @truncate(u64, rep); | |
| 22 | ||
| 23 | if (hi == expectedHi and lo == expectedLo) { | |
| 24 | return true; | |
| 25 | } | |
| 26 | // test other possible NaN representation(signal NaN) | |
| 27 | if (expectedHi == 0x7fff800000000000 and expectedLo == 0x0) { | |
| 28 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 29 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 30 | { | |
| 31 | return true; | |
| 32 | } | |
| 33 | } | |
| 34 | return false; | |
| 35 | } | |
| 36 | ||
| 37 | fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { | |
| 38 | const x = __multf3(a, b); | |
| 39 | ||
| 40 | if (compareResultLD(x, expected_hi, expected_lo)) | |
| 41 | return; | |
| 42 | ||
| 43 | @panic("__multf3 test failure"); | |
| 44 | } | |
| 45 | ||
| 46 | fn makeNaN128(rand: u64) f128 { | |
| 47 | const int_result = @as(u128, 0x7fff000000000000 | (rand & 0xffffffffffff)) << 64; | |
| 48 | const float_result = @bitCast(f128, int_result); | |
| 49 | return float_result; | |
| 50 | } | |
| 51 | test "multf3" { | |
| 52 | // qNaN * any = qNaN | |
| 53 | try test__multf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 54 | ||
| 55 | // NaN * any = NaN | |
| 56 | const a = makeNaN128(0x800030000000); | |
| 57 | try test__multf3(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 58 | // inf * any = inf | |
| 59 | try test__multf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); | |
| 60 | ||
| 61 | // any * any | |
| 62 | try test__multf3( | |
| 63 | @bitCast(f128, @as(u128, 0x40042eab345678439abcdefea5678234)), | |
| 64 | @bitCast(f128, @as(u128, 0x3ffeedcb34a235253948765432134675)), | |
| 65 | 0x400423e7f9e3c9fc, | |
| 66 | 0xd906c2c2a85777c4, | |
| 67 | ); | |
| 68 | ||
| 69 | try test__multf3( | |
| 70 | @bitCast(f128, @as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50)), | |
| 71 | @bitCast(f128, @as(u128, 0x3ff6ed8764648369535adf4be3214568)), | |
| 72 | 0x3fc52a163c6223fc, | |
| 73 | 0xc94c4bf0430768b4, | |
| 74 | ); | |
| 75 | ||
| 76 | try test__multf3( | |
| 77 | 0x1.234425696abcad34a35eeffefdcbap+456, | |
| 78 | 0x451.ed98d76e5d46e5f24323dff21ffp+600, | |
| 79 | 0x44293a91de5e0e94, | |
| 80 | 0xe8ed17cc2cdf64ac, | |
| 81 | ); | |
| 82 | ||
| 83 | try test__multf3( | |
| 84 | @bitCast(f128, @as(u128, 0x3f154356473c82a9fabf2d22ace345df)), | |
| 85 | @bitCast(f128, @as(u128, 0x3e38eda98765476743ab21da23d45679)), | |
| 86 | 0x3d4f37c1a3137cae, | |
| 87 | 0xfc6807048bc2836a, | |
| 88 | ); | |
| 89 | ||
| 90 | try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0); | |
| 91 | ||
| 92 | // Denormal operands. | |
| 93 | try test__multf3( | |
| 94 | 0x0.0000000000000000000000000001p-16382, | |
| 95 | 0x1p16383, | |
| 96 | 0x3f90000000000000, | |
| 97 | 0x0, | |
| 98 | ); | |
| 99 | try test__multf3( | |
| 100 | 0x1p16383, | |
| 101 | 0x0.0000000000000000000000000001p-16382, | |
| 102 | 0x3f90000000000000, | |
| 103 | 0x0, | |
| 104 | ); | |
| 105 | ||
| 106 | try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002); | |
| 107 | try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003); | |
| 108 | try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002); | |
| 109 | } | |
| 110 | ||
| 111 | const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1))); | |
| 112 | ||
| 113 | fn test__mulxf3(a: f80, b: f80, expected: u80) !void { | |
| 114 | const x = __mulxf3(a, b); | |
| 115 | const rep = @bitCast(u80, x); | |
| 116 | ||
| 117 | if (rep == expected) | |
| 118 | return; | |
| 119 | ||
| 120 | if (math.isNan(@bitCast(f80, expected)) and math.isNan(x)) | |
| 121 | return; // We don't currently test NaN payload propagation | |
| 122 | ||
| 123 | return error.TestFailed; | |
| 124 | } | |
| 125 | ||
| 126 | test "mulxf3" { | |
| 127 | // NaN * any = NaN | |
| 128 | try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @bitCast(u80, qnan80)); | |
| 129 | try test__mulxf3(@bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), 0x1.23456789abcdefp+5, @bitCast(u80, qnan80)); | |
| 130 | ||
| 131 | // any * NaN = NaN | |
| 132 | try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @bitCast(u80, qnan80)); | |
| 133 | try test__mulxf3(0x1.23456789abcdefp+5, @bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), @bitCast(u80, qnan80)); | |
| 134 | ||
| 135 | // NaN * inf = NaN | |
| 136 | try test__mulxf3(qnan80, math.inf(f80), @bitCast(u80, qnan80)); | |
| 137 | ||
| 138 | // inf * NaN = NaN | |
| 139 | try test__mulxf3(math.inf(f80), qnan80, @bitCast(u80, qnan80)); | |
| 140 | ||
| 141 | // inf * inf = inf | |
| 142 | try test__mulxf3(math.inf(f80), math.inf(f80), @bitCast(u80, math.inf(f80))); | |
| 143 | ||
| 144 | // inf * -inf = -inf | |
| 145 | try test__mulxf3(math.inf(f80), -math.inf(f80), @bitCast(u80, -math.inf(f80))); | |
| 146 | ||
| 147 | // -inf + inf = -inf | |
| 148 | try test__mulxf3(-math.inf(f80), math.inf(f80), @bitCast(u80, -math.inf(f80))); | |
| 149 | ||
| 150 | // inf * any = inf | |
| 151 | try test__mulxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @bitCast(u80, math.inf(f80))); | |
| 152 | ||
| 153 | // any * inf = inf | |
| 154 | try test__mulxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @bitCast(u80, math.inf(f80))); | |
| 155 | ||
| 156 | // any * any | |
| 157 | try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800); | |
| 158 | try test__mulxf3(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact | |
| 159 | ||
| 160 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact | |
| 161 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down | |
| 162 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even | |
| 163 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up | |
| 164 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact | |
| 165 | ||
| 166 | try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even | |
| 167 | try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up | |
| 168 | try test__mulxf3(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal | |
| 169 | try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal | |
| 170 | try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal | |
| 171 | } |
lib/compiler_rt/muldf3.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const mulf3 = @import("./mulf3.zig").mulf3; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_dmul, .{ .name = "__aeabi_dmul", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__muldf3, .{ .name = "__muldf3", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __muldf3(a: f64, b: f64) callconv(.C) f64 { | |
| 15 | return mulf3(f64, a, b); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_dmul(a: f64, b: f64) callconv(.AAPCS) f64 { | |
| 19 | return mulf3(f64, a, b); | |
| 20 | } |
lib/compiler_rt/muldi3.zig+30-16| ... | ... | @@ -1,10 +1,36 @@ |
| 1 | //! Ported from | |
| 2 | //! https://github.com/llvm/llvm-project/blob/llvmorg-9.0.0/compiler-rt/lib/builtins/muldi3.c | |
| 3 | ||
| 1 | 4 | const std = @import("std"); |
| 2 | 5 | const builtin = @import("builtin"); |
| 3 | const is_test = builtin.is_test; | |
| 4 | 6 | const native_endian = builtin.cpu.arch.endian(); |
| 7 | const common = @import("common.zig"); | |
| 8 | ||
| 9 | pub const panic = common.panic; | |
| 10 | ||
| 11 | comptime { | |
| 12 | if (common.want_aeabi) { | |
| 13 | @export(__aeabi_lmul, .{ .name = "__aeabi_lmul", .linkage = common.linkage }); | |
| 14 | } else { | |
| 15 | @export(__muldi3, .{ .name = "__muldi3", .linkage = common.linkage }); | |
| 16 | } | |
| 17 | } | |
| 18 | ||
| 19 | pub fn __muldi3(a: i64, b: i64) callconv(.C) i64 { | |
| 20 | return mul(a, b); | |
| 21 | } | |
| 5 | 22 | |
| 6 | // Ported from | |
| 7 | // https://github.com/llvm/llvm-project/blob/llvmorg-9.0.0/compiler-rt/lib/builtins/muldi3.c | |
| 23 | fn __aeabi_lmul(a: i64, b: i64) callconv(.AAPCS) i64 { | |
| 24 | return mul(a, b); | |
| 25 | } | |
| 26 | ||
| 27 | inline fn mul(a: i64, b: i64) i64 { | |
| 28 | const x = dwords{ .all = a }; | |
| 29 | const y = dwords{ .all = b }; | |
| 30 | var r = dwords{ .all = muldsi3(x.s.low, y.s.low) }; | |
| 31 | r.s.high +%= x.s.high *% y.s.low +% x.s.low *% y.s.high; | |
| 32 | return r.all; | |
| 33 | } | |
| 8 | 34 | |
| 9 | 35 | const dwords = extern union { |
| 10 | 36 | all: i64, |
| ... | ... | @@ -20,9 +46,7 @@ const dwords = extern union { |
| 20 | 46 | }, |
| 21 | 47 | }; |
| 22 | 48 | |
| 23 | fn __muldsi3(a: u32, b: u32) i64 { | |
| 24 | @setRuntimeSafety(is_test); | |
| 25 | ||
| 49 | fn muldsi3(a: u32, b: u32) i64 { | |
| 26 | 50 | const bits_in_word_2 = @sizeOf(i32) * 8 / 2; |
| 27 | 51 | const lower_mask = (~@as(u32, 0)) >> bits_in_word_2; |
| 28 | 52 | |
| ... | ... | @@ -42,16 +66,6 @@ fn __muldsi3(a: u32, b: u32) i64 { |
| 42 | 66 | return r.all; |
| 43 | 67 | } |
| 44 | 68 | |
| 45 | pub fn __muldi3(a: i64, b: i64) callconv(.C) i64 { | |
| 46 | @setRuntimeSafety(is_test); | |
| 47 | ||
| 48 | const x = dwords{ .all = a }; | |
| 49 | const y = dwords{ .all = b }; | |
| 50 | var r = dwords{ .all = __muldsi3(x.s.low, y.s.low) }; | |
| 51 | r.s.high +%= x.s.high *% y.s.low +% x.s.low *% y.s.high; | |
| 52 | return r.all; | |
| 53 | } | |
| 54 | ||
| 55 | 69 | test { |
| 56 | 70 | _ = @import("muldi3_test.zig"); |
| 57 | 71 | } |
lib/compiler_rt/mulf3.zig created+203| ... | ... | @@ -0,0 +1,203 @@ |
| 1 | const std = @import("std"); | |
| 2 | const math = std.math; | |
| 3 | const builtin = @import("builtin"); | |
| 4 | const common = @import("./common.zig"); | |
| 5 | ||
| 6 | /// Ported from: | |
| 7 | /// https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc | |
| 8 | pub inline fn mulf3(comptime T: type, a: T, b: T) T { | |
| 9 | @setRuntimeSafety(builtin.is_test); | |
| 10 | const typeWidth = @typeInfo(T).Float.bits; | |
| 11 | const significandBits = math.floatMantissaBits(T); | |
| 12 | const fractionalBits = math.floatFractionalBits(T); | |
| 13 | const exponentBits = math.floatExponentBits(T); | |
| 14 | ||
| 15 | const Z = std.meta.Int(.unsigned, typeWidth); | |
| 16 | ||
| 17 | // ZSignificand is large enough to contain the significand, including an explicit integer bit | |
| 18 | const ZSignificand = PowerOfTwoSignificandZ(T); | |
| 19 | const ZSignificandBits = @typeInfo(ZSignificand).Int.bits; | |
| 20 | ||
| 21 | const roundBit = (1 << (ZSignificandBits - 1)); | |
| 22 | const signBit = (@as(Z, 1) << (significandBits + exponentBits)); | |
| 23 | const maxExponent = ((1 << exponentBits) - 1); | |
| 24 | const exponentBias = (maxExponent >> 1); | |
| 25 | ||
| 26 | const integerBit = (@as(ZSignificand, 1) << fractionalBits); | |
| 27 | const quietBit = integerBit >> 1; | |
| 28 | const significandMask = (@as(Z, 1) << significandBits) - 1; | |
| 29 | ||
| 30 | const absMask = signBit - 1; | |
| 31 | const qnanRep = @bitCast(Z, math.nan(T)) | quietBit; | |
| 32 | const infRep = @bitCast(Z, math.inf(T)); | |
| 33 | const minNormalRep = @bitCast(Z, math.floatMin(T)); | |
| 34 | ||
| 35 | const aExponent = @truncate(u32, (@bitCast(Z, a) >> significandBits) & maxExponent); | |
| 36 | const bExponent = @truncate(u32, (@bitCast(Z, b) >> significandBits) & maxExponent); | |
| 37 | const productSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit; | |
| 38 | ||
| 39 | var aSignificand: ZSignificand = @intCast(ZSignificand, @bitCast(Z, a) & significandMask); | |
| 40 | var bSignificand: ZSignificand = @intCast(ZSignificand, @bitCast(Z, b) & significandMask); | |
| 41 | var scale: i32 = 0; | |
| 42 | ||
| 43 | // Detect if a or b is zero, denormal, infinity, or NaN. | |
| 44 | if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) { | |
| 45 | const aAbs: Z = @bitCast(Z, a) & absMask; | |
| 46 | const bAbs: Z = @bitCast(Z, b) & absMask; | |
| 47 | ||
| 48 | // NaN * anything = qNaN | |
| 49 | if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit); | |
| 50 | // anything * NaN = qNaN | |
| 51 | if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit); | |
| 52 | ||
| 53 | if (aAbs == infRep) { | |
| 54 | // infinity * non-zero = +/- infinity | |
| 55 | if (bAbs != 0) { | |
| 56 | return @bitCast(T, aAbs | productSign); | |
| 57 | } else { | |
| 58 | // infinity * zero = NaN | |
| 59 | return @bitCast(T, qnanRep); | |
| 60 | } | |
| 61 | } | |
| 62 | ||
| 63 | if (bAbs == infRep) { | |
| 64 | //? non-zero * infinity = +/- infinity | |
| 65 | if (aAbs != 0) { | |
| 66 | return @bitCast(T, bAbs | productSign); | |
| 67 | } else { | |
| 68 | // zero * infinity = NaN | |
| 69 | return @bitCast(T, qnanRep); | |
| 70 | } | |
| 71 | } | |
| 72 | ||
| 73 | // zero * anything = +/- zero | |
| 74 | if (aAbs == 0) return @bitCast(T, productSign); | |
| 75 | // anything * zero = +/- zero | |
| 76 | if (bAbs == 0) return @bitCast(T, productSign); | |
| 77 | ||
| 78 | // one or both of a or b is denormal, the other (if applicable) is a | |
| 79 | // normal number. Renormalize one or both of a and b, and set scale to | |
| 80 | // include the necessary exponent adjustment. | |
| 81 | if (aAbs < minNormalRep) scale += normalize(T, &aSignificand); | |
| 82 | if (bAbs < minNormalRep) scale += normalize(T, &bSignificand); | |
| 83 | } | |
| 84 | ||
| 85 | // Or in the implicit significand bit. (If we fell through from the | |
| 86 | // denormal path it was already set by normalize( ), but setting it twice | |
| 87 | // won't hurt anything.) | |
| 88 | aSignificand |= integerBit; | |
| 89 | bSignificand |= integerBit; | |
| 90 | ||
| 91 | // Get the significand of a*b. Before multiplying the significands, shift | |
| 92 | // one of them left to left-align it in the field. Thus, the product will | |
| 93 | // have (exponentBits + 2) integral digits, all but two of which must be | |
| 94 | // zero. Normalizing this result is just a conditional left-shift by one | |
| 95 | // and bumping the exponent accordingly. | |
| 96 | var productHi: ZSignificand = undefined; | |
| 97 | var productLo: ZSignificand = undefined; | |
| 98 | const left_align_shift = ZSignificandBits - fractionalBits - 1; | |
| 99 | common.wideMultiply(ZSignificand, aSignificand, bSignificand << left_align_shift, &productHi, &productLo); | |
| 100 | ||
| 101 | var productExponent: i32 = @intCast(i32, aExponent + bExponent) - exponentBias + scale; | |
| 102 | ||
| 103 | // Normalize the significand, adjust exponent if needed. | |
| 104 | if ((productHi & integerBit) != 0) { | |
| 105 | productExponent +%= 1; | |
| 106 | } else { | |
| 107 | productHi = (productHi << 1) | (productLo >> (ZSignificandBits - 1)); | |
| 108 | productLo = productLo << 1; | |
| 109 | } | |
| 110 | ||
| 111 | // If we have overflowed the type, return +/- infinity. | |
| 112 | if (productExponent >= maxExponent) return @bitCast(T, infRep | productSign); | |
| 113 | ||
| 114 | var result: Z = undefined; | |
| 115 | if (productExponent <= 0) { | |
| 116 | // Result is denormal before rounding | |
| 117 | // | |
| 118 | // If the result is so small that it just underflows to zero, return | |
| 119 | // a zero of the appropriate sign. Mathematically there is no need to | |
| 120 | // handle this case separately, but we make it a special case to | |
| 121 | // simplify the shift logic. | |
| 122 | const shift: u32 = @truncate(u32, @as(Z, 1) -% @bitCast(u32, productExponent)); | |
| 123 | if (shift >= ZSignificandBits) return @bitCast(T, productSign); | |
| 124 | ||
| 125 | // Otherwise, shift the significand of the result so that the round | |
| 126 | // bit is the high bit of productLo. | |
| 127 | const sticky = wideShrWithTruncation(ZSignificand, &productHi, &productLo, shift); | |
| 128 | productLo |= @boolToInt(sticky); | |
| 129 | result = productHi; | |
| 130 | ||
| 131 | // We include the integer bit so that rounding will carry to the exponent, | |
| 132 | // but it will be removed later if the result is still denormal | |
| 133 | if (significandBits != fractionalBits) result |= integerBit; | |
| 134 | } else { | |
| 135 | // Result is normal before rounding; insert the exponent. | |
| 136 | result = productHi & significandMask; | |
| 137 | result |= @intCast(Z, productExponent) << significandBits; | |
| 138 | } | |
| 139 | ||
| 140 | // Final rounding. The final result may overflow to infinity, or underflow | |
| 141 | // to zero, but those are the correct results in those cases. We use the | |
| 142 | // default IEEE-754 round-to-nearest, ties-to-even rounding mode. | |
| 143 | if (productLo > roundBit) result +%= 1; | |
| 144 | if (productLo == roundBit) result +%= result & 1; | |
| 145 | ||
| 146 | // Restore any explicit integer bit, if it was rounded off | |
| 147 | if (significandBits != fractionalBits) { | |
| 148 | if ((result >> significandBits) != 0) { | |
| 149 | result |= integerBit; | |
| 150 | } else { | |
| 151 | result &= ~integerBit; | |
| 152 | } | |
| 153 | } | |
| 154 | ||
| 155 | // Insert the sign of the result: | |
| 156 | result |= productSign; | |
| 157 | ||
| 158 | return @bitCast(T, result); | |
| 159 | } | |
| 160 | ||
| 161 | /// Returns `true` if the right shift is inexact (i.e. any bit shifted out is non-zero) | |
| 162 | /// | |
| 163 | /// This is analogous to an shr version of `@shlWithOverflow` | |
| 164 | fn wideShrWithTruncation(comptime Z: type, hi: *Z, lo: *Z, count: u32) bool { | |
| 165 | @setRuntimeSafety(builtin.is_test); | |
| 166 | const typeWidth = @typeInfo(Z).Int.bits; | |
| 167 | const S = math.Log2Int(Z); | |
| 168 | var inexact = false; | |
| 169 | if (count < typeWidth) { | |
| 170 | inexact = (lo.* << @intCast(S, typeWidth -% count)) != 0; | |
| 171 | lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count)); | |
| 172 | hi.* = hi.* >> @intCast(S, count); | |
| 173 | } else if (count < 2 * typeWidth) { | |
| 174 | inexact = (hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*) != 0; | |
| 175 | lo.* = hi.* >> @intCast(S, count -% typeWidth); | |
| 176 | hi.* = 0; | |
| 177 | } else { | |
| 178 | inexact = (hi.* | lo.*) != 0; | |
| 179 | lo.* = 0; | |
| 180 | hi.* = 0; | |
| 181 | } | |
| 182 | return inexact; | |
| 183 | } | |
| 184 | ||
| 185 | fn normalize(comptime T: type, significand: *PowerOfTwoSignificandZ(T)) i32 { | |
| 186 | const Z = PowerOfTwoSignificandZ(T); | |
| 187 | const integerBit = @as(Z, 1) << math.floatFractionalBits(T); | |
| 188 | ||
| 189 | const shift = @clz(Z, significand.*) - @clz(Z, integerBit); | |
| 190 | significand.* <<= @intCast(math.Log2Int(Z), shift); | |
| 191 | return @as(i32, 1) - shift; | |
| 192 | } | |
| 193 | ||
| 194 | /// Returns a power-of-two integer type that is large enough to contain | |
| 195 | /// the significand of T, including an explicit integer bit | |
| 196 | fn PowerOfTwoSignificandZ(comptime T: type) type { | |
| 197 | const bits = math.ceilPowerOfTwoAssert(u16, math.floatFractionalBits(T) + 1); | |
| 198 | return std.meta.Int(.unsigned, bits); | |
| 199 | } | |
| 200 | ||
| 201 | test { | |
| 202 | _ = @import("mulf3_test.zig"); | |
| 203 | } |
lib/compiler_rt/mulf3_test.zig created+171| ... | ... | @@ -0,0 +1,171 @@ |
| 1 | // Ported from: | |
| 2 | // | |
| 3 | // https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/test/builtins/Unit/multf3_test.c | |
| 4 | ||
| 5 | const std = @import("std"); | |
| 6 | const math = std.math; | |
| 7 | const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64); | |
| 8 | const inf128 = @bitCast(f128, @as(u128, 0x7fff000000000000) << 64); | |
| 9 | ||
| 10 | const __multf3 = @import("multf3.zig").__multf3; | |
| 11 | const __mulxf3 = @import("mulxf3.zig").__mulxf3; | |
| 12 | const __muldf3 = @import("muldf3.zig").__muldf3; | |
| 13 | const __mulsf3 = @import("mulsf3.zig").__mulsf3; | |
| 14 | ||
| 15 | // return true if equal | |
| 16 | // use two 64-bit integers intead of one 128-bit integer | |
| 17 | // because 128-bit integer constant can't be assigned directly | |
| 18 | fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { | |
| 19 | const rep = @bitCast(u128, result); | |
| 20 | const hi = @intCast(u64, rep >> 64); | |
| 21 | const lo = @truncate(u64, rep); | |
| 22 | ||
| 23 | if (hi == expectedHi and lo == expectedLo) { | |
| 24 | return true; | |
| 25 | } | |
| 26 | // test other possible NaN representation(signal NaN) | |
| 27 | if (expectedHi == 0x7fff800000000000 and expectedLo == 0x0) { | |
| 28 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and | |
| 29 | ((hi & 0xffffffffffff) > 0 or lo > 0)) | |
| 30 | { | |
| 31 | return true; | |
| 32 | } | |
| 33 | } | |
| 34 | return false; | |
| 35 | } | |
| 36 | ||
| 37 | fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { | |
| 38 | const x = __multf3(a, b); | |
| 39 | ||
| 40 | if (compareResultLD(x, expected_hi, expected_lo)) | |
| 41 | return; | |
| 42 | ||
| 43 | @panic("__multf3 test failure"); | |
| 44 | } | |
| 45 | ||
| 46 | fn makeNaN128(rand: u64) f128 { | |
| 47 | const int_result = @as(u128, 0x7fff000000000000 | (rand & 0xffffffffffff)) << 64; | |
| 48 | const float_result = @bitCast(f128, int_result); | |
| 49 | return float_result; | |
| 50 | } | |
| 51 | test "multf3" { | |
| 52 | // qNaN * any = qNaN | |
| 53 | try test__multf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 54 | ||
| 55 | // NaN * any = NaN | |
| 56 | const a = makeNaN128(0x800030000000); | |
| 57 | try test__multf3(a, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 58 | // inf * any = inf | |
| 59 | try test__multf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); | |
| 60 | ||
| 61 | // any * any | |
| 62 | try test__multf3( | |
| 63 | @bitCast(f128, @as(u128, 0x40042eab345678439abcdefea5678234)), | |
| 64 | @bitCast(f128, @as(u128, 0x3ffeedcb34a235253948765432134675)), | |
| 65 | 0x400423e7f9e3c9fc, | |
| 66 | 0xd906c2c2a85777c4, | |
| 67 | ); | |
| 68 | ||
| 69 | try test__multf3( | |
| 70 | @bitCast(f128, @as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50)), | |
| 71 | @bitCast(f128, @as(u128, 0x3ff6ed8764648369535adf4be3214568)), | |
| 72 | 0x3fc52a163c6223fc, | |
| 73 | 0xc94c4bf0430768b4, | |
| 74 | ); | |
| 75 | ||
| 76 | try test__multf3( | |
| 77 | 0x1.234425696abcad34a35eeffefdcbap+456, | |
| 78 | 0x451.ed98d76e5d46e5f24323dff21ffp+600, | |
| 79 | 0x44293a91de5e0e94, | |
| 80 | 0xe8ed17cc2cdf64ac, | |
| 81 | ); | |
| 82 | ||
| 83 | try test__multf3( | |
| 84 | @bitCast(f128, @as(u128, 0x3f154356473c82a9fabf2d22ace345df)), | |
| 85 | @bitCast(f128, @as(u128, 0x3e38eda98765476743ab21da23d45679)), | |
| 86 | 0x3d4f37c1a3137cae, | |
| 87 | 0xfc6807048bc2836a, | |
| 88 | ); | |
| 89 | ||
| 90 | try test__multf3(0x1.23456734245345p-10000, 0x1.edcba524498724p-6497, 0x0, 0x0); | |
| 91 | ||
| 92 | // Denormal operands. | |
| 93 | try test__multf3( | |
| 94 | 0x0.0000000000000000000000000001p-16382, | |
| 95 | 0x1p16383, | |
| 96 | 0x3f90000000000000, | |
| 97 | 0x0, | |
| 98 | ); | |
| 99 | try test__multf3( | |
| 100 | 0x1p16383, | |
| 101 | 0x0.0000000000000000000000000001p-16382, | |
| 102 | 0x3f90000000000000, | |
| 103 | 0x0, | |
| 104 | ); | |
| 105 | ||
| 106 | try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002); | |
| 107 | try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003); | |
| 108 | try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002); | |
| 109 | } | |
| 110 | ||
| 111 | const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1))); | |
| 112 | ||
| 113 | fn test__mulxf3(a: f80, b: f80, expected: u80) !void { | |
| 114 | const x = __mulxf3(a, b); | |
| 115 | const rep = @bitCast(u80, x); | |
| 116 | ||
| 117 | if (rep == expected) | |
| 118 | return; | |
| 119 | ||
| 120 | if (math.isNan(@bitCast(f80, expected)) and math.isNan(x)) | |
| 121 | return; // We don't currently test NaN payload propagation | |
| 122 | ||
| 123 | return error.TestFailed; | |
| 124 | } | |
| 125 | ||
| 126 | test "mulxf3" { | |
| 127 | // NaN * any = NaN | |
| 128 | try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @bitCast(u80, qnan80)); | |
| 129 | try test__mulxf3(@bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), 0x1.23456789abcdefp+5, @bitCast(u80, qnan80)); | |
| 130 | ||
| 131 | // any * NaN = NaN | |
| 132 | try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @bitCast(u80, qnan80)); | |
| 133 | try test__mulxf3(0x1.23456789abcdefp+5, @bitCast(f80, @as(u80, 0x7fff_8000_8000_3000_0000)), @bitCast(u80, qnan80)); | |
| 134 | ||
| 135 | // NaN * inf = NaN | |
| 136 | try test__mulxf3(qnan80, math.inf(f80), @bitCast(u80, qnan80)); | |
| 137 | ||
| 138 | // inf * NaN = NaN | |
| 139 | try test__mulxf3(math.inf(f80), qnan80, @bitCast(u80, qnan80)); | |
| 140 | ||
| 141 | // inf * inf = inf | |
| 142 | try test__mulxf3(math.inf(f80), math.inf(f80), @bitCast(u80, math.inf(f80))); | |
| 143 | ||
| 144 | // inf * -inf = -inf | |
| 145 | try test__mulxf3(math.inf(f80), -math.inf(f80), @bitCast(u80, -math.inf(f80))); | |
| 146 | ||
| 147 | // -inf + inf = -inf | |
| 148 | try test__mulxf3(-math.inf(f80), math.inf(f80), @bitCast(u80, -math.inf(f80))); | |
| 149 | ||
| 150 | // inf * any = inf | |
| 151 | try test__mulxf3(math.inf(f80), 0x1.2335653452436234723489432abcdefp+5, @bitCast(u80, math.inf(f80))); | |
| 152 | ||
| 153 | // any * inf = inf | |
| 154 | try test__mulxf3(0x1.2335653452436234723489432abcdefp+5, math.inf(f80), @bitCast(u80, math.inf(f80))); | |
| 155 | ||
| 156 | // any * any | |
| 157 | try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800); | |
| 158 | try test__mulxf3(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact | |
| 159 | ||
| 160 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact | |
| 161 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down | |
| 162 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even | |
| 163 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up | |
| 164 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact | |
| 165 | ||
| 166 | try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even | |
| 167 | try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up | |
| 168 | try test__mulxf3(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal | |
| 169 | try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal | |
| 170 | try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal | |
| 171 | } |
lib/compiler_rt/mulo.zig+10-3| ... | ... | @@ -1,6 +1,15 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | 3 | const math = std.math; |
| 4 | const common = @import("common.zig"); | |
| 5 | ||
| 6 | pub const panic = common.panic; | |
| 7 | ||
| 8 | comptime { | |
| 9 | @export(__mulosi4, .{ .name = "__mulosi4", .linkage = common.linkage }); | |
| 10 | @export(__mulodi4, .{ .name = "__mulodi4", .linkage = common.linkage }); | |
| 11 | @export(__muloti4, .{ .name = "__muloti4", .linkage = common.linkage }); | |
| 12 | } | |
| 4 | 13 | |
| 5 | 14 | // mulo - multiplication overflow |
| 6 | 15 | // * return a*%b. |
| ... | ... | @@ -9,7 +18,6 @@ const math = std.math; |
| 9 | 18 | // - muloXi4_genericFast for 2*bitsize <= usize |
| 10 | 19 | |
| 11 | 20 | inline fn muloXi4_genericSmall(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST { |
| 12 | @setRuntimeSafety(builtin.is_test); | |
| 13 | 21 | overflow.* = 0; |
| 14 | 22 | const min = math.minInt(ST); |
| 15 | 23 | var res: ST = a *% b; |
| ... | ... | @@ -24,7 +32,6 @@ inline fn muloXi4_genericSmall(comptime ST: type, a: ST, b: ST, overflow: *c_int |
| 24 | 32 | } |
| 25 | 33 | |
| 26 | 34 | inline fn muloXi4_genericFast(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST { |
| 27 | @setRuntimeSafety(builtin.is_test); | |
| 28 | 35 | overflow.* = 0; |
| 29 | 36 | const EST = switch (ST) { |
| 30 | 37 | i32 => i64, |
lib/compiler_rt/mulsf3.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const mulf3 = @import("./mulf3.zig").mulf3; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_fmul, .{ .name = "__aeabi_fmul", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__mulsf3, .{ .name = "__mulsf3", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __mulsf3(a: f32, b: f32) callconv(.C) f32 { | |
| 15 | return mulf3(f32, a, b); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_fmul(a: f32, b: f32) callconv(.AAPCS) f32 { | |
| 19 | return mulf3(f32, a, b); | |
| 20 | } |
lib/compiler_rt/multf3.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const mulf3 = @import("./mulf3.zig").mulf3; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__mulkf3, .{ .name = "__mulkf3", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_mul, .{ .name = "_Qp_mul", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__multf3, .{ .name = "__multf3", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __multf3(a: f128, b: f128) callconv(.C) f128 { | |
| 17 | return mulf3(f128, a, b); | |
| 18 | } | |
| 19 | ||
| 20 | fn __mulkf3(a: f128, b: f128) callconv(.C) f128 { | |
| 21 | return mulf3(f128, a, b); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.C) void { | |
| 25 | c.* = mulf3(f128, a.*, b.*); | |
| 26 | } |
lib/compiler_rt/multi3.zig+37-16| ... | ... | @@ -1,31 +1,52 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 1 | //! Ported from git@github.com:llvm-project/llvm-project-20170507.git | |
| 2 | //! ae684fad6d34858c014c94da69c15e7774a633c3 | |
| 3 | //! 2018-08-13 | |
| 4 | ||
| 2 | 5 | const std = @import("std"); |
| 3 | 6 | const builtin = @import("builtin"); |
| 4 | const is_test = builtin.is_test; | |
| 7 | const arch = builtin.cpu.arch; | |
| 5 | 8 | const native_endian = builtin.cpu.arch.endian(); |
| 9 | const common = @import("common.zig"); | |
| 10 | ||
| 11 | pub const panic = common.panic; | |
| 6 | 12 | |
| 7 | // Ported from git@github.com:llvm-project/llvm-project-20170507.git | |
| 8 | // ae684fad6d34858c014c94da69c15e7774a633c3 | |
| 9 | // 2018-08-13 | |
| 13 | comptime { | |
| 14 | if (builtin.os.tag == .windows) { | |
| 15 | switch (arch) { | |
| 16 | .i386 => { | |
| 17 | @export(__multi3, .{ .name = "__multi3", .linkage = common.linkage }); | |
| 18 | }, | |
| 19 | .x86_64 => { | |
| 20 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | |
| 21 | // that LLVM expects compiler-rt to have. | |
| 22 | @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = common.linkage }); | |
| 23 | }, | |
| 24 | else => {}, | |
| 25 | } | |
| 26 | } else { | |
| 27 | @export(__multi3, .{ .name = "__multi3", .linkage = common.linkage }); | |
| 28 | } | |
| 29 | } | |
| 10 | 30 | |
| 11 | 31 | pub fn __multi3(a: i128, b: i128) callconv(.C) i128 { |
| 12 | @setRuntimeSafety(is_test); | |
| 32 | return mul(a, b); | |
| 33 | } | |
| 34 | ||
| 35 | const v128 = @Vector(2, u64); | |
| 36 | ||
| 37 | fn __multi3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 38 | return @bitCast(v128, mul(@bitCast(i128, a), @bitCast(i128, b))); | |
| 39 | } | |
| 40 | ||
| 41 | inline fn mul(a: i128, b: i128) i128 { | |
| 13 | 42 | const x = twords{ .all = a }; |
| 14 | 43 | const y = twords{ .all = b }; |
| 15 | var r = twords{ .all = __mulddi3(x.s.low, y.s.low) }; | |
| 44 | var r = twords{ .all = mulddi3(x.s.low, y.s.low) }; | |
| 16 | 45 | r.s.high +%= x.s.high *% y.s.low +% x.s.low *% y.s.high; |
| 17 | 46 | return r.all; |
| 18 | 47 | } |
| 19 | 48 | |
| 20 | const v128 = @Vector(2, u64); | |
| 21 | pub fn __multi3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 22 | return @bitCast(v128, @call(.{ .modifier = .always_inline }, __multi3, .{ | |
| 23 | @bitCast(i128, a), | |
| 24 | @bitCast(i128, b), | |
| 25 | })); | |
| 26 | } | |
| 27 | ||
| 28 | fn __mulddi3(a: u64, b: u64) i128 { | |
| 49 | fn mulddi3(a: u64, b: u64) i128 { | |
| 29 | 50 | const bits_in_dword_2 = (@sizeOf(i64) * 8) / 2; |
| 30 | 51 | const lower_mask = ~@as(u64, 0) >> bits_in_dword_2; |
| 31 | 52 | var r: twords = undefined; |
lib/compiler_rt/mulxf3.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const mulf3 = @import("./mulf3.zig").mulf3; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__mulxf3, .{ .name = "__mulxf3", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __mulxf3(a: f80, b: f80) callconv(.C) f80 { | |
| 11 | return mulf3(f80, a, b); | |
| 12 | } |
lib/compiler_rt/negXf2.zig+21-9| ... | ... | @@ -1,24 +1,36 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | const common = @import("common.zig"); | |
| 4 | ||
| 5 | pub const panic = common.panic; | |
| 6 | ||
| 7 | comptime { | |
| 8 | if (common.want_aeabi) { | |
| 9 | @export(__aeabi_fneg, .{ .name = "__aeabi_fneg", .linkage = common.linkage }); | |
| 10 | @export(__aeabi_dneg, .{ .name = "__aeabi_dneg", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__negsf2, .{ .name = "__negsf2", .linkage = common.linkage }); | |
| 13 | @export(__negdf2, .{ .name = "__negdf2", .linkage = common.linkage }); | |
| 14 | } | |
| 15 | } | |
| 2 | 16 | |
| 3 | 17 | pub fn __negsf2(a: f32) callconv(.C) f32 { |
| 4 | 18 | return negXf2(f32, a); |
| 5 | 19 | } |
| 6 | 20 | |
| 7 | pub fn __negdf2(a: f64) callconv(.C) f64 { | |
| 8 | return negXf2(f64, a); | |
| 21 | fn __aeabi_fneg(a: f32) callconv(.AAPCS) f32 { | |
| 22 | return negXf2(f32, a); | |
| 9 | 23 | } |
| 10 | 24 | |
| 11 | pub fn __aeabi_fneg(arg: f32) callconv(.AAPCS) f32 { | |
| 12 | @setRuntimeSafety(false); | |
| 13 | return @call(.{ .modifier = .always_inline }, __negsf2, .{arg}); | |
| 25 | pub fn __negdf2(a: f64) callconv(.C) f64 { | |
| 26 | return negXf2(f64, a); | |
| 14 | 27 | } |
| 15 | 28 | |
| 16 | pub fn __aeabi_dneg(arg: f64) callconv(.AAPCS) f64 { | |
| 17 | @setRuntimeSafety(false); | |
| 18 | return @call(.{ .modifier = .always_inline }, __negdf2, .{arg}); | |
| 29 | fn __aeabi_dneg(a: f64) callconv(.AAPCS) f64 { | |
| 30 | return negXf2(f64, a); | |
| 19 | 31 | } |
| 20 | 32 | |
| 21 | fn negXf2(comptime T: type, a: T) T { | |
| 33 | inline fn negXf2(comptime T: type, a: T) T { | |
| 22 | 34 | const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits); |
| 23 | 35 | |
| 24 | 36 | const significandBits = std.math.floatMantissaBits(T); |
lib/compiler_rt/negXi2.zig+18-12| ... | ... | @@ -1,19 +1,21 @@ |
| 1 | //! neg - negate (the number) | |
| 2 | //! - negXi2 for unoptimized little and big endian | |
| 3 | //! sfffffff = 2^31-1 | |
| 4 | //! two's complement inverting bits and add 1 would result in -INT_MIN == 0 | |
| 5 | //! => -INT_MIN = -2^31 forbidden | |
| 6 | //! * size optimized builds | |
| 7 | //! * machines that dont support carry operations | |
| 8 | ||
| 1 | 9 | const std = @import("std"); |
| 2 | 10 | const builtin = @import("builtin"); |
| 11 | const common = @import("common.zig"); | |
| 3 | 12 | |
| 4 | // neg - negate (the number) | |
| 5 | // - negXi2 for unoptimized little and big endian | |
| 6 | ||
| 7 | // sfffffff = 2^31-1 | |
| 8 | // two's complement inverting bits and add 1 would result in -INT_MIN == 0 | |
| 9 | // => -INT_MIN = -2^31 forbidden | |
| 10 | ||
| 11 | // * size optimized builds | |
| 12 | // * machines that dont support carry operations | |
| 13 | pub const panic = common.panic; | |
| 13 | 14 | |
| 14 | inline fn negXi2(comptime T: type, a: T) T { | |
| 15 | @setRuntimeSafety(builtin.is_test); | |
| 16 | return -a; | |
| 15 | comptime { | |
| 16 | @export(__negsi2, .{ .name = "__negsi2", .linkage = common.linkage }); | |
| 17 | @export(__negdi2, .{ .name = "__negdi2", .linkage = common.linkage }); | |
| 18 | @export(__negti2, .{ .name = "__negti2", .linkage = common.linkage }); | |
| 17 | 19 | } |
| 18 | 20 | |
| 19 | 21 | pub fn __negsi2(a: i32) callconv(.C) i32 { |
| ... | ... | @@ -28,6 +30,10 @@ pub fn __negti2(a: i128) callconv(.C) i128 { |
| 28 | 30 | return negXi2(i128, a); |
| 29 | 31 | } |
| 30 | 32 | |
| 33 | inline fn negXi2(comptime T: type, a: T) T { | |
| 34 | return -a; | |
| 35 | } | |
| 36 | ||
| 31 | 37 | test { |
| 32 | 38 | _ = @import("negsi2_test.zig"); |
| 33 | 39 | _ = @import("negdi2_test.zig"); |
lib/compiler_rt/negv.zig+26-16| ... | ... | @@ -1,20 +1,16 @@ |
| 1 | // negv - negate oVerflow | |
| 2 | // * @panic, if result can not be represented | |
| 3 | // - negvXi4_generic for unoptimized version | |
| 1 | //! negv - negate oVerflow | |
| 2 | //! * @panic, if result can not be represented | |
| 3 | //! - negvXi4_generic for unoptimized version | |
| 4 | const std = @import("std"); | |
| 5 | const builtin = @import("builtin"); | |
| 6 | const common = @import("common.zig"); | |
| 4 | 7 | |
| 5 | // assume -0 == 0 is gracefully handled by the hardware | |
| 6 | inline fn negvXi(comptime ST: type, a: ST) ST { | |
| 7 | const UT = switch (ST) { | |
| 8 | i32 => u32, | |
| 9 | i64 => u64, | |
| 10 | i128 => u128, | |
| 11 | else => unreachable, | |
| 12 | }; | |
| 13 | const N: UT = @bitSizeOf(ST); | |
| 14 | const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1))); | |
| 15 | if (a == min) | |
| 16 | @panic("compiler_rt negv: overflow"); | |
| 17 | return -a; | |
| 8 | pub const panic = common.panic; | |
| 9 | ||
| 10 | comptime { | |
| 11 | @export(__negvsi2, .{ .name = "__negvsi2", .linkage = common.linkage }); | |
| 12 | @export(__negvdi2, .{ .name = "__negvdi2", .linkage = common.linkage }); | |
| 13 | @export(__negvti2, .{ .name = "__negvti2", .linkage = common.linkage }); | |
| 18 | 14 | } |
| 19 | 15 | |
| 20 | 16 | pub fn __negvsi2(a: i32) callconv(.C) i32 { |
| ... | ... | @@ -29,6 +25,20 @@ pub fn __negvti2(a: i128) callconv(.C) i128 { |
| 29 | 25 | return negvXi(i128, a); |
| 30 | 26 | } |
| 31 | 27 | |
| 28 | inline fn negvXi(comptime ST: type, a: ST) ST { | |
| 29 | const UT = switch (ST) { | |
| 30 | i32 => u32, | |
| 31 | i64 => u64, | |
| 32 | i128 => u128, | |
| 33 | else => unreachable, | |
| 34 | }; | |
| 35 | const N: UT = @bitSizeOf(ST); | |
| 36 | const min: ST = @bitCast(ST, (@as(UT, 1) << (N - 1))); | |
| 37 | if (a == min) | |
| 38 | @panic("compiler_rt negv: overflow"); | |
| 39 | return -a; | |
| 40 | } | |
| 41 | ||
| 32 | 42 | test { |
| 33 | 43 | _ = @import("negvsi2_test.zig"); |
| 34 | 44 | _ = @import("negvdi2_test.zig"); |
lib/compiler_rt/os_version_check.zig+32-21| ... | ... | @@ -1,5 +1,14 @@ |
| 1 | const testing = @import("std").testing; | |
| 1 | const std = @import("std"); | |
| 2 | const testing = std.testing; | |
| 2 | 3 | const builtin = @import("builtin"); |
| 4 | const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak; | |
| 5 | pub const panic = @import("common.zig").panic; | |
| 6 | ||
| 7 | comptime { | |
| 8 | if (builtin.os.tag.isDarwin()) { | |
| 9 | @export(__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = linkage }); | |
| 10 | } | |
| 11 | } | |
| 3 | 12 | |
| 4 | 13 | // Ported from llvm-project 13.0.0 d7b669b3a30345cfcdb2fde2af6f48aa4b94845d |
| 5 | 14 | // |
| ... | ... | @@ -16,30 +25,32 @@ const builtin = @import("builtin"); |
| 16 | 25 | // the newer codepath, which merely calls out to the Darwin _availability_version_check API which is |
| 17 | 26 | // available on macOS 10.15+, iOS 13+, tvOS 13+ and watchOS 6+. |
| 18 | 27 | |
| 19 | inline fn constructVersion(major: u32, minor: u32, subminor: u32) u32 { | |
| 20 | return ((major & 0xffff) << 16) | ((minor & 0xff) << 8) | (subminor & 0xff); | |
| 21 | } | |
| 28 | const __isPlatformVersionAtLeast = if (builtin.os.tag.isDarwin()) struct { | |
| 29 | inline fn constructVersion(major: u32, minor: u32, subminor: u32) u32 { | |
| 30 | return ((major & 0xffff) << 16) | ((minor & 0xff) << 8) | (subminor & 0xff); | |
| 31 | } | |
| 22 | 32 | |
| 23 | // Darwin-only | |
| 24 | pub fn __isPlatformVersionAtLeast(platform: u32, major: u32, minor: u32, subminor: u32) callconv(.C) i32 { | |
| 25 | const build_version = dyld_build_version_t{ | |
| 26 | .platform = platform, | |
| 27 | .version = constructVersion(major, minor, subminor), | |
| 28 | }; | |
| 29 | return @boolToInt(_availability_version_check(1, &[_]dyld_build_version_t{build_version})); | |
| 30 | } | |
| 33 | // Darwin-only | |
| 34 | fn __isPlatformVersionAtLeast(platform: u32, major: u32, minor: u32, subminor: u32) callconv(.C) i32 { | |
| 35 | const build_version = dyld_build_version_t{ | |
| 36 | .platform = platform, | |
| 37 | .version = constructVersion(major, minor, subminor), | |
| 38 | }; | |
| 39 | return @boolToInt(_availability_version_check(1, &[_]dyld_build_version_t{build_version})); | |
| 40 | } | |
| 31 | 41 | |
| 32 | // _availability_version_check darwin API support. | |
| 33 | const dyld_platform_t = u32; | |
| 34 | const dyld_build_version_t = extern struct { | |
| 35 | platform: dyld_platform_t, | |
| 36 | version: u32, | |
| 37 | }; | |
| 38 | // Darwin-only | |
| 39 | extern "c" fn _availability_version_check(count: u32, versions: [*c]const dyld_build_version_t) bool; | |
| 42 | // _availability_version_check darwin API support. | |
| 43 | const dyld_platform_t = u32; | |
| 44 | const dyld_build_version_t = extern struct { | |
| 45 | platform: dyld_platform_t, | |
| 46 | version: u32, | |
| 47 | }; | |
| 48 | // Darwin-only | |
| 49 | extern "c" fn _availability_version_check(count: u32, versions: [*c]const dyld_build_version_t) bool; | |
| 50 | }.__isPlatformVersionAtLeast else struct {}; | |
| 40 | 51 | |
| 41 | 52 | test "isPlatformVersionAtLeast" { |
| 42 | if (!builtin.os.tag.isDarwin()) return error.SkipZigTest; | |
| 53 | if (!comptime builtin.os.tag.isDarwin()) return error.SkipZigTest; | |
| 43 | 54 | |
| 44 | 55 | // Note: this test depends on the actual host OS version since it is merely calling into the |
| 45 | 56 | // native Darwin API. |
lib/compiler_rt/parity.zig+23-16| ... | ... | @@ -1,12 +1,31 @@ |
| 1 | //! parity - if number of bits set is even => 0, else => 1 | |
| 2 | //! - pariytXi2_generic for big and little endian | |
| 3 | ||
| 1 | 4 | const std = @import("std"); |
| 2 | 5 | const builtin = @import("builtin"); |
| 6 | const common = @import("common.zig"); | |
| 3 | 7 | |
| 4 | // parity - if number of bits set is even => 0, else => 1 | |
| 5 | // - pariytXi2_generic for big and little endian | |
| 8 | pub const panic = common.panic; | |
| 6 | 9 | |
| 7 | inline fn parityXi2(comptime T: type, a: T) i32 { | |
| 8 | @setRuntimeSafety(builtin.is_test); | |
| 10 | comptime { | |
| 11 | @export(__paritysi2, .{ .name = "__paritysi2", .linkage = common.linkage }); | |
| 12 | @export(__paritydi2, .{ .name = "__paritydi2", .linkage = common.linkage }); | |
| 13 | @export(__parityti2, .{ .name = "__parityti2", .linkage = common.linkage }); | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __paritysi2(a: i32) callconv(.C) i32 { | |
| 17 | return parityXi2(i32, a); | |
| 18 | } | |
| 19 | ||
| 20 | pub fn __paritydi2(a: i64) callconv(.C) i32 { | |
| 21 | return parityXi2(i64, a); | |
| 22 | } | |
| 23 | ||
| 24 | pub fn __parityti2(a: i128) callconv(.C) i32 { | |
| 25 | return parityXi2(i128, a); | |
| 26 | } | |
| 9 | 27 | |
| 28 | inline fn parityXi2(comptime T: type, a: T) i32 { | |
| 10 | 29 | var x = switch (@bitSizeOf(T)) { |
| 11 | 30 | 32 => @bitCast(u32, a), |
| 12 | 31 | 64 => @bitCast(u64, a), |
| ... | ... | @@ -23,18 +42,6 @@ inline fn parityXi2(comptime T: type, a: T) i32 { |
| 23 | 42 | return (@intCast(u16, 0x6996) >> @intCast(u4, x)) & 1; // optimization for >>2 and >>1 |
| 24 | 43 | } |
| 25 | 44 | |
| 26 | pub fn __paritysi2(a: i32) callconv(.C) i32 { | |
| 27 | return parityXi2(i32, a); | |
| 28 | } | |
| 29 | ||
| 30 | pub fn __paritydi2(a: i64) callconv(.C) i32 { | |
| 31 | return parityXi2(i64, a); | |
| 32 | } | |
| 33 | ||
| 34 | pub fn __parityti2(a: i128) callconv(.C) i32 { | |
| 35 | return parityXi2(i128, a); | |
| 36 | } | |
| 37 | ||
| 38 | 45 | test { |
| 39 | 46 | _ = @import("paritysi2_test.zig"); |
| 40 | 47 | _ = @import("paritydi2_test.zig"); |
lib/compiler_rt/popcount.zig+27-20| ... | ... | @@ -1,17 +1,36 @@ |
| 1 | //! popcount - population count | |
| 2 | //! counts the number of 1 bits | |
| 3 | //! SWAR-Popcount: count bits of duos, aggregate to nibbles, and bytes inside | |
| 4 | //! x-bit register in parallel to sum up all bytes | |
| 5 | //! SWAR-Masks and factors can be defined as 2-adic fractions | |
| 6 | //! TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques, | |
| 7 | //! subsubsection "Working with the rightmost bits" and "Sideways addition". | |
| 8 | ||
| 1 | 9 | const builtin = @import("builtin"); |
| 2 | 10 | const std = @import("std"); |
| 11 | const common = @import("common.zig"); | |
| 12 | ||
| 13 | pub const panic = common.panic; | |
| 14 | ||
| 15 | comptime { | |
| 16 | @export(__popcountsi2, .{ .name = "__popcountsi2", .linkage = common.linkage }); | |
| 17 | @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = common.linkage }); | |
| 18 | @export(__popcountti2, .{ .name = "__popcountti2", .linkage = common.linkage }); | |
| 19 | } | |
| 3 | 20 | |
| 4 | // popcount - population count | |
| 5 | // counts the number of 1 bits | |
| 21 | pub fn __popcountsi2(a: i32) callconv(.C) i32 { | |
| 22 | return popcountXi2(i32, a); | |
| 23 | } | |
| 6 | 24 | |
| 7 | // SWAR-Popcount: count bits of duos, aggregate to nibbles, and bytes inside | |
| 8 | // x-bit register in parallel to sum up all bytes | |
| 9 | // SWAR-Masks and factors can be defined as 2-adic fractions | |
| 10 | // TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques, | |
| 11 | // subsubsection "Working with the rightmost bits" and "Sideways addition". | |
| 25 | pub fn __popcountdi2(a: i64) callconv(.C) i32 { | |
| 26 | return popcountXi2(i64, a); | |
| 27 | } | |
| 28 | ||
| 29 | pub fn __popcountti2(a: i128) callconv(.C) i32 { | |
| 30 | return popcountXi2(i128, a); | |
| 31 | } | |
| 12 | 32 | |
| 13 | 33 | inline fn popcountXi2(comptime ST: type, a: ST) i32 { |
| 14 | @setRuntimeSafety(builtin.is_test); | |
| 15 | 34 | const UT = switch (ST) { |
| 16 | 35 | i32 => u32, |
| 17 | 36 | i64 => u64, |
| ... | ... | @@ -30,18 +49,6 @@ inline fn popcountXi2(comptime ST: type, a: ST) i32 { |
| 30 | 49 | return @intCast(i32, x); |
| 31 | 50 | } |
| 32 | 51 | |
| 33 | pub fn __popcountsi2(a: i32) callconv(.C) i32 { | |
| 34 | return popcountXi2(i32, a); | |
| 35 | } | |
| 36 | ||
| 37 | pub fn __popcountdi2(a: i64) callconv(.C) i32 { | |
| 38 | return popcountXi2(i64, a); | |
| 39 | } | |
| 40 | ||
| 41 | pub fn __popcountti2(a: i128) callconv(.C) i32 { | |
| 42 | return popcountXi2(i128, a); | |
| 43 | } | |
| 44 | ||
| 45 | 52 | test { |
| 46 | 53 | _ = @import("popcountsi2_test.zig"); |
| 47 | 54 | _ = @import("popcountdi2_test.zig"); |
lib/compiler_rt/round.zig+20-5| ... | ... | @@ -1,12 +1,27 @@ |
| 1 | // Ported from musl, which is licensed under the MIT license: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/roundf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/round.c | |
| 1 | //! Ported from musl, which is licensed under the MIT license: | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/roundf.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/round.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 8 | 9 | const math = std.math; |
| 9 | 10 | const expect = std.testing.expect; |
| 11 | const arch = builtin.cpu.arch; | |
| 12 | const common = @import("common.zig"); | |
| 13 | ||
| 14 | pub const panic = common.panic; | |
| 15 | ||
| 16 | comptime { | |
| 17 | @export(__roundh, .{ .name = "__roundh", .linkage = common.linkage }); | |
| 18 | @export(roundf, .{ .name = "roundf", .linkage = common.linkage }); | |
| 19 | @export(round, .{ .name = "round", .linkage = common.linkage }); | |
| 20 | @export(__roundx, .{ .name = "__roundx", .linkage = common.linkage }); | |
| 21 | const roundq_sym_name = if (common.want_ppc_abi) "roundf128" else "roundq"; | |
| 22 | @export(roundq, .{ .name = roundq_sym_name, .linkage = common.linkage }); | |
| 23 | @export(roundl, .{ .name = "roundl", .linkage = common.linkage }); | |
| 24 | } | |
| 10 | 25 | |
| 11 | 26 | pub fn __roundh(x: f16) callconv(.C) f16 { |
| 12 | 27 | // TODO: more efficient implementation |
lib/compiler_rt/shift.zig+42-18| ... | ... | @@ -1,13 +1,33 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 2 | 3 | const Log2Int = std.math.Log2Int; |
| 3 | const native_endian = @import("builtin").cpu.arch.endian(); | |
| 4 | const native_endian = builtin.cpu.arch.endian(); | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | @export(__ashlti3, .{ .name = "__ashlti3", .linkage = common.linkage }); | |
| 11 | @export(__ashrti3, .{ .name = "__ashrti3", .linkage = common.linkage }); | |
| 12 | @export(__lshrti3, .{ .name = "__lshrti3", .linkage = common.linkage }); | |
| 13 | ||
| 14 | if (common.want_aeabi) { | |
| 15 | @export(__aeabi_llsl, .{ .name = "__aeabi_llsl", .linkage = common.linkage }); | |
| 16 | @export(__aeabi_lasr, .{ .name = "__aeabi_lasr", .linkage = common.linkage }); | |
| 17 | @export(__aeabi_llsr, .{ .name = "__aeabi_llsr", .linkage = common.linkage }); | |
| 18 | } else { | |
| 19 | @export(__ashldi3, .{ .name = "__ashldi3", .linkage = common.linkage }); | |
| 20 | @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = common.linkage }); | |
| 21 | @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = common.linkage }); | |
| 22 | } | |
| 23 | } | |
| 4 | 24 | |
| 5 | 25 | fn Dwords(comptime T: type, comptime signed_half: bool) type { |
| 6 | 26 | return extern union { |
| 7 | pub const bits = @divExact(@typeInfo(T).Int.bits, 2); | |
| 8 | pub const HalfTU = std.meta.Int(.unsigned, bits); | |
| 9 | pub const HalfTS = std.meta.Int(.signed, bits); | |
| 10 | pub const HalfT = if (signed_half) HalfTS else HalfTU; | |
| 27 | const bits = @divExact(@typeInfo(T).Int.bits, 2); | |
| 28 | const HalfTU = std.meta.Int(.unsigned, bits); | |
| 29 | const HalfTS = std.meta.Int(.signed, bits); | |
| 30 | const HalfT = if (signed_half) HalfTS else HalfTU; | |
| 11 | 31 | |
| 12 | 32 | all: T, |
| 13 | 33 | s: if (native_endian == .Little) |
| ... | ... | @@ -19,7 +39,7 @@ fn Dwords(comptime T: type, comptime signed_half: bool) type { |
| 19 | 39 | |
| 20 | 40 | // Arithmetic shift left |
| 21 | 41 | // Precondition: 0 <= b < bits_in_dword |
| 22 | pub inline fn ashlXi3(comptime T: type, a: T, b: i32) T { | |
| 42 | inline fn ashlXi3(comptime T: type, a: T, b: i32) T { | |
| 23 | 43 | const dwords = Dwords(T, false); |
| 24 | 44 | const S = Log2Int(dwords.HalfT); |
| 25 | 45 | |
| ... | ... | @@ -42,7 +62,7 @@ pub inline fn ashlXi3(comptime T: type, a: T, b: i32) T { |
| 42 | 62 | |
| 43 | 63 | // Arithmetic shift right |
| 44 | 64 | // Precondition: 0 <= b < T.bit_count |
| 45 | pub inline fn ashrXi3(comptime T: type, a: T, b: i32) T { | |
| 65 | inline fn ashrXi3(comptime T: type, a: T, b: i32) T { | |
| 46 | 66 | const dwords = Dwords(T, true); |
| 47 | 67 | const S = Log2Int(dwords.HalfT); |
| 48 | 68 | |
| ... | ... | @@ -69,7 +89,7 @@ pub inline fn ashrXi3(comptime T: type, a: T, b: i32) T { |
| 69 | 89 | |
| 70 | 90 | // Logical shift right |
| 71 | 91 | // Precondition: 0 <= b < T.bit_count |
| 72 | pub inline fn lshrXi3(comptime T: type, a: T, b: i32) T { | |
| 92 | inline fn lshrXi3(comptime T: type, a: T, b: i32) T { | |
| 73 | 93 | const dwords = Dwords(T, false); |
| 74 | 94 | const S = Log2Int(dwords.HalfT); |
| 75 | 95 | |
| ... | ... | @@ -93,30 +113,34 @@ pub inline fn lshrXi3(comptime T: type, a: T, b: i32) T { |
| 93 | 113 | pub fn __ashldi3(a: i64, b: i32) callconv(.C) i64 { |
| 94 | 114 | return ashlXi3(i64, a, b); |
| 95 | 115 | } |
| 116 | fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 { | |
| 117 | return ashlXi3(i64, a, b); | |
| 118 | } | |
| 119 | ||
| 96 | 120 | pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 { |
| 97 | 121 | return ashlXi3(i128, a, b); |
| 98 | 122 | } |
| 123 | ||
| 99 | 124 | pub fn __ashrdi3(a: i64, b: i32) callconv(.C) i64 { |
| 100 | 125 | return ashrXi3(i64, a, b); |
| 101 | 126 | } |
| 127 | fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 { | |
| 128 | return ashrXi3(i64, a, b); | |
| 129 | } | |
| 130 | ||
| 102 | 131 | pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 { |
| 103 | 132 | return ashrXi3(i128, a, b); |
| 104 | 133 | } |
| 134 | ||
| 105 | 135 | pub fn __lshrdi3(a: i64, b: i32) callconv(.C) i64 { |
| 106 | 136 | return lshrXi3(i64, a, b); |
| 107 | 137 | } |
| 108 | pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 { | |
| 109 | return lshrXi3(i128, a, b); | |
| 138 | fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 { | |
| 139 | return lshrXi3(i64, a, b); | |
| 110 | 140 | } |
| 111 | 141 | |
| 112 | pub fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 { | |
| 113 | return ashlXi3(i64, a, b); | |
| 114 | } | |
| 115 | pub fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 { | |
| 116 | return ashrXi3(i64, a, b); | |
| 117 | } | |
| 118 | pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 { | |
| 119 | return lshrXi3(i64, a, b); | |
| 142 | pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 { | |
| 143 | return lshrXi3(i128, a, b); | |
| 120 | 144 | } |
| 121 | 145 | |
| 122 | 146 | test { |
lib/compiler_rt/sin.zig+20-5| ... | ... | @@ -1,17 +1,32 @@ |
| 1 | // Ported from musl, which is licensed under the MIT license: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/sinf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/sin.c | |
| 1 | //! Ported from musl, which is licensed under the MIT license: | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/sinf.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/sin.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 9 | const arch = builtin.cpu.arch; | |
| 8 | 10 | const math = std.math; |
| 9 | 11 | const expect = std.testing.expect; |
| 12 | const common = @import("common.zig"); | |
| 10 | 13 | |
| 11 | 14 | const trig = @import("trig.zig"); |
| 12 | 15 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 13 | 16 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 14 | 17 | |
| 18 | pub const panic = common.panic; | |
| 19 | ||
| 20 | comptime { | |
| 21 | @export(__sinh, .{ .name = "__sinh", .linkage = common.linkage }); | |
| 22 | @export(sinf, .{ .name = "sinf", .linkage = common.linkage }); | |
| 23 | @export(sin, .{ .name = "sin", .linkage = common.linkage }); | |
| 24 | @export(__sinx, .{ .name = "__sinx", .linkage = common.linkage }); | |
| 25 | const sinq_sym_name = if (common.want_ppc_abi) "sinf128" else "sinq"; | |
| 26 | @export(sinq, .{ .name = sinq_sym_name, .linkage = common.linkage }); | |
| 27 | @export(sinl, .{ .name = "sinl", .linkage = common.linkage }); | |
| 28 | } | |
| 29 | ||
| 15 | 30 | pub fn __sinh(x: f16) callconv(.C) f16 { |
| 16 | 31 | // TODO: more efficient implementation |
| 17 | 32 | return @floatCast(f16, sinf(x)); |
lib/compiler_rt/sincos.zig+16-3| ... | ... | @@ -1,10 +1,23 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | const arch = builtin.cpu.arch; | |
| 2 | 4 | const math = std.math; |
| 3 | const sin = @import("sin.zig"); | |
| 4 | const cos = @import("cos.zig"); | |
| 5 | 5 | const trig = @import("trig.zig"); |
| 6 | 6 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 7 | 7 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 8 | const common = @import("common.zig"); | |
| 9 | ||
| 10 | pub const panic = common.panic; | |
| 11 | ||
| 12 | comptime { | |
| 13 | @export(__sincosh, .{ .name = "__sincosh", .linkage = common.linkage }); | |
| 14 | @export(sincosf, .{ .name = "sincosf", .linkage = common.linkage }); | |
| 15 | @export(sincos, .{ .name = "sincos", .linkage = common.linkage }); | |
| 16 | @export(__sincosx, .{ .name = "__sincosx", .linkage = common.linkage }); | |
| 17 | const sincosq_sym_name = if (common.want_ppc_abi) "sincosf128" else "sincosq"; | |
| 18 | @export(sincosq, .{ .name = sincosq_sym_name, .linkage = common.linkage }); | |
| 19 | @export(sincosl, .{ .name = "sincosl", .linkage = common.linkage }); | |
| 20 | } | |
| 8 | 21 | |
| 9 | 22 | pub fn __sincosh(x: f16, r_sin: *f16, r_cos: *f16) callconv(.C) void { |
| 10 | 23 | // TODO: more efficient implementation |
| ... | ... | @@ -192,7 +205,7 @@ pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) call |
| 192 | 205 | } |
| 193 | 206 | } |
| 194 | 207 | |
| 195 | const rem_pio2_generic = @compileError("TODO"); | |
| 208 | pub const rem_pio2_generic = @compileError("TODO"); | |
| 196 | 209 | |
| 197 | 210 | /// Ported from musl sincosl.c. Needs the following dependencies to be complete: |
| 198 | 211 | /// * rem_pio2_generic ported from __rem_pio2l.c |
lib/compiler_rt/sparc.zig deleted-114| ... | ... | @@ -1,114 +0,0 @@ |
| 1 | // | |
| 2 | // SPARC uses a different naming scheme for its support routines so we map it here to the x86 name. | |
| 3 | ||
| 4 | const std = @import("std"); | |
| 5 | const builtin = @import("builtin"); | |
| 6 | ||
| 7 | // The SPARC Architecture Manual, Version 9: | |
| 8 | // A.13 Floating-Point Compare | |
| 9 | const FCMP = enum(i32) { | |
| 10 | Equal = 0, | |
| 11 | Less = 1, | |
| 12 | Greater = 2, | |
| 13 | Unordered = 3, | |
| 14 | }; | |
| 15 | ||
| 16 | // Basic arithmetic | |
| 17 | ||
| 18 | pub fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.C) void { | |
| 19 | c.* = @import("addXf3.zig").__addtf3(a.*, b.*); | |
| 20 | } | |
| 21 | ||
| 22 | pub fn _Qp_div(c: *f128, a: *f128, b: *f128) callconv(.C) void { | |
| 23 | c.* = @import("divtf3.zig").__divtf3(a.*, b.*); | |
| 24 | } | |
| 25 | ||
| 26 | pub fn _Qp_mul(c: *f128, a: *f128, b: *f128) callconv(.C) void { | |
| 27 | c.* = @import("mulXf3.zig").__multf3(a.*, b.*); | |
| 28 | } | |
| 29 | ||
| 30 | pub fn _Qp_sub(c: *f128, a: *f128, b: *f128) callconv(.C) void { | |
| 31 | c.* = @import("addXf3.zig").__subtf3(a.*, b.*); | |
| 32 | } | |
| 33 | ||
| 34 | // Comparison | |
| 35 | ||
| 36 | pub fn _Qp_cmp(a: *f128, b: *f128) callconv(.C) i32 { | |
| 37 | return @enumToInt(@import("compareXf2.zig").cmp(f128, FCMP, a.*, b.*)); | |
| 38 | } | |
| 39 | ||
| 40 | pub fn _Qp_feq(a: *f128, b: *f128) callconv(.C) bool { | |
| 41 | return _Qp_cmp(a, b) == @enumToInt(FCMP.Equal); | |
| 42 | } | |
| 43 | ||
| 44 | pub fn _Qp_fne(a: *f128, b: *f128) callconv(.C) bool { | |
| 45 | return _Qp_cmp(a, b) != @enumToInt(FCMP.Equal); | |
| 46 | } | |
| 47 | ||
| 48 | pub fn _Qp_flt(a: *f128, b: *f128) callconv(.C) bool { | |
| 49 | return _Qp_cmp(a, b) == @enumToInt(FCMP.Less); | |
| 50 | } | |
| 51 | ||
| 52 | pub fn _Qp_fle(a: *f128, b: *f128) callconv(.C) bool { | |
| 53 | const cmp = _Qp_cmp(a, b); | |
| 54 | return cmp == @enumToInt(FCMP.Less) or cmp == @enumToInt(FCMP.Equal); | |
| 55 | } | |
| 56 | ||
| 57 | pub fn _Qp_fgt(a: *f128, b: *f128) callconv(.C) bool { | |
| 58 | return _Qp_cmp(a, b) == @enumToInt(FCMP.Greater); | |
| 59 | } | |
| 60 | ||
| 61 | pub fn _Qp_fge(a: *f128, b: *f128) callconv(.C) bool { | |
| 62 | const cmp = _Qp_cmp(a, b); | |
| 63 | return cmp == @enumToInt(FCMP.Greater) or cmp == @enumToInt(FCMP.Equal); | |
| 64 | } | |
| 65 | ||
| 66 | // Conversion | |
| 67 | ||
| 68 | pub fn _Qp_itoq(c: *f128, a: i32) callconv(.C) void { | |
| 69 | c.* = @import("floatXiYf.zig").__floatsitf(a); | |
| 70 | } | |
| 71 | ||
| 72 | pub fn _Qp_uitoq(c: *f128, a: u32) callconv(.C) void { | |
| 73 | c.* = @import("floatXiYf.zig").__floatunsitf(a); | |
| 74 | } | |
| 75 | ||
| 76 | pub fn _Qp_xtoq(c: *f128, a: i64) callconv(.C) void { | |
| 77 | c.* = @import("floatXiYf.zig").__floatditf(a); | |
| 78 | } | |
| 79 | ||
| 80 | pub fn _Qp_uxtoq(c: *f128, a: u64) callconv(.C) void { | |
| 81 | c.* = @import("floatXiYf.zig").__floatunditf(a); | |
| 82 | } | |
| 83 | ||
| 84 | pub fn _Qp_stoq(c: *f128, a: f32) callconv(.C) void { | |
| 85 | c.* = @import("extendXfYf2.zig").__extendsftf2(a); | |
| 86 | } | |
| 87 | ||
| 88 | pub fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void { | |
| 89 | c.* = @import("extendXfYf2.zig").__extenddftf2(a); | |
| 90 | } | |
| 91 | ||
| 92 | pub fn _Qp_qtoi(a: *f128) callconv(.C) i32 { | |
| 93 | return @import("fixXfYi.zig").__fixtfsi(a.*); | |
| 94 | } | |
| 95 | ||
| 96 | pub fn _Qp_qtoui(a: *f128) callconv(.C) u32 { | |
| 97 | return @import("fixXfYi.zig").__fixunstfsi(a.*); | |
| 98 | } | |
| 99 | ||
| 100 | pub fn _Qp_qtox(a: *f128) callconv(.C) i64 { | |
| 101 | return @import("fixXfYi.zig").__fixtfdi(a.*); | |
| 102 | } | |
| 103 | ||
| 104 | pub fn _Qp_qtoux(a: *f128) callconv(.C) u64 { | |
| 105 | return @import("fixXfYi.zig").__fixunstfdi(a.*); | |
| 106 | } | |
| 107 | ||
| 108 | pub fn _Qp_qtos(a: *f128) callconv(.C) f32 { | |
| 109 | return @import("truncXfYf2.zig").__trunctfsf2(a.*); | |
| 110 | } | |
| 111 | ||
| 112 | pub fn _Qp_qtod(a: *f128) callconv(.C) f64 { | |
| 113 | return @import("truncXfYf2.zig").__trunctfdf2(a.*); | |
| 114 | } |
lib/compiler_rt/sqrt.zig+15| ... | ... | @@ -1,5 +1,20 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | const arch = builtin.cpu.arch; | |
| 2 | 4 | const math = std.math; |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | @export(__sqrth, .{ .name = "__sqrth", .linkage = common.linkage }); | |
| 11 | @export(sqrtf, .{ .name = "sqrtf", .linkage = common.linkage }); | |
| 12 | @export(sqrt, .{ .name = "sqrt", .linkage = common.linkage }); | |
| 13 | @export(__sqrtx, .{ .name = "__sqrtx", .linkage = common.linkage }); | |
| 14 | const sqrtq_sym_name = if (common.want_ppc_abi) "sqrtf128" else "sqrtq"; | |
| 15 | @export(sqrtq, .{ .name = sqrtq_sym_name, .linkage = common.linkage }); | |
| 16 | @export(sqrtl, .{ .name = "sqrtl", .linkage = common.linkage }); | |
| 17 | } | |
| 3 | 18 | |
| 4 | 19 | pub fn __sqrth(x: f16) callconv(.C) f16 { |
| 5 | 20 | // TODO: more efficient implementation |
lib/compiler_rt/stack_probe.zig+46-7| ... | ... | @@ -1,4 +1,43 @@ |
| 1 | const native_arch = @import("builtin").cpu.arch; | |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const os_tag = builtin.os.tag; | |
| 4 | const arch = builtin.cpu.arch; | |
| 5 | const abi = builtin.abi; | |
| 6 | const is_test = builtin.is_test; | |
| 7 | ||
| 8 | const is_gnu = abi.isGnu(); | |
| 9 | const is_mingw = os_tag == .windows and is_gnu; | |
| 10 | ||
| 11 | const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak; | |
| 12 | const strong_linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Strong; | |
| 13 | pub const panic = @import("common.zig").panic; | |
| 14 | ||
| 15 | comptime { | |
| 16 | if (builtin.os.tag == .windows) { | |
| 17 | // Default stack-probe functions emitted by LLVM | |
| 18 | if (is_mingw) { | |
| 19 | @export(_chkstk, .{ .name = "_alloca", .linkage = strong_linkage }); | |
| 20 | @export(___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = strong_linkage }); | |
| 21 | } else if (!builtin.link_libc) { | |
| 22 | // This symbols are otherwise exported by MSVCRT.lib | |
| 23 | @export(_chkstk, .{ .name = "_chkstk", .linkage = strong_linkage }); | |
| 24 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | |
| 25 | } | |
| 26 | ||
| 27 | if (arch.isAARCH64()) { | |
| 28 | @export(__chkstk, .{ .name = "__chkstk", .linkage = strong_linkage }); | |
| 29 | } | |
| 30 | } | |
| 31 | ||
| 32 | switch (arch) { | |
| 33 | .i386, | |
| 34 | .x86_64, | |
| 35 | => { | |
| 36 | @export(zig_probe_stack, .{ .name = "__zig_probe_stack", .linkage = linkage }); | |
| 37 | }, | |
| 38 | else => {}, | |
| 39 | } | |
| 40 | } | |
| 2 | 41 | |
| 3 | 42 | // Zig's own stack-probe routine (available only on x86 and x86_64) |
| 4 | 43 | pub fn zig_probe_stack() callconv(.Naked) void { |
| ... | ... | @@ -8,7 +47,7 @@ pub fn zig_probe_stack() callconv(.Naked) void { |
| 8 | 47 | // invalid so let's update it on the go, otherwise we'll get a segfault |
| 9 | 48 | // instead of triggering the stack growth. |
| 10 | 49 | |
| 11 | switch (native_arch) { | |
| 50 | switch (arch) { | |
| 12 | 51 | .x86_64 => { |
| 13 | 52 | // %rax = probe length, %rsp = stack pointer |
| 14 | 53 | asm volatile ( |
| ... | ... | @@ -60,7 +99,7 @@ pub fn zig_probe_stack() callconv(.Naked) void { |
| 60 | 99 | fn win_probe_stack_only() void { |
| 61 | 100 | @setRuntimeSafety(false); |
| 62 | 101 | |
| 63 | switch (native_arch) { | |
| 102 | switch (arch) { | |
| 64 | 103 | .x86_64 => { |
| 65 | 104 | asm volatile ( |
| 66 | 105 | \\ push %%rcx |
| ... | ... | @@ -105,7 +144,7 @@ fn win_probe_stack_only() void { |
| 105 | 144 | }, |
| 106 | 145 | else => {}, |
| 107 | 146 | } |
| 108 | if (comptime native_arch.isAARCH64()) { | |
| 147 | if (comptime arch.isAARCH64()) { | |
| 109 | 148 | // NOTE: page size hardcoded to 4096 for now |
| 110 | 149 | asm volatile ( |
| 111 | 150 | \\ lsl x16, x15, #4 |
| ... | ... | @@ -127,7 +166,7 @@ fn win_probe_stack_only() void { |
| 127 | 166 | fn win_probe_stack_adjust_sp() void { |
| 128 | 167 | @setRuntimeSafety(false); |
| 129 | 168 | |
| 130 | switch (native_arch) { | |
| 169 | switch (arch) { | |
| 131 | 170 | .x86_64 => { |
| 132 | 171 | asm volatile ( |
| 133 | 172 | \\ push %%rcx |
| ... | ... | @@ -201,9 +240,9 @@ pub fn _chkstk() callconv(.Naked) void { |
| 201 | 240 | } |
| 202 | 241 | pub fn __chkstk() callconv(.Naked) void { |
| 203 | 242 | @setRuntimeSafety(false); |
| 204 | if (comptime native_arch.isAARCH64()) { | |
| 243 | if (comptime arch.isAARCH64()) { | |
| 205 | 244 | @call(.{ .modifier = .always_inline }, win_probe_stack_only, .{}); |
| 206 | } else switch (native_arch) { | |
| 245 | } else switch (arch) { | |
| 207 | 246 | .i386 => @call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{}), |
| 208 | 247 | .x86_64 => @call(.{ .modifier = .always_inline }, win_probe_stack_only, .{}), |
| 209 | 248 | else => unreachable, |
lib/compiler_rt/subdf3.zig created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | ||
| 3 | pub const panic = common.panic; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (common.want_aeabi) { | |
| 7 | @export(__aeabi_dsub, .{ .name = "__aeabi_dsub", .linkage = common.linkage }); | |
| 8 | } else { | |
| 9 | @export(__subdf3, .{ .name = "__subdf3", .linkage = common.linkage }); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | fn __subdf3(a: f64, b: f64) callconv(.C) f64 { | |
| 14 | const neg_b = @bitCast(f64, @bitCast(u64, b) ^ (@as(u64, 1) << 63)); | |
| 15 | return a + neg_b; | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_dsub(a: f64, b: f64) callconv(.AAPCS) f64 { | |
| 19 | const neg_b = @bitCast(f64, @bitCast(u64, b) ^ (@as(u64, 1) << 63)); | |
| 20 | return a + neg_b; | |
| 21 | } |
lib/compiler_rt/subo.zig+24-15| ... | ... | @@ -1,12 +1,31 @@ |
| 1 | //! subo - subtract overflow | |
| 2 | //! * return a-%b. | |
| 3 | //! * return if a-b overflows => 1 else => 0 | |
| 4 | //! - suboXi4_generic as default | |
| 5 | ||
| 6 | const std = @import("std"); | |
| 1 | 7 | const builtin = @import("builtin"); |
| 8 | const common = @import("common.zig"); | |
| 9 | ||
| 10 | pub const panic = common.panic; | |
| 2 | 11 | |
| 3 | // subo - subtract overflow | |
| 4 | // * return a-%b. | |
| 5 | // * return if a-b overflows => 1 else => 0 | |
| 6 | // - suboXi4_generic as default | |
| 12 | comptime { | |
| 13 | @export(__subosi4, .{ .name = "__subosi4", .linkage = common.linkage }); | |
| 14 | @export(__subodi4, .{ .name = "__subodi4", .linkage = common.linkage }); | |
| 15 | @export(__suboti4, .{ .name = "__suboti4", .linkage = common.linkage }); | |
| 16 | } | |
| 17 | ||
| 18 | pub fn __subosi4(a: i32, b: i32, overflow: *c_int) callconv(.C) i32 { | |
| 19 | return suboXi4_generic(i32, a, b, overflow); | |
| 20 | } | |
| 21 | pub fn __subodi4(a: i64, b: i64, overflow: *c_int) callconv(.C) i64 { | |
| 22 | return suboXi4_generic(i64, a, b, overflow); | |
| 23 | } | |
| 24 | pub fn __suboti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 { | |
| 25 | return suboXi4_generic(i128, a, b, overflow); | |
| 26 | } | |
| 7 | 27 | |
| 8 | 28 | inline fn suboXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST { |
| 9 | @setRuntimeSafety(builtin.is_test); | |
| 10 | 29 | overflow.* = 0; |
| 11 | 30 | var sum: ST = a -% b; |
| 12 | 31 | // Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract |
| ... | ... | @@ -21,16 +40,6 @@ inline fn suboXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST |
| 21 | 40 | return sum; |
| 22 | 41 | } |
| 23 | 42 | |
| 24 | pub fn __subosi4(a: i32, b: i32, overflow: *c_int) callconv(.C) i32 { | |
| 25 | return suboXi4_generic(i32, a, b, overflow); | |
| 26 | } | |
| 27 | pub fn __subodi4(a: i64, b: i64, overflow: *c_int) callconv(.C) i64 { | |
| 28 | return suboXi4_generic(i64, a, b, overflow); | |
| 29 | } | |
| 30 | pub fn __suboti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 { | |
| 31 | return suboXi4_generic(i128, a, b, overflow); | |
| 32 | } | |
| 33 | ||
| 34 | 43 | test { |
| 35 | 44 | _ = @import("subosi4_test.zig"); |
| 36 | 45 | _ = @import("subodi4_test.zig"); |
lib/compiler_rt/subsf3.zig created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | ||
| 3 | pub const panic = common.panic; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (common.want_aeabi) { | |
| 7 | @export(__aeabi_fsub, .{ .name = "__aeabi_fsub", .linkage = common.linkage }); | |
| 8 | } else { | |
| 9 | @export(__subsf3, .{ .name = "__subsf3", .linkage = common.linkage }); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | fn __subsf3(a: f32, b: f32) callconv(.C) f32 { | |
| 14 | const neg_b = @bitCast(f32, @bitCast(u32, b) ^ (@as(u32, 1) << 31)); | |
| 15 | return a + neg_b; | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_fsub(a: f32, b: f32) callconv(.AAPCS) f32 { | |
| 19 | const neg_b = @bitCast(f32, @bitCast(u32, b) ^ (@as(u32, 1) << 31)); | |
| 20 | return a + neg_b; | |
| 21 | } |
lib/compiler_rt/subtf3.zig created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | ||
| 3 | pub const panic = common.panic; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (common.want_ppc_abi) { | |
| 7 | @export(__subkf3, .{ .name = "__subkf3", .linkage = common.linkage }); | |
| 8 | } else if (common.want_sparc_abi) { | |
| 9 | @export(_Qp_sub, .{ .name = "_Qp_sub", .linkage = common.linkage }); | |
| 10 | } else { | |
| 11 | @export(__subtf3, .{ .name = "__subtf3", .linkage = common.linkage }); | |
| 12 | } | |
| 13 | } | |
| 14 | ||
| 15 | pub fn __subtf3(a: f128, b: f128) callconv(.C) f128 { | |
| 16 | return sub(a, b); | |
| 17 | } | |
| 18 | ||
| 19 | fn __subkf3(a: f128, b: f128) callconv(.C) f128 { | |
| 20 | return sub(a, b); | |
| 21 | } | |
| 22 | ||
| 23 | fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.C) void { | |
| 24 | c.* = sub(a.*, b.*); | |
| 25 | } | |
| 26 | ||
| 27 | inline fn sub(a: f128, b: f128) f128 { | |
| 28 | const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (@as(u128, 1) << 127)); | |
| 29 | return a + neg_b; | |
| 30 | } |
lib/compiler_rt/subxf3.zig created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | const std = @import("std"); | |
| 2 | const common = @import("./common.zig"); | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__subxf3, .{ .name = "__subxf3", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __subxf3(a: f80, b: f80) callconv(.C) f80 { | |
| 11 | var b_rep = std.math.break_f80(b); | |
| 12 | b_rep.exp ^= 0x8000; | |
| 13 | const neg_b = std.math.make_f80(b_rep); | |
| 14 | return a + neg_b; | |
| 15 | } |
lib/compiler_rt/tan.zig+22-6| ... | ... | @@ -1,11 +1,12 @@ |
| 1 | // Ported from musl, which is licensed under the MIT license: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/tanf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/tan.c | |
| 6 | // https://golang.org/src/math/tan.go | |
| 1 | //! Ported from musl, which is licensed under the MIT license: | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/tanf.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/tan.c | |
| 6 | //! https://golang.org/src/math/tan.go | |
| 7 | 7 | |
| 8 | 8 | const std = @import("std"); |
| 9 | const builtin = @import("builtin"); | |
| 9 | 10 | const math = std.math; |
| 10 | 11 | const expect = std.testing.expect; |
| 11 | 12 | |
| ... | ... | @@ -13,6 +14,21 @@ const kernel = @import("trig.zig"); |
| 13 | 14 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 14 | 15 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 15 | 16 | |
| 17 | const arch = builtin.cpu.arch; | |
| 18 | const common = @import("common.zig"); | |
| 19 | ||
| 20 | pub const panic = common.panic; | |
| 21 | ||
| 22 | comptime { | |
| 23 | @export(__tanh, .{ .name = "__tanh", .linkage = common.linkage }); | |
| 24 | @export(tanf, .{ .name = "tanf", .linkage = common.linkage }); | |
| 25 | @export(tan, .{ .name = "tan", .linkage = common.linkage }); | |
| 26 | @export(__tanx, .{ .name = "__tanx", .linkage = common.linkage }); | |
| 27 | const tanq_sym_name = if (common.want_ppc_abi) "tanf128" else "tanq"; | |
| 28 | @export(tanq, .{ .name = tanq_sym_name, .linkage = common.linkage }); | |
| 29 | @export(tanl, .{ .name = "tanl", .linkage = common.linkage }); | |
| 30 | } | |
| 31 | ||
| 16 | 32 | pub fn __tanh(x: f16) callconv(.C) f16 { |
| 17 | 33 | // TODO: more efficient implementation |
| 18 | 34 | return @floatCast(f16, tanf(x)); |
lib/compiler_rt/trunc.zig+20-5| ... | ... | @@ -1,12 +1,27 @@ |
| 1 | // Ported from musl, which is licensed under the MIT license: | |
| 2 | // https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | // | |
| 4 | // https://git.musl-libc.org/cgit/musl/tree/src/math/truncf.c | |
| 5 | // https://git.musl-libc.org/cgit/musl/tree/src/math/trunc.c | |
| 1 | //! Ported from musl, which is MIT licensed. | |
| 2 | //! https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT | |
| 3 | //! | |
| 4 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/truncf.c | |
| 5 | //! https://git.musl-libc.org/cgit/musl/tree/src/math/trunc.c | |
| 6 | 6 | |
| 7 | 7 | const std = @import("std"); |
| 8 | const builtin = @import("builtin"); | |
| 9 | const arch = builtin.cpu.arch; | |
| 8 | 10 | const math = std.math; |
| 9 | 11 | const expect = std.testing.expect; |
| 12 | const common = @import("common.zig"); | |
| 13 | ||
| 14 | pub const panic = common.panic; | |
| 15 | ||
| 16 | comptime { | |
| 17 | @export(__trunch, .{ .name = "__trunch", .linkage = common.linkage }); | |
| 18 | @export(truncf, .{ .name = "truncf", .linkage = common.linkage }); | |
| 19 | @export(trunc, .{ .name = "trunc", .linkage = common.linkage }); | |
| 20 | @export(__truncx, .{ .name = "__truncx", .linkage = common.linkage }); | |
| 21 | const truncq_sym_name = if (common.want_ppc_abi) "truncf128" else "truncq"; | |
| 22 | @export(truncq, .{ .name = truncq_sym_name, .linkage = common.linkage }); | |
| 23 | @export(truncl, .{ .name = "truncl", .linkage = common.linkage }); | |
| 24 | } | |
| 10 | 25 | |
| 11 | 26 | pub fn __trunch(x: f16) callconv(.C) f16 { |
| 12 | 27 | // TODO: more efficient implementation |
lib/compiler_rt/truncXfYf2.zig deleted-152| ... | ... | @@ -1,152 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const native_arch = builtin.cpu.arch; | |
| 4 | ||
| 5 | // AArch64 is the only ABI (at the moment) to support f16 arguments without the | |
| 6 | // need for extending them to wider fp types. | |
| 7 | // TODO remove this; do this type selection in the language rather than | |
| 8 | // here in compiler-rt. | |
| 9 | pub const F16T = if (native_arch.isAARCH64()) f16 else u16; | |
| 10 | ||
| 11 | pub fn __truncsfhf2(a: f32) callconv(.C) F16T { | |
| 12 | return @bitCast(F16T, truncXfYf2(f16, f32, a)); | |
| 13 | } | |
| 14 | ||
| 15 | pub fn __truncdfhf2(a: f64) callconv(.C) F16T { | |
| 16 | return @bitCast(F16T, truncXfYf2(f16, f64, a)); | |
| 17 | } | |
| 18 | ||
| 19 | pub fn __trunctfhf2(a: f128) callconv(.C) F16T { | |
| 20 | return @bitCast(F16T, truncXfYf2(f16, f128, a)); | |
| 21 | } | |
| 22 | ||
| 23 | pub fn __trunctfsf2(a: f128) callconv(.C) f32 { | |
| 24 | return truncXfYf2(f32, f128, a); | |
| 25 | } | |
| 26 | ||
| 27 | pub fn __trunctfdf2(a: f128) callconv(.C) f64 { | |
| 28 | return truncXfYf2(f64, f128, a); | |
| 29 | } | |
| 30 | ||
| 31 | pub fn __truncdfsf2(a: f64) callconv(.C) f32 { | |
| 32 | return truncXfYf2(f32, f64, a); | |
| 33 | } | |
| 34 | ||
| 35 | pub fn __aeabi_d2f(a: f64) callconv(.AAPCS) f32 { | |
| 36 | @setRuntimeSafety(false); | |
| 37 | return truncXfYf2(f32, f64, a); | |
| 38 | } | |
| 39 | ||
| 40 | pub fn __aeabi_d2h(a: f64) callconv(.AAPCS) u16 { | |
| 41 | @setRuntimeSafety(false); | |
| 42 | return @bitCast(F16T, truncXfYf2(f16, f64, a)); | |
| 43 | } | |
| 44 | ||
| 45 | pub fn __aeabi_f2h(a: f32) callconv(.AAPCS) u16 { | |
| 46 | @setRuntimeSafety(false); | |
| 47 | return @bitCast(F16T, truncXfYf2(f16, f32, a)); | |
| 48 | } | |
| 49 | ||
| 50 | inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { | |
| 51 | const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits); | |
| 52 | const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits); | |
| 53 | const srcSigBits = std.math.floatMantissaBits(src_t); | |
| 54 | const dstSigBits = std.math.floatMantissaBits(dst_t); | |
| 55 | const SrcShift = std.math.Log2Int(src_rep_t); | |
| 56 | ||
| 57 | // Various constants whose values follow from the type parameters. | |
| 58 | // Any reasonable optimizer will fold and propagate all of these. | |
| 59 | const srcBits = @typeInfo(src_t).Float.bits; | |
| 60 | const srcExpBits = srcBits - srcSigBits - 1; | |
| 61 | const srcInfExp = (1 << srcExpBits) - 1; | |
| 62 | const srcExpBias = srcInfExp >> 1; | |
| 63 | ||
| 64 | const srcMinNormal = 1 << srcSigBits; | |
| 65 | const srcSignificandMask = srcMinNormal - 1; | |
| 66 | const srcInfinity = srcInfExp << srcSigBits; | |
| 67 | const srcSignMask = 1 << (srcSigBits + srcExpBits); | |
| 68 | const srcAbsMask = srcSignMask - 1; | |
| 69 | const roundMask = (1 << (srcSigBits - dstSigBits)) - 1; | |
| 70 | const halfway = 1 << (srcSigBits - dstSigBits - 1); | |
| 71 | const srcQNaN = 1 << (srcSigBits - 1); | |
| 72 | const srcNaNCode = srcQNaN - 1; | |
| 73 | ||
| 74 | const dstBits = @typeInfo(dst_t).Float.bits; | |
| 75 | const dstExpBits = dstBits - dstSigBits - 1; | |
| 76 | const dstInfExp = (1 << dstExpBits) - 1; | |
| 77 | const dstExpBias = dstInfExp >> 1; | |
| 78 | ||
| 79 | const underflowExponent = srcExpBias + 1 - dstExpBias; | |
| 80 | const overflowExponent = srcExpBias + dstInfExp - dstExpBias; | |
| 81 | const underflow = underflowExponent << srcSigBits; | |
| 82 | const overflow = overflowExponent << srcSigBits; | |
| 83 | ||
| 84 | const dstQNaN = 1 << (dstSigBits - 1); | |
| 85 | const dstNaNCode = dstQNaN - 1; | |
| 86 | ||
| 87 | // Break a into a sign and representation of the absolute value | |
| 88 | const aRep: src_rep_t = @bitCast(src_rep_t, a); | |
| 89 | const aAbs: src_rep_t = aRep & srcAbsMask; | |
| 90 | const sign: src_rep_t = aRep & srcSignMask; | |
| 91 | var absResult: dst_rep_t = undefined; | |
| 92 | ||
| 93 | if (aAbs -% underflow < aAbs -% overflow) { | |
| 94 | // The exponent of a is within the range of normal numbers in the | |
| 95 | // destination format. We can convert by simply right-shifting with | |
| 96 | // rounding and adjusting the exponent. | |
| 97 | absResult = @truncate(dst_rep_t, aAbs >> (srcSigBits - dstSigBits)); | |
| 98 | absResult -%= @as(dst_rep_t, srcExpBias - dstExpBias) << dstSigBits; | |
| 99 | ||
| 100 | const roundBits: src_rep_t = aAbs & roundMask; | |
| 101 | if (roundBits > halfway) { | |
| 102 | // Round to nearest | |
| 103 | absResult += 1; | |
| 104 | } else if (roundBits == halfway) { | |
| 105 | // Ties to even | |
| 106 | absResult += absResult & 1; | |
| 107 | } | |
| 108 | } else if (aAbs > srcInfinity) { | |
| 109 | // a is NaN. | |
| 110 | // Conjure the result by beginning with infinity, setting the qNaN | |
| 111 | // bit and inserting the (truncated) trailing NaN field. | |
| 112 | absResult = @intCast(dst_rep_t, dstInfExp) << dstSigBits; | |
| 113 | absResult |= dstQNaN; | |
| 114 | absResult |= @intCast(dst_rep_t, ((aAbs & srcNaNCode) >> (srcSigBits - dstSigBits)) & dstNaNCode); | |
| 115 | } else if (aAbs >= overflow) { | |
| 116 | // a overflows to infinity. | |
| 117 | absResult = @intCast(dst_rep_t, dstInfExp) << dstSigBits; | |
| 118 | } else { | |
| 119 | // a underflows on conversion to the destination type or is an exact | |
| 120 | // zero. The result may be a denormal or zero. Extract the exponent | |
| 121 | // to get the shift amount for the denormalization. | |
| 122 | const aExp = @intCast(u32, aAbs >> srcSigBits); | |
| 123 | const shift = @intCast(u32, srcExpBias - dstExpBias - aExp + 1); | |
| 124 | ||
| 125 | const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal; | |
| 126 | ||
| 127 | // Right shift by the denormalization amount with sticky. | |
| 128 | if (shift > srcSigBits) { | |
| 129 | absResult = 0; | |
| 130 | } else { | |
| 131 | const sticky: src_rep_t = @boolToInt(significand << @intCast(SrcShift, srcBits - shift) != 0); | |
| 132 | const denormalizedSignificand: src_rep_t = significand >> @intCast(SrcShift, shift) | sticky; | |
| 133 | absResult = @intCast(dst_rep_t, denormalizedSignificand >> (srcSigBits - dstSigBits)); | |
| 134 | const roundBits: src_rep_t = denormalizedSignificand & roundMask; | |
| 135 | if (roundBits > halfway) { | |
| 136 | // Round to nearest | |
| 137 | absResult += 1; | |
| 138 | } else if (roundBits == halfway) { | |
| 139 | // Ties to even | |
| 140 | absResult += absResult & 1; | |
| 141 | } | |
| 142 | } | |
| 143 | } | |
| 144 | ||
| 145 | const result: dst_rep_t align(@alignOf(dst_t)) = absResult | | |
| 146 | @truncate(dst_rep_t, sign >> @intCast(SrcShift, srcBits - dstBits)); | |
| 147 | return @bitCast(dst_t, result); | |
| 148 | } | |
| 149 | ||
| 150 | test { | |
| 151 | _ = @import("truncXfYf2_test.zig"); | |
| 152 | } |
lib/compiler_rt/truncXfYf2_test.zig deleted-296| ... | ... | @@ -1,296 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const __truncsfhf2 = @import("truncXfYf2.zig").__truncsfhf2; | |
| 3 | ||
| 4 | fn test__truncsfhf2(a: u32, expected: u16) !void { | |
| 5 | const actual = @bitCast(u16, __truncsfhf2(@bitCast(f32, a))); | |
| 6 | ||
| 7 | if (actual == expected) { | |
| 8 | return; | |
| 9 | } | |
| 10 | ||
| 11 | return error.TestFailure; | |
| 12 | } | |
| 13 | ||
| 14 | test "truncsfhf2" { | |
| 15 | try test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN | |
| 16 | try test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN | |
| 17 | ||
| 18 | try test__truncsfhf2(0, 0); // 0 | |
| 19 | try test__truncsfhf2(0x80000000, 0x8000); // -0 | |
| 20 | ||
| 21 | try test__truncsfhf2(0x7f800000, 0x7c00); // inf | |
| 22 | try test__truncsfhf2(0xff800000, 0xfc00); // -inf | |
| 23 | ||
| 24 | try test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf | |
| 25 | try test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf | |
| 26 | ||
| 27 | try test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf | |
| 28 | try test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf | |
| 29 | ||
| 30 | try test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14 | |
| 31 | try test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14 | |
| 32 | ||
| 33 | try test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504 | |
| 34 | try test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504 | |
| 35 | ||
| 36 | try test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504 | |
| 37 | try test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 | |
| 38 | ||
| 39 | try test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504 | |
| 40 | try test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 | |
| 41 | ||
| 42 | try test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10 | |
| 43 | try test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10 | |
| 44 | ||
| 45 | try test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3 | |
| 46 | try test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3 | |
| 47 | ||
| 48 | try test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535 | |
| 49 | try test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535 | |
| 50 | ||
| 51 | try test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 | |
| 52 | ||
| 53 | try test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1 | |
| 54 | try test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14 | |
| 55 | ||
| 56 | try test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24 | |
| 57 | try test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24 | |
| 58 | ||
| 59 | try test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 | |
| 60 | try test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 | |
| 61 | ||
| 62 | try test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20 | |
| 63 | try test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 | |
| 64 | try test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero | |
| 65 | } | |
| 66 | ||
| 67 | const __truncdfhf2 = @import("truncXfYf2.zig").__truncdfhf2; | |
| 68 | ||
| 69 | fn test__truncdfhf2(a: f64, expected: u16) void { | |
| 70 | const rep = @bitCast(u16, __truncdfhf2(a)); | |
| 71 | ||
| 72 | if (rep == expected) { | |
| 73 | return; | |
| 74 | } | |
| 75 | // test other possible NaN representation(signal NaN) | |
| 76 | else if (expected == 0x7e00) { | |
| 77 | if ((rep & 0x7c00) == 0x7c00 and (rep & 0x3ff) > 0) { | |
| 78 | return; | |
| 79 | } | |
| 80 | } | |
| 81 | ||
| 82 | @panic("__truncdfhf2 test failure"); | |
| 83 | } | |
| 84 | ||
| 85 | fn test__truncdfhf2_raw(a: u64, expected: u16) void { | |
| 86 | const actual = @bitCast(u16, __truncdfhf2(@bitCast(f64, a))); | |
| 87 | ||
| 88 | if (actual == expected) { | |
| 89 | return; | |
| 90 | } | |
| 91 | ||
| 92 | @panic("__truncdfhf2 test failure"); | |
| 93 | } | |
| 94 | ||
| 95 | test "truncdfhf2" { | |
| 96 | test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN | |
| 97 | test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN | |
| 98 | ||
| 99 | test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf | |
| 100 | test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf | |
| 101 | ||
| 102 | test__truncdfhf2(0.0, 0x0); // zero | |
| 103 | test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero | |
| 104 | ||
| 105 | test__truncdfhf2(3.1415926535, 0x4248); | |
| 106 | test__truncdfhf2(-3.1415926535, 0xc248); | |
| 107 | ||
| 108 | test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00); | |
| 109 | test__truncdfhf2(0x1.987124876876324p+12, 0x6e62); | |
| 110 | test__truncdfhf2(0x1.0p+0, 0x3c00); | |
| 111 | test__truncdfhf2(0x1.0p-14, 0x0400); | |
| 112 | ||
| 113 | // denormal | |
| 114 | test__truncdfhf2(0x1.0p-20, 0x0010); | |
| 115 | test__truncdfhf2(0x1.0p-24, 0x0001); | |
| 116 | test__truncdfhf2(-0x1.0p-24, 0x8001); | |
| 117 | test__truncdfhf2(0x1.5p-25, 0x0001); | |
| 118 | ||
| 119 | // and back to zero | |
| 120 | test__truncdfhf2(0x1.0p-25, 0x0000); | |
| 121 | test__truncdfhf2(-0x1.0p-25, 0x8000); | |
| 122 | ||
| 123 | // max (precise) | |
| 124 | test__truncdfhf2(65504.0, 0x7bff); | |
| 125 | ||
| 126 | // max (rounded) | |
| 127 | test__truncdfhf2(65519.0, 0x7bff); | |
| 128 | ||
| 129 | // max (to +inf) | |
| 130 | test__truncdfhf2(65520.0, 0x7c00); | |
| 131 | test__truncdfhf2(-65520.0, 0xfc00); | |
| 132 | test__truncdfhf2(65536.0, 0x7c00); | |
| 133 | } | |
| 134 | ||
| 135 | const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2; | |
| 136 | ||
| 137 | fn test__trunctfsf2(a: f128, expected: u32) void { | |
| 138 | const x = __trunctfsf2(a); | |
| 139 | ||
| 140 | const rep = @bitCast(u32, x); | |
| 141 | if (rep == expected) { | |
| 142 | return; | |
| 143 | } | |
| 144 | // test other possible NaN representation(signal NaN) | |
| 145 | else if (expected == 0x7fc00000) { | |
| 146 | if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) { | |
| 147 | return; | |
| 148 | } | |
| 149 | } | |
| 150 | ||
| 151 | @panic("__trunctfsf2 test failure"); | |
| 152 | } | |
| 153 | ||
| 154 | test "trunctfsf2" { | |
| 155 | // qnan | |
| 156 | test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); | |
| 157 | // nan | |
| 158 | test__trunctfsf2(@bitCast(f128, @as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000); | |
| 159 | // inf | |
| 160 | test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff000000000000 << 64)), 0x7f800000); | |
| 161 | // zero | |
| 162 | test__trunctfsf2(0.0, 0x0); | |
| 163 | ||
| 164 | test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156); | |
| 165 | test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2); | |
| 166 | test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000); | |
| 167 | test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0); | |
| 168 | } | |
| 169 | ||
| 170 | const __trunctfdf2 = @import("truncXfYf2.zig").__trunctfdf2; | |
| 171 | ||
| 172 | fn test__trunctfdf2(a: f128, expected: u64) void { | |
| 173 | const x = __trunctfdf2(a); | |
| 174 | ||
| 175 | const rep = @bitCast(u64, x); | |
| 176 | if (rep == expected) { | |
| 177 | return; | |
| 178 | } | |
| 179 | // test other possible NaN representation(signal NaN) | |
| 180 | else if (expected == 0x7ff8000000000000) { | |
| 181 | if ((rep & 0x7ff0000000000000) == 0x7ff0000000000000 and (rep & 0xfffffffffffff) > 0) { | |
| 182 | return; | |
| 183 | } | |
| 184 | } | |
| 185 | ||
| 186 | @panic("__trunctfsf2 test failure"); | |
| 187 | } | |
| 188 | ||
| 189 | test "trunctfdf2" { | |
| 190 | // qnan | |
| 191 | test__trunctfdf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); | |
| 192 | // nan | |
| 193 | test__trunctfdf2(@bitCast(f128, @as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000); | |
| 194 | // inf | |
| 195 | test__trunctfdf2(@bitCast(f128, @as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); | |
| 196 | // zero | |
| 197 | test__trunctfdf2(0.0, 0x0); | |
| 198 | ||
| 199 | test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb); | |
| 200 | test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7); | |
| 201 | test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); | |
| 202 | test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); | |
| 203 | } | |
| 204 | ||
| 205 | const __truncdfsf2 = @import("truncXfYf2.zig").__truncdfsf2; | |
| 206 | ||
| 207 | fn test__truncdfsf2(a: f64, expected: u32) void { | |
| 208 | const x = __truncdfsf2(a); | |
| 209 | ||
| 210 | const rep = @bitCast(u32, x); | |
| 211 | if (rep == expected) { | |
| 212 | return; | |
| 213 | } | |
| 214 | // test other possible NaN representation(signal NaN) | |
| 215 | else if (expected == 0x7fc00000) { | |
| 216 | if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) { | |
| 217 | return; | |
| 218 | } | |
| 219 | } | |
| 220 | ||
| 221 | std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); | |
| 222 | ||
| 223 | @panic("__trunctfsf2 test failure"); | |
| 224 | } | |
| 225 | ||
| 226 | test "truncdfsf2" { | |
| 227 | // nan & qnan | |
| 228 | test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff8000000000000)), 0x7fc00000); | |
| 229 | test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff0000000000001)), 0x7fc00000); | |
| 230 | // inf | |
| 231 | test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff0000000000000)), 0x7f800000); | |
| 232 | test__truncdfsf2(@bitCast(f64, @as(u64, 0xfff0000000000000)), 0xff800000); | |
| 233 | ||
| 234 | test__truncdfsf2(0.0, 0x0); | |
| 235 | test__truncdfsf2(1.0, 0x3f800000); | |
| 236 | test__truncdfsf2(-1.0, 0xbf800000); | |
| 237 | ||
| 238 | // huge number becomes inf | |
| 239 | test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000); | |
| 240 | } | |
| 241 | ||
| 242 | const __trunctfhf2 = @import("truncXfYf2.zig").__trunctfhf2; | |
| 243 | ||
| 244 | fn test__trunctfhf2(a: f128, expected: u16) void { | |
| 245 | const x = __trunctfhf2(a); | |
| 246 | ||
| 247 | const rep = @bitCast(u16, x); | |
| 248 | if (rep == expected) { | |
| 249 | return; | |
| 250 | } | |
| 251 | ||
| 252 | std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); | |
| 253 | ||
| 254 | @panic("__trunctfhf2 test failure"); | |
| 255 | } | |
| 256 | ||
| 257 | test "trunctfhf2" { | |
| 258 | // qNaN | |
| 259 | test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff8000000000000000000000000000)), 0x7e00); | |
| 260 | // NaN | |
| 261 | test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000001)), 0x7e00); | |
| 262 | // inf | |
| 263 | test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0x7c00); | |
| 264 | test__trunctfhf2(-@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0xfc00); | |
| 265 | // zero | |
| 266 | test__trunctfhf2(0.0, 0x0); | |
| 267 | test__trunctfhf2(-0.0, 0x8000); | |
| 268 | ||
| 269 | test__trunctfhf2(3.1415926535, 0x4248); | |
| 270 | test__trunctfhf2(-3.1415926535, 0xc248); | |
| 271 | test__trunctfhf2(0x1.987124876876324p+100, 0x7c00); | |
| 272 | test__trunctfhf2(0x1.987124876876324p+12, 0x6e62); | |
| 273 | test__trunctfhf2(0x1.0p+0, 0x3c00); | |
| 274 | test__trunctfhf2(0x1.0p-14, 0x0400); | |
| 275 | // denormal | |
| 276 | test__trunctfhf2(0x1.0p-20, 0x0010); | |
| 277 | test__trunctfhf2(0x1.0p-24, 0x0001); | |
| 278 | test__trunctfhf2(-0x1.0p-24, 0x8001); | |
| 279 | test__trunctfhf2(0x1.5p-25, 0x0001); | |
| 280 | // and back to zero | |
| 281 | test__trunctfhf2(0x1.0p-25, 0x0000); | |
| 282 | test__trunctfhf2(-0x1.0p-25, 0x8000); | |
| 283 | // max (precise) | |
| 284 | test__trunctfhf2(65504.0, 0x7bff); | |
| 285 | // max (rounded) | |
| 286 | test__trunctfhf2(65519.0, 0x7bff); | |
| 287 | // max (to +inf) | |
| 288 | test__trunctfhf2(65520.0, 0x7c00); | |
| 289 | test__trunctfhf2(65536.0, 0x7c00); | |
| 290 | test__trunctfhf2(-65520.0, 0xfc00); | |
| 291 | ||
| 292 | test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f); | |
| 293 | test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f); | |
| 294 | test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00); | |
| 295 | test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0); | |
| 296 | } |
lib/compiler_rt/trunc_f80.zig deleted-173| ... | ... | @@ -1,173 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const native_arch = builtin.cpu.arch; | |
| 4 | const testing = std.testing; | |
| 5 | ||
| 6 | // AArch64 is the only ABI (at the moment) to support f16 arguments without the | |
| 7 | // need for extending them to wider fp types. | |
| 8 | pub const F16T = if (native_arch.isAARCH64()) f16 else u16; | |
| 9 | ||
| 10 | pub fn __truncxfhf2(a: f80) callconv(.C) F16T { | |
| 11 | return @bitCast(F16T, trunc(f16, a)); | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __truncxfsf2(a: f80) callconv(.C) f32 { | |
| 15 | return trunc(f32, a); | |
| 16 | } | |
| 17 | ||
| 18 | pub fn __truncxfdf2(a: f80) callconv(.C) f64 { | |
| 19 | return trunc(f64, a); | |
| 20 | } | |
| 21 | ||
| 22 | inline fn trunc(comptime dst_t: type, a: f80) dst_t { | |
| 23 | @setRuntimeSafety(builtin.is_test); | |
| 24 | ||
| 25 | const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits); | |
| 26 | const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit | |
| 27 | const dst_sig_bits = std.math.floatMantissaBits(dst_t); | |
| 28 | ||
| 29 | const src_exp_bias = 16383; | |
| 30 | ||
| 31 | const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1; | |
| 32 | const halfway = 1 << (src_sig_bits - dst_sig_bits - 1); | |
| 33 | ||
| 34 | const dst_bits = @typeInfo(dst_t).Float.bits; | |
| 35 | const dst_exp_bits = dst_bits - dst_sig_bits - 1; | |
| 36 | const dst_inf_exp = (1 << dst_exp_bits) - 1; | |
| 37 | const dst_exp_bias = dst_inf_exp >> 1; | |
| 38 | ||
| 39 | const underflow = src_exp_bias + 1 - dst_exp_bias; | |
| 40 | const overflow = src_exp_bias + dst_inf_exp - dst_exp_bias; | |
| 41 | ||
| 42 | const dst_qnan = 1 << (dst_sig_bits - 1); | |
| 43 | const dst_nan_mask = dst_qnan - 1; | |
| 44 | ||
| 45 | // Break a into a sign and representation of the absolute value | |
| 46 | var a_rep = std.math.break_f80(a); | |
| 47 | const sign = a_rep.exp & 0x8000; | |
| 48 | a_rep.exp &= 0x7FFF; | |
| 49 | a_rep.fraction &= 0x7FFFFFFFFFFFFFFF; | |
| 50 | var abs_result: dst_rep_t = undefined; | |
| 51 | ||
| 52 | if (a_rep.exp -% underflow < a_rep.exp -% overflow) { | |
| 53 | // The exponent of a is within the range of normal numbers in the | |
| 54 | // destination format. We can convert by simply right-shifting with | |
| 55 | // rounding and adjusting the exponent. | |
| 56 | abs_result = @as(dst_rep_t, a_rep.exp) << dst_sig_bits; | |
| 57 | abs_result |= @truncate(dst_rep_t, a_rep.fraction >> (src_sig_bits - dst_sig_bits)); | |
| 58 | abs_result -%= @as(dst_rep_t, src_exp_bias - dst_exp_bias) << dst_sig_bits; | |
| 59 | ||
| 60 | const round_bits = a_rep.fraction & round_mask; | |
| 61 | if (round_bits > halfway) { | |
| 62 | // Round to nearest | |
| 63 | abs_result += 1; | |
| 64 | } else if (round_bits == halfway) { | |
| 65 | // Ties to even | |
| 66 | abs_result += abs_result & 1; | |
| 67 | } | |
| 68 | } else if (a_rep.exp == 0x7FFF and a_rep.fraction != 0) { | |
| 69 | // a is NaN. | |
| 70 | // Conjure the result by beginning with infinity, setting the qNaN | |
| 71 | // bit and inserting the (truncated) trailing NaN field. | |
| 72 | abs_result = @intCast(dst_rep_t, dst_inf_exp) << dst_sig_bits; | |
| 73 | abs_result |= dst_qnan; | |
| 74 | abs_result |= @intCast(dst_rep_t, (a_rep.fraction >> (src_sig_bits - dst_sig_bits)) & dst_nan_mask); | |
| 75 | } else if (a_rep.exp >= overflow) { | |
| 76 | // a overflows to infinity. | |
| 77 | abs_result = @intCast(dst_rep_t, dst_inf_exp) << dst_sig_bits; | |
| 78 | } else { | |
| 79 | // a underflows on conversion to the destination type or is an exact | |
| 80 | // zero. The result may be a denormal or zero. Extract the exponent | |
| 81 | // to get the shift amount for the denormalization. | |
| 82 | const shift = src_exp_bias - dst_exp_bias - a_rep.exp; | |
| 83 | ||
| 84 | // Right shift by the denormalization amount with sticky. | |
| 85 | if (shift > src_sig_bits) { | |
| 86 | abs_result = 0; | |
| 87 | } else { | |
| 88 | const sticky = @boolToInt(a_rep.fraction << @intCast(u6, shift) != 0); | |
| 89 | const denormalized_significand = a_rep.fraction >> @intCast(u6, shift) | sticky; | |
| 90 | abs_result = @intCast(dst_rep_t, denormalized_significand >> (src_sig_bits - dst_sig_bits)); | |
| 91 | const round_bits = denormalized_significand & round_mask; | |
| 92 | if (round_bits > halfway) { | |
| 93 | // Round to nearest | |
| 94 | abs_result += 1; | |
| 95 | } else if (round_bits == halfway) { | |
| 96 | // Ties to even | |
| 97 | abs_result += abs_result & 1; | |
| 98 | } | |
| 99 | } | |
| 100 | } | |
| 101 | ||
| 102 | const result align(@alignOf(dst_t)) = abs_result | @as(dst_rep_t, sign) << dst_bits - 16; | |
| 103 | return @bitCast(dst_t, result); | |
| 104 | } | |
| 105 | ||
| 106 | pub fn __trunctfxf2(a: f128) callconv(.C) f80 { | |
| 107 | const src_sig_bits = std.math.floatMantissaBits(f128); | |
| 108 | const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit | |
| 109 | ||
| 110 | // Various constants whose values follow from the type parameters. | |
| 111 | // Any reasonable optimizer will fold and propagate all of these. | |
| 112 | const src_bits = @typeInfo(f128).Float.bits; | |
| 113 | const src_exp_bits = src_bits - src_sig_bits - 1; | |
| 114 | const src_inf_exp = 0x7FFF; | |
| 115 | ||
| 116 | const src_inf = src_inf_exp << src_sig_bits; | |
| 117 | const src_sign_mask = 1 << (src_sig_bits + src_exp_bits); | |
| 118 | const src_abs_mask = src_sign_mask - 1; | |
| 119 | const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1; | |
| 120 | const halfway = 1 << (src_sig_bits - dst_sig_bits - 1); | |
| 121 | ||
| 122 | // Break a into a sign and representation of the absolute value | |
| 123 | const a_rep = @bitCast(u128, a); | |
| 124 | const a_abs = a_rep & src_abs_mask; | |
| 125 | const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0; | |
| 126 | const integer_bit = 1 << 63; | |
| 127 | ||
| 128 | var res: std.math.F80 = undefined; | |
| 129 | ||
| 130 | if (a_abs > src_inf) { | |
| 131 | // a is NaN. | |
| 132 | // Conjure the result by beginning with infinity, setting the qNaN | |
| 133 | // bit and inserting the (truncated) trailing NaN field. | |
| 134 | res.exp = 0x7fff; | |
| 135 | res.fraction = 0x8000000000000000; | |
| 136 | res.fraction |= @truncate(u64, a_abs >> (src_sig_bits - dst_sig_bits)); | |
| 137 | } else { | |
| 138 | // The exponent of a is within the range of normal numbers in the | |
| 139 | // destination format. We can convert by simply right-shifting with | |
| 140 | // rounding, adding the explicit integer bit, and adjusting the exponent | |
| 141 | res.fraction = @truncate(u64, a_abs >> (src_sig_bits - dst_sig_bits)) | integer_bit; | |
| 142 | res.exp = @truncate(u16, a_abs >> src_sig_bits); | |
| 143 | ||
| 144 | const round_bits = a_abs & round_mask; | |
| 145 | if (round_bits > halfway) { | |
| 146 | // Round to nearest | |
| 147 | const carry = @boolToInt(@addWithOverflow(u64, res.fraction, 1, &res.fraction)); | |
| 148 | res.exp += carry; | |
| 149 | res.fraction |= @as(u64, carry) << 63; // Restore integer bit after carry | |
| 150 | } else if (round_bits == halfway) { | |
| 151 | // Ties to even | |
| 152 | const carry = @boolToInt(@addWithOverflow(u64, res.fraction, res.fraction & 1, &res.fraction)); | |
| 153 | res.exp += carry; | |
| 154 | res.fraction |= @as(u64, carry) << 63; // Restore integer bit after carry | |
| 155 | } | |
| 156 | if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals | |
| 157 | } | |
| 158 | ||
| 159 | res.exp |= sign; | |
| 160 | return std.math.make_f80(res); | |
| 161 | } | |
| 162 | ||
| 163 | fn test__trunctfxf2(a: f128, expected: f80) !void { | |
| 164 | const x = __trunctfxf2(a); | |
| 165 | try testing.expect(x == expected); | |
| 166 | } | |
| 167 | ||
| 168 | test { | |
| 169 | try test__trunctfxf2(1.5, 1.5); | |
| 170 | try test__trunctfxf2(2.5, 2.5); | |
| 171 | try test__trunctfxf2(-2.5, -2.5); | |
| 172 | try test__trunctfxf2(0.0, 0.0); | |
| 173 | } |
lib/compiler_rt/truncdfhf2.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const truncf = @import("./truncf.zig").truncf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __truncdfhf2(a: f64) callconv(.C) common.F16T { | |
| 15 | return @bitCast(common.F16T, truncf(f16, f64, a)); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_d2h(a: f64) callconv(.AAPCS) u16 { | |
| 19 | return @bitCast(common.F16T, truncf(f16, f64, a)); | |
| 20 | } |
lib/compiler_rt/truncdfsf2.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const truncf = @import("./truncf.zig").truncf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_d2f, .{ .name = "__aeabi_d2f", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __truncdfsf2(a: f64) callconv(.C) f32 { | |
| 15 | return truncf(f32, f64, a); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_d2f(a: f64) callconv(.AAPCS) f32 { | |
| 19 | return truncf(f32, f64, a); | |
| 20 | } |
lib/compiler_rt/truncf.zig created+187| ... | ... | @@ -0,0 +1,187 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { | |
| 4 | const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits); | |
| 5 | const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits); | |
| 6 | const srcSigBits = std.math.floatMantissaBits(src_t); | |
| 7 | const dstSigBits = std.math.floatMantissaBits(dst_t); | |
| 8 | const SrcShift = std.math.Log2Int(src_rep_t); | |
| 9 | ||
| 10 | // Various constants whose values follow from the type parameters. | |
| 11 | // Any reasonable optimizer will fold and propagate all of these. | |
| 12 | const srcBits = @typeInfo(src_t).Float.bits; | |
| 13 | const srcExpBits = srcBits - srcSigBits - 1; | |
| 14 | const srcInfExp = (1 << srcExpBits) - 1; | |
| 15 | const srcExpBias = srcInfExp >> 1; | |
| 16 | ||
| 17 | const srcMinNormal = 1 << srcSigBits; | |
| 18 | const srcSignificandMask = srcMinNormal - 1; | |
| 19 | const srcInfinity = srcInfExp << srcSigBits; | |
| 20 | const srcSignMask = 1 << (srcSigBits + srcExpBits); | |
| 21 | const srcAbsMask = srcSignMask - 1; | |
| 22 | const roundMask = (1 << (srcSigBits - dstSigBits)) - 1; | |
| 23 | const halfway = 1 << (srcSigBits - dstSigBits - 1); | |
| 24 | const srcQNaN = 1 << (srcSigBits - 1); | |
| 25 | const srcNaNCode = srcQNaN - 1; | |
| 26 | ||
| 27 | const dstBits = @typeInfo(dst_t).Float.bits; | |
| 28 | const dstExpBits = dstBits - dstSigBits - 1; | |
| 29 | const dstInfExp = (1 << dstExpBits) - 1; | |
| 30 | const dstExpBias = dstInfExp >> 1; | |
| 31 | ||
| 32 | const underflowExponent = srcExpBias + 1 - dstExpBias; | |
| 33 | const overflowExponent = srcExpBias + dstInfExp - dstExpBias; | |
| 34 | const underflow = underflowExponent << srcSigBits; | |
| 35 | const overflow = overflowExponent << srcSigBits; | |
| 36 | ||
| 37 | const dstQNaN = 1 << (dstSigBits - 1); | |
| 38 | const dstNaNCode = dstQNaN - 1; | |
| 39 | ||
| 40 | // Break a into a sign and representation of the absolute value | |
| 41 | const aRep: src_rep_t = @bitCast(src_rep_t, a); | |
| 42 | const aAbs: src_rep_t = aRep & srcAbsMask; | |
| 43 | const sign: src_rep_t = aRep & srcSignMask; | |
| 44 | var absResult: dst_rep_t = undefined; | |
| 45 | ||
| 46 | if (aAbs -% underflow < aAbs -% overflow) { | |
| 47 | // The exponent of a is within the range of normal numbers in the | |
| 48 | // destination format. We can convert by simply right-shifting with | |
| 49 | // rounding and adjusting the exponent. | |
| 50 | absResult = @truncate(dst_rep_t, aAbs >> (srcSigBits - dstSigBits)); | |
| 51 | absResult -%= @as(dst_rep_t, srcExpBias - dstExpBias) << dstSigBits; | |
| 52 | ||
| 53 | const roundBits: src_rep_t = aAbs & roundMask; | |
| 54 | if (roundBits > halfway) { | |
| 55 | // Round to nearest | |
| 56 | absResult += 1; | |
| 57 | } else if (roundBits == halfway) { | |
| 58 | // Ties to even | |
| 59 | absResult += absResult & 1; | |
| 60 | } | |
| 61 | } else if (aAbs > srcInfinity) { | |
| 62 | // a is NaN. | |
| 63 | // Conjure the result by beginning with infinity, setting the qNaN | |
| 64 | // bit and inserting the (truncated) trailing NaN field. | |
| 65 | absResult = @intCast(dst_rep_t, dstInfExp) << dstSigBits; | |
| 66 | absResult |= dstQNaN; | |
| 67 | absResult |= @intCast(dst_rep_t, ((aAbs & srcNaNCode) >> (srcSigBits - dstSigBits)) & dstNaNCode); | |
| 68 | } else if (aAbs >= overflow) { | |
| 69 | // a overflows to infinity. | |
| 70 | absResult = @intCast(dst_rep_t, dstInfExp) << dstSigBits; | |
| 71 | } else { | |
| 72 | // a underflows on conversion to the destination type or is an exact | |
| 73 | // zero. The result may be a denormal or zero. Extract the exponent | |
| 74 | // to get the shift amount for the denormalization. | |
| 75 | const aExp = @intCast(u32, aAbs >> srcSigBits); | |
| 76 | const shift = @intCast(u32, srcExpBias - dstExpBias - aExp + 1); | |
| 77 | ||
| 78 | const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal; | |
| 79 | ||
| 80 | // Right shift by the denormalization amount with sticky. | |
| 81 | if (shift > srcSigBits) { | |
| 82 | absResult = 0; | |
| 83 | } else { | |
| 84 | const sticky: src_rep_t = @boolToInt(significand << @intCast(SrcShift, srcBits - shift) != 0); | |
| 85 | const denormalizedSignificand: src_rep_t = significand >> @intCast(SrcShift, shift) | sticky; | |
| 86 | absResult = @intCast(dst_rep_t, denormalizedSignificand >> (srcSigBits - dstSigBits)); | |
| 87 | const roundBits: src_rep_t = denormalizedSignificand & roundMask; | |
| 88 | if (roundBits > halfway) { | |
| 89 | // Round to nearest | |
| 90 | absResult += 1; | |
| 91 | } else if (roundBits == halfway) { | |
| 92 | // Ties to even | |
| 93 | absResult += absResult & 1; | |
| 94 | } | |
| 95 | } | |
| 96 | } | |
| 97 | ||
| 98 | const result: dst_rep_t align(@alignOf(dst_t)) = absResult | | |
| 99 | @truncate(dst_rep_t, sign >> @intCast(SrcShift, srcBits - dstBits)); | |
| 100 | return @bitCast(dst_t, result); | |
| 101 | } | |
| 102 | ||
| 103 | pub inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t { | |
| 104 | const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits); | |
| 105 | const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit | |
| 106 | const dst_sig_bits = std.math.floatMantissaBits(dst_t); | |
| 107 | ||
| 108 | const src_exp_bias = 16383; | |
| 109 | ||
| 110 | const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1; | |
| 111 | const halfway = 1 << (src_sig_bits - dst_sig_bits - 1); | |
| 112 | ||
| 113 | const dst_bits = @typeInfo(dst_t).Float.bits; | |
| 114 | const dst_exp_bits = dst_bits - dst_sig_bits - 1; | |
| 115 | const dst_inf_exp = (1 << dst_exp_bits) - 1; | |
| 116 | const dst_exp_bias = dst_inf_exp >> 1; | |
| 117 | ||
| 118 | const underflow = src_exp_bias + 1 - dst_exp_bias; | |
| 119 | const overflow = src_exp_bias + dst_inf_exp - dst_exp_bias; | |
| 120 | ||
| 121 | const dst_qnan = 1 << (dst_sig_bits - 1); | |
| 122 | const dst_nan_mask = dst_qnan - 1; | |
| 123 | ||
| 124 | // Break a into a sign and representation of the absolute value | |
| 125 | var a_rep = std.math.break_f80(a); | |
| 126 | const sign = a_rep.exp & 0x8000; | |
| 127 | a_rep.exp &= 0x7FFF; | |
| 128 | a_rep.fraction &= 0x7FFFFFFFFFFFFFFF; | |
| 129 | var abs_result: dst_rep_t = undefined; | |
| 130 | ||
| 131 | if (a_rep.exp -% underflow < a_rep.exp -% overflow) { | |
| 132 | // The exponent of a is within the range of normal numbers in the | |
| 133 | // destination format. We can convert by simply right-shifting with | |
| 134 | // rounding and adjusting the exponent. | |
| 135 | abs_result = @as(dst_rep_t, a_rep.exp) << dst_sig_bits; | |
| 136 | abs_result |= @truncate(dst_rep_t, a_rep.fraction >> (src_sig_bits - dst_sig_bits)); | |
| 137 | abs_result -%= @as(dst_rep_t, src_exp_bias - dst_exp_bias) << dst_sig_bits; | |
| 138 | ||
| 139 | const round_bits = a_rep.fraction & round_mask; | |
| 140 | if (round_bits > halfway) { | |
| 141 | // Round to nearest | |
| 142 | abs_result += 1; | |
| 143 | } else if (round_bits == halfway) { | |
| 144 | // Ties to even | |
| 145 | abs_result += abs_result & 1; | |
| 146 | } | |
| 147 | } else if (a_rep.exp == 0x7FFF and a_rep.fraction != 0) { | |
| 148 | // a is NaN. | |
| 149 | // Conjure the result by beginning with infinity, setting the qNaN | |
| 150 | // bit and inserting the (truncated) trailing NaN field. | |
| 151 | abs_result = @intCast(dst_rep_t, dst_inf_exp) << dst_sig_bits; | |
| 152 | abs_result |= dst_qnan; | |
| 153 | abs_result |= @intCast(dst_rep_t, (a_rep.fraction >> (src_sig_bits - dst_sig_bits)) & dst_nan_mask); | |
| 154 | } else if (a_rep.exp >= overflow) { | |
| 155 | // a overflows to infinity. | |
| 156 | abs_result = @intCast(dst_rep_t, dst_inf_exp) << dst_sig_bits; | |
| 157 | } else { | |
| 158 | // a underflows on conversion to the destination type or is an exact | |
| 159 | // zero. The result may be a denormal or zero. Extract the exponent | |
| 160 | // to get the shift amount for the denormalization. | |
| 161 | const shift = src_exp_bias - dst_exp_bias - a_rep.exp; | |
| 162 | ||
| 163 | // Right shift by the denormalization amount with sticky. | |
| 164 | if (shift > src_sig_bits) { | |
| 165 | abs_result = 0; | |
| 166 | } else { | |
| 167 | const sticky = @boolToInt(a_rep.fraction << @intCast(u6, shift) != 0); | |
| 168 | const denormalized_significand = a_rep.fraction >> @intCast(u6, shift) | sticky; | |
| 169 | abs_result = @intCast(dst_rep_t, denormalized_significand >> (src_sig_bits - dst_sig_bits)); | |
| 170 | const round_bits = denormalized_significand & round_mask; | |
| 171 | if (round_bits > halfway) { | |
| 172 | // Round to nearest | |
| 173 | abs_result += 1; | |
| 174 | } else if (round_bits == halfway) { | |
| 175 | // Ties to even | |
| 176 | abs_result += abs_result & 1; | |
| 177 | } | |
| 178 | } | |
| 179 | } | |
| 180 | ||
| 181 | const result align(@alignOf(dst_t)) = abs_result | @as(dst_rep_t, sign) << dst_bits - 16; | |
| 182 | return @bitCast(dst_t, result); | |
| 183 | } | |
| 184 | ||
| 185 | test { | |
| 186 | _ = @import("truncf_test.zig"); | |
| 187 | } |
lib/compiler_rt/truncf_test.zig created+306| ... | ... | @@ -0,0 +1,306 @@ |
| 1 | const std = @import("std"); | |
| 2 | const testing = std.testing; | |
| 3 | ||
| 4 | const __truncsfhf2 = @import("truncsfhf2.zig").__truncsfhf2; | |
| 5 | const __truncdfhf2 = @import("truncdfhf2.zig").__truncdfhf2; | |
| 6 | const __truncdfsf2 = @import("truncdfsf2.zig").__truncdfsf2; | |
| 7 | const __trunctfhf2 = @import("trunctfhf2.zig").__trunctfhf2; | |
| 8 | const __trunctfsf2 = @import("trunctfsf2.zig").__trunctfsf2; | |
| 9 | const __trunctfdf2 = @import("trunctfdf2.zig").__trunctfdf2; | |
| 10 | const __trunctfxf2 = @import("trunctfxf2.zig").__trunctfxf2; | |
| 11 | ||
| 12 | fn test__truncsfhf2(a: u32, expected: u16) !void { | |
| 13 | const actual = @bitCast(u16, __truncsfhf2(@bitCast(f32, a))); | |
| 14 | ||
| 15 | if (actual == expected) { | |
| 16 | return; | |
| 17 | } | |
| 18 | ||
| 19 | return error.TestFailure; | |
| 20 | } | |
| 21 | ||
| 22 | test "truncsfhf2" { | |
| 23 | try test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN | |
| 24 | try test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN | |
| 25 | ||
| 26 | try test__truncsfhf2(0, 0); // 0 | |
| 27 | try test__truncsfhf2(0x80000000, 0x8000); // -0 | |
| 28 | ||
| 29 | try test__truncsfhf2(0x7f800000, 0x7c00); // inf | |
| 30 | try test__truncsfhf2(0xff800000, 0xfc00); // -inf | |
| 31 | ||
| 32 | try test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf | |
| 33 | try test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf | |
| 34 | ||
| 35 | try test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf | |
| 36 | try test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf | |
| 37 | ||
| 38 | try test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14 | |
| 39 | try test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14 | |
| 40 | ||
| 41 | try test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504 | |
| 42 | try test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504 | |
| 43 | ||
| 44 | try test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504 | |
| 45 | try test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 | |
| 46 | ||
| 47 | try test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504 | |
| 48 | try test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 | |
| 49 | ||
| 50 | try test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10 | |
| 51 | try test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10 | |
| 52 | ||
| 53 | try test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3 | |
| 54 | try test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3 | |
| 55 | ||
| 56 | try test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535 | |
| 57 | try test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535 | |
| 58 | ||
| 59 | try test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 | |
| 60 | ||
| 61 | try test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1 | |
| 62 | try test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14 | |
| 63 | ||
| 64 | try test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24 | |
| 65 | try test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24 | |
| 66 | ||
| 67 | try test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 | |
| 68 | try test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 | |
| 69 | ||
| 70 | try test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20 | |
| 71 | try test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 | |
| 72 | try test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero | |
| 73 | } | |
| 74 | ||
| 75 | fn test__truncdfhf2(a: f64, expected: u16) void { | |
| 76 | const rep = @bitCast(u16, __truncdfhf2(a)); | |
| 77 | ||
| 78 | if (rep == expected) { | |
| 79 | return; | |
| 80 | } | |
| 81 | // test other possible NaN representation(signal NaN) | |
| 82 | else if (expected == 0x7e00) { | |
| 83 | if ((rep & 0x7c00) == 0x7c00 and (rep & 0x3ff) > 0) { | |
| 84 | return; | |
| 85 | } | |
| 86 | } | |
| 87 | ||
| 88 | @panic("__truncdfhf2 test failure"); | |
| 89 | } | |
| 90 | ||
| 91 | fn test__truncdfhf2_raw(a: u64, expected: u16) void { | |
| 92 | const actual = @bitCast(u16, __truncdfhf2(@bitCast(f64, a))); | |
| 93 | ||
| 94 | if (actual == expected) { | |
| 95 | return; | |
| 96 | } | |
| 97 | ||
| 98 | @panic("__truncdfhf2 test failure"); | |
| 99 | } | |
| 100 | ||
| 101 | test "truncdfhf2" { | |
| 102 | test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN | |
| 103 | test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN | |
| 104 | ||
| 105 | test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf | |
| 106 | test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf | |
| 107 | ||
| 108 | test__truncdfhf2(0.0, 0x0); // zero | |
| 109 | test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero | |
| 110 | ||
| 111 | test__truncdfhf2(3.1415926535, 0x4248); | |
| 112 | test__truncdfhf2(-3.1415926535, 0xc248); | |
| 113 | ||
| 114 | test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00); | |
| 115 | test__truncdfhf2(0x1.987124876876324p+12, 0x6e62); | |
| 116 | test__truncdfhf2(0x1.0p+0, 0x3c00); | |
| 117 | test__truncdfhf2(0x1.0p-14, 0x0400); | |
| 118 | ||
| 119 | // denormal | |
| 120 | test__truncdfhf2(0x1.0p-20, 0x0010); | |
| 121 | test__truncdfhf2(0x1.0p-24, 0x0001); | |
| 122 | test__truncdfhf2(-0x1.0p-24, 0x8001); | |
| 123 | test__truncdfhf2(0x1.5p-25, 0x0001); | |
| 124 | ||
| 125 | // and back to zero | |
| 126 | test__truncdfhf2(0x1.0p-25, 0x0000); | |
| 127 | test__truncdfhf2(-0x1.0p-25, 0x8000); | |
| 128 | ||
| 129 | // max (precise) | |
| 130 | test__truncdfhf2(65504.0, 0x7bff); | |
| 131 | ||
| 132 | // max (rounded) | |
| 133 | test__truncdfhf2(65519.0, 0x7bff); | |
| 134 | ||
| 135 | // max (to +inf) | |
| 136 | test__truncdfhf2(65520.0, 0x7c00); | |
| 137 | test__truncdfhf2(-65520.0, 0xfc00); | |
| 138 | test__truncdfhf2(65536.0, 0x7c00); | |
| 139 | } | |
| 140 | ||
| 141 | fn test__trunctfsf2(a: f128, expected: u32) void { | |
| 142 | const x = __trunctfsf2(a); | |
| 143 | ||
| 144 | const rep = @bitCast(u32, x); | |
| 145 | if (rep == expected) { | |
| 146 | return; | |
| 147 | } | |
| 148 | // test other possible NaN representation(signal NaN) | |
| 149 | else if (expected == 0x7fc00000) { | |
| 150 | if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) { | |
| 151 | return; | |
| 152 | } | |
| 153 | } | |
| 154 | ||
| 155 | @panic("__trunctfsf2 test failure"); | |
| 156 | } | |
| 157 | ||
| 158 | test "trunctfsf2" { | |
| 159 | // qnan | |
| 160 | test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); | |
| 161 | // nan | |
| 162 | test__trunctfsf2(@bitCast(f128, @as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000); | |
| 163 | // inf | |
| 164 | test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff000000000000 << 64)), 0x7f800000); | |
| 165 | // zero | |
| 166 | test__trunctfsf2(0.0, 0x0); | |
| 167 | ||
| 168 | test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156); | |
| 169 | test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2); | |
| 170 | test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000); | |
| 171 | test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0); | |
| 172 | } | |
| 173 | ||
| 174 | fn test__trunctfdf2(a: f128, expected: u64) void { | |
| 175 | const x = __trunctfdf2(a); | |
| 176 | ||
| 177 | const rep = @bitCast(u64, x); | |
| 178 | if (rep == expected) { | |
| 179 | return; | |
| 180 | } | |
| 181 | // test other possible NaN representation(signal NaN) | |
| 182 | else if (expected == 0x7ff8000000000000) { | |
| 183 | if ((rep & 0x7ff0000000000000) == 0x7ff0000000000000 and (rep & 0xfffffffffffff) > 0) { | |
| 184 | return; | |
| 185 | } | |
| 186 | } | |
| 187 | ||
| 188 | @panic("__trunctfsf2 test failure"); | |
| 189 | } | |
| 190 | ||
| 191 | test "trunctfdf2" { | |
| 192 | // qnan | |
| 193 | test__trunctfdf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); | |
| 194 | // nan | |
| 195 | test__trunctfdf2(@bitCast(f128, @as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7ff8100000000000); | |
| 196 | // inf | |
| 197 | test__trunctfdf2(@bitCast(f128, @as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); | |
| 198 | // zero | |
| 199 | test__trunctfdf2(0.0, 0x0); | |
| 200 | ||
| 201 | test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb); | |
| 202 | test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7); | |
| 203 | test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); | |
| 204 | test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); | |
| 205 | } | |
| 206 | ||
| 207 | fn test__truncdfsf2(a: f64, expected: u32) void { | |
| 208 | const x = __truncdfsf2(a); | |
| 209 | ||
| 210 | const rep = @bitCast(u32, x); | |
| 211 | if (rep == expected) { | |
| 212 | return; | |
| 213 | } | |
| 214 | // test other possible NaN representation(signal NaN) | |
| 215 | else if (expected == 0x7fc00000) { | |
| 216 | if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) { | |
| 217 | return; | |
| 218 | } | |
| 219 | } | |
| 220 | ||
| 221 | std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); | |
| 222 | ||
| 223 | @panic("__trunctfsf2 test failure"); | |
| 224 | } | |
| 225 | ||
| 226 | test "truncdfsf2" { | |
| 227 | // nan & qnan | |
| 228 | test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff8000000000000)), 0x7fc00000); | |
| 229 | test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff0000000000001)), 0x7fc00000); | |
| 230 | // inf | |
| 231 | test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff0000000000000)), 0x7f800000); | |
| 232 | test__truncdfsf2(@bitCast(f64, @as(u64, 0xfff0000000000000)), 0xff800000); | |
| 233 | ||
| 234 | test__truncdfsf2(0.0, 0x0); | |
| 235 | test__truncdfsf2(1.0, 0x3f800000); | |
| 236 | test__truncdfsf2(-1.0, 0xbf800000); | |
| 237 | ||
| 238 | // huge number becomes inf | |
| 239 | test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000); | |
| 240 | } | |
| 241 | ||
| 242 | fn test__trunctfhf2(a: f128, expected: u16) void { | |
| 243 | const x = __trunctfhf2(a); | |
| 244 | ||
| 245 | const rep = @bitCast(u16, x); | |
| 246 | if (rep == expected) { | |
| 247 | return; | |
| 248 | } | |
| 249 | ||
| 250 | std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); | |
| 251 | ||
| 252 | @panic("__trunctfhf2 test failure"); | |
| 253 | } | |
| 254 | ||
| 255 | test "trunctfhf2" { | |
| 256 | // qNaN | |
| 257 | test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff8000000000000000000000000000)), 0x7e00); | |
| 258 | // NaN | |
| 259 | test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000001)), 0x7e00); | |
| 260 | // inf | |
| 261 | test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0x7c00); | |
| 262 | test__trunctfhf2(-@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0xfc00); | |
| 263 | // zero | |
| 264 | test__trunctfhf2(0.0, 0x0); | |
| 265 | test__trunctfhf2(-0.0, 0x8000); | |
| 266 | ||
| 267 | test__trunctfhf2(3.1415926535, 0x4248); | |
| 268 | test__trunctfhf2(-3.1415926535, 0xc248); | |
| 269 | test__trunctfhf2(0x1.987124876876324p+100, 0x7c00); | |
| 270 | test__trunctfhf2(0x1.987124876876324p+12, 0x6e62); | |
| 271 | test__trunctfhf2(0x1.0p+0, 0x3c00); | |
| 272 | test__trunctfhf2(0x1.0p-14, 0x0400); | |
| 273 | // denormal | |
| 274 | test__trunctfhf2(0x1.0p-20, 0x0010); | |
| 275 | test__trunctfhf2(0x1.0p-24, 0x0001); | |
| 276 | test__trunctfhf2(-0x1.0p-24, 0x8001); | |
| 277 | test__trunctfhf2(0x1.5p-25, 0x0001); | |
| 278 | // and back to zero | |
| 279 | test__trunctfhf2(0x1.0p-25, 0x0000); | |
| 280 | test__trunctfhf2(-0x1.0p-25, 0x8000); | |
| 281 | // max (precise) | |
| 282 | test__trunctfhf2(65504.0, 0x7bff); | |
| 283 | // max (rounded) | |
| 284 | test__trunctfhf2(65519.0, 0x7bff); | |
| 285 | // max (to +inf) | |
| 286 | test__trunctfhf2(65520.0, 0x7c00); | |
| 287 | test__trunctfhf2(65536.0, 0x7c00); | |
| 288 | test__trunctfhf2(-65520.0, 0xfc00); | |
| 289 | ||
| 290 | test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f); | |
| 291 | test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f); | |
| 292 | test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00); | |
| 293 | test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0); | |
| 294 | } | |
| 295 | ||
| 296 | test "trunctfxf2" { | |
| 297 | try test__trunctfxf2(1.5, 1.5); | |
| 298 | try test__trunctfxf2(2.5, 2.5); | |
| 299 | try test__trunctfxf2(-2.5, -2.5); | |
| 300 | try test__trunctfxf2(0.0, 0.0); | |
| 301 | } | |
| 302 | ||
| 303 | fn test__trunctfxf2(a: f128, expected: f80) !void { | |
| 304 | const x = __trunctfxf2(a); | |
| 305 | try testing.expect(x == expected); | |
| 306 | } |
lib/compiler_rt/truncsfhf2.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const truncf = @import("./truncf.zig").truncf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.gnu_f16_abi) { | |
| 8 | @export(__gnu_f2h_ieee, .{ .name = "__gnu_f2h_ieee", .linkage = common.linkage }); | |
| 9 | } else if (common.want_aeabi) { | |
| 10 | @export(__aeabi_f2h, .{ .name = "__aeabi_f2h", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __truncsfhf2(a: f32) callconv(.C) common.F16T { | |
| 17 | return @bitCast(common.F16T, truncf(f16, f32, a)); | |
| 18 | } | |
| 19 | ||
| 20 | fn __gnu_f2h_ieee(a: f32) callconv(.C) common.F16T { | |
| 21 | return @bitCast(common.F16T, truncf(f16, f32, a)); | |
| 22 | } | |
| 23 | ||
| 24 | fn __aeabi_f2h(a: f32) callconv(.AAPCS) u16 { | |
| 25 | return @bitCast(common.F16T, truncf(f16, f32, a)); | |
| 26 | } |
lib/compiler_rt/trunctfdf2.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const truncf = @import("./truncf.zig").truncf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__trunckfdf2, .{ .name = "__trunckfdf2", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_qtod, .{ .name = "_Qp_qtod", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __trunctfdf2(a: f128) callconv(.C) f64 { | |
| 17 | return truncf(f64, f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __trunckfdf2(a: f128) callconv(.C) f64 { | |
| 21 | return truncf(f64, f128, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_qtod(a: *const f128) callconv(.C) f64 { | |
| 25 | return truncf(f64, f128, a.*); | |
| 26 | } |
lib/compiler_rt/trunctfhf2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const truncf = @import("./truncf.zig").truncf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __trunctfhf2(a: f128) callconv(.C) common.F16T { | |
| 11 | return @bitCast(common.F16T, truncf(f16, f128, a)); | |
| 12 | } |
lib/compiler_rt/trunctfsf2.zig created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const truncf = @import("./truncf.zig").truncf; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__trunckfsf2, .{ .name = "__trunckfsf2", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | @export(_Qp_qtos, .{ .name = "_Qp_qtos", .linkage = common.linkage }); | |
| 11 | } else { | |
| 12 | @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = common.linkage }); | |
| 13 | } | |
| 14 | } | |
| 15 | ||
| 16 | pub fn __trunctfsf2(a: f128) callconv(.C) f32 { | |
| 17 | return truncf(f32, f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __trunckfsf2(a: f128) callconv(.C) f32 { | |
| 21 | return truncf(f32, f128, a); | |
| 22 | } | |
| 23 | ||
| 24 | fn _Qp_qtos(a: *const f128) callconv(.C) f32 { | |
| 25 | return truncf(f32, f128, a.*); | |
| 26 | } |
lib/compiler_rt/trunctfxf2.zig created+66| ... | ... | @@ -0,0 +1,66 @@ |
| 1 | const math = @import("std").math; | |
| 2 | const common = @import("./common.zig"); | |
| 3 | const trunc_f80 = @import("./truncf.zig").trunc_f80; | |
| 4 | ||
| 5 | pub const panic = common.panic; | |
| 6 | ||
| 7 | comptime { | |
| 8 | @export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = common.linkage }); | |
| 9 | } | |
| 10 | ||
| 11 | pub fn __trunctfxf2(a: f128) callconv(.C) f80 { | |
| 12 | const src_sig_bits = math.floatMantissaBits(f128); | |
| 13 | const dst_sig_bits = math.floatMantissaBits(f80) - 1; // -1 for the integer bit | |
| 14 | ||
| 15 | // Various constants whose values follow from the type parameters. | |
| 16 | // Any reasonable optimizer will fold and propagate all of these. | |
| 17 | const src_bits = @typeInfo(f128).Float.bits; | |
| 18 | const src_exp_bits = src_bits - src_sig_bits - 1; | |
| 19 | const src_inf_exp = 0x7FFF; | |
| 20 | ||
| 21 | const src_inf = src_inf_exp << src_sig_bits; | |
| 22 | const src_sign_mask = 1 << (src_sig_bits + src_exp_bits); | |
| 23 | const src_abs_mask = src_sign_mask - 1; | |
| 24 | const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1; | |
| 25 | const halfway = 1 << (src_sig_bits - dst_sig_bits - 1); | |
| 26 | ||
| 27 | // Break a into a sign and representation of the absolute value | |
| 28 | const a_rep = @bitCast(u128, a); | |
| 29 | const a_abs = a_rep & src_abs_mask; | |
| 30 | const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0; | |
| 31 | const integer_bit = 1 << 63; | |
| 32 | ||
| 33 | var res: math.F80 = undefined; | |
| 34 | ||
| 35 | if (a_abs > src_inf) { | |
| 36 | // a is NaN. | |
| 37 | // Conjure the result by beginning with infinity, setting the qNaN | |
| 38 | // bit and inserting the (truncated) trailing NaN field. | |
| 39 | res.exp = 0x7fff; | |
| 40 | res.fraction = 0x8000000000000000; | |
| 41 | res.fraction |= @truncate(u64, a_abs >> (src_sig_bits - dst_sig_bits)); | |
| 42 | } else { | |
| 43 | // The exponent of a is within the range of normal numbers in the | |
| 44 | // destination format. We can convert by simply right-shifting with | |
| 45 | // rounding, adding the explicit integer bit, and adjusting the exponent | |
| 46 | res.fraction = @truncate(u64, a_abs >> (src_sig_bits - dst_sig_bits)) | integer_bit; | |
| 47 | res.exp = @truncate(u16, a_abs >> src_sig_bits); | |
| 48 | ||
| 49 | const round_bits = a_abs & round_mask; | |
| 50 | if (round_bits > halfway) { | |
| 51 | // Round to nearest | |
| 52 | const carry = @boolToInt(@addWithOverflow(u64, res.fraction, 1, &res.fraction)); | |
| 53 | res.exp += carry; | |
| 54 | res.fraction |= @as(u64, carry) << 63; // Restore integer bit after carry | |
| 55 | } else if (round_bits == halfway) { | |
| 56 | // Ties to even | |
| 57 | const carry = @boolToInt(@addWithOverflow(u64, res.fraction, res.fraction & 1, &res.fraction)); | |
| 58 | res.exp += carry; | |
| 59 | res.fraction |= @as(u64, carry) << 63; // Restore integer bit after carry | |
| 60 | } | |
| 61 | if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals | |
| 62 | } | |
| 63 | ||
| 64 | res.exp |= sign; | |
| 65 | return math.make_f80(res); | |
| 66 | } |
lib/compiler_rt/truncxfdf2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const trunc_f80 = @import("./truncf.zig").trunc_f80; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__truncxfdf2, .{ .name = "__truncxfdf2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __truncxfdf2(a: f80) callconv(.C) f64 { | |
| 11 | return trunc_f80(f64, a); | |
| 12 | } |
lib/compiler_rt/truncxfhf2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const trunc_f80 = @import("./truncf.zig").trunc_f80; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__truncxfhf2, .{ .name = "__truncxfhf2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __truncxfhf2(a: f80) callconv(.C) common.F16T { | |
| 11 | return @bitCast(common.F16T, trunc_f80(f16, a)); | |
| 12 | } |
lib/compiler_rt/truncxfsf2.zig created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const trunc_f80 = @import("./truncf.zig").trunc_f80; | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | @export(__truncxfsf2, .{ .name = "__truncxfsf2", .linkage = common.linkage }); | |
| 8 | } | |
| 9 | ||
| 10 | fn __truncxfsf2(a: f80) callconv(.C) f32 { | |
| 11 | return trunc_f80(f32, a); | |
| 12 | } |
lib/compiler_rt/udivmodti4.zig+27-6| ... | ... | @@ -1,15 +1,36 @@ |
| 1 | const udivmod = @import("udivmod.zig").udivmod; | |
| 1 | const std = @import("std"); | |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const udivmod = @import("udivmod.zig").udivmod; | |
| 4 | const arch = builtin.cpu.arch; | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | if (builtin.os.tag == .windows) { | |
| 11 | switch (arch) { | |
| 12 | .i386 => { | |
| 13 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = common.linkage }); | |
| 14 | }, | |
| 15 | .x86_64 => { | |
| 16 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | |
| 17 | // that LLVM expects compiler-rt to have. | |
| 18 | @export(__udivmodti4_windows_x86_64, .{ .name = "__udivmodti4", .linkage = common.linkage }); | |
| 19 | }, | |
| 20 | else => {}, | |
| 21 | } | |
| 22 | } else { | |
| 23 | @export(__udivmodti4, .{ .name = "__udivmodti4", .linkage = common.linkage }); | |
| 24 | } | |
| 25 | } | |
| 4 | 26 | |
| 5 | 27 | pub fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) callconv(.C) u128 { |
| 6 | @setRuntimeSafety(builtin.is_test); | |
| 7 | 28 | return udivmod(u128, a, b, maybe_rem); |
| 8 | 29 | } |
| 9 | 30 | |
| 10 | const v128 = @import("std").meta.Vector(2, u64); | |
| 11 | pub fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) callconv(.C) v128 { | |
| 12 | @setRuntimeSafety(builtin.is_test); | |
| 31 | const v128 = std.meta.Vector(2, u64); | |
| 32 | ||
| 33 | fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) callconv(.C) v128 { | |
| 13 | 34 | return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), maybe_rem)); |
| 14 | 35 | } |
| 15 | 36 |
lib/compiler_rt/udivti3.zig+32-7| ... | ... | @@ -1,13 +1,38 @@ |
| 1 | const udivmodti4 = @import("udivmodti4.zig"); | |
| 1 | const std = @import("std"); | |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const udivmod = @import("udivmod.zig").udivmod; | |
| 4 | const arch = builtin.cpu.arch; | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | if (builtin.os.tag == .windows) { | |
| 11 | switch (arch) { | |
| 12 | .i386 => { | |
| 13 | @export(__udivti3, .{ .name = "__udivti3", .linkage = common.linkage }); | |
| 14 | }, | |
| 15 | .x86_64 => { | |
| 16 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | |
| 17 | // that LLVM expects compiler-rt to have. | |
| 18 | @export(__udivti3_windows_x86_64, .{ .name = "__udivti3", .linkage = common.linkage }); | |
| 19 | }, | |
| 20 | else => {}, | |
| 21 | } | |
| 22 | if (arch.isAARCH64()) { | |
| 23 | @export(__udivti3, .{ .name = "__udivti3", .linkage = common.linkage }); | |
| 24 | } | |
| 25 | } else { | |
| 26 | @export(__udivti3, .{ .name = "__udivti3", .linkage = common.linkage }); | |
| 27 | } | |
| 28 | } | |
| 3 | 29 | |
| 4 | 30 | pub fn __udivti3(a: u128, b: u128) callconv(.C) u128 { |
| 5 | @setRuntimeSafety(builtin.is_test); | |
| 6 | return udivmodti4.__udivmodti4(a, b, null); | |
| 31 | return udivmod(u128, a, b, null); | |
| 7 | 32 | } |
| 8 | 33 | |
| 9 | const v128 = @import("std").meta.Vector(2, u64); | |
| 10 | pub fn __udivti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 11 | @setRuntimeSafety(builtin.is_test); | |
| 12 | return udivmodti4.__udivmodti4_windows_x86_64(a, b, null); | |
| 34 | const v128 = std.meta.Vector(2, u64); | |
| 35 | ||
| 36 | fn __udivti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 37 | return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), null)); | |
| 13 | 38 | } |
lib/compiler_rt/umodti3.zig+34-10| ... | ... | @@ -1,18 +1,42 @@ |
| 1 | const udivmodti4 = @import("udivmodti4.zig"); | |
| 1 | const std = @import("std"); | |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const udivmod = @import("udivmod.zig").udivmod; | |
| 4 | const arch = builtin.cpu.arch; | |
| 5 | const common = @import("common.zig"); | |
| 6 | ||
| 7 | pub const panic = common.panic; | |
| 8 | ||
| 9 | comptime { | |
| 10 | if (builtin.os.tag == .windows) { | |
| 11 | switch (arch) { | |
| 12 | .i386 => { | |
| 13 | @export(__umodti3, .{ .name = "__umodti3", .linkage = common.linkage }); | |
| 14 | }, | |
| 15 | .x86_64 => { | |
| 16 | // The "ti" functions must use Vector(2, u64) parameter types to adhere to the ABI | |
| 17 | // that LLVM expects compiler-rt to have. | |
| 18 | @export(__umodti3_windows_x86_64, .{ .name = "__umodti3", .linkage = common.linkage }); | |
| 19 | }, | |
| 20 | else => {}, | |
| 21 | } | |
| 22 | if (arch.isAARCH64()) { | |
| 23 | @export(__umodti3, .{ .name = "__umodti3", .linkage = common.linkage }); | |
| 24 | } | |
| 25 | } else { | |
| 26 | @export(__umodti3, .{ .name = "__umodti3", .linkage = common.linkage }); | |
| 27 | } | |
| 28 | } | |
| 4 | 29 | |
| 5 | 30 | pub fn __umodti3(a: u128, b: u128) callconv(.C) u128 { |
| 6 | @setRuntimeSafety(builtin.is_test); | |
| 7 | 31 | var r: u128 = undefined; |
| 8 | _ = udivmodti4.__udivmodti4(a, b, &r); | |
| 32 | _ = udivmod(u128, a, b, &r); | |
| 9 | 33 | return r; |
| 10 | 34 | } |
| 11 | 35 | |
| 12 | const v128 = @import("std").meta.Vector(2, u64); | |
| 13 | pub fn __umodti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 14 | return @bitCast(v128, @call(.{ .modifier = .always_inline }, __umodti3, .{ | |
| 15 | @bitCast(u128, a), | |
| 16 | @bitCast(u128, b), | |
| 17 | })); | |
| 36 | const v128 = std.meta.Vector(2, u64); | |
| 37 | ||
| 38 | fn __umodti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 { | |
| 39 | var r: u128 = undefined; | |
| 40 | _ = udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), &r); | |
| 41 | return @bitCast(v128, r); | |
| 18 | 42 | } |
lib/compiler_rt/unorddf2.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const comparef = @import("./comparef.zig"); | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__unorddf2, .{ .name = "__unorddf2", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __unorddf2(a: f64, b: f64) callconv(.C) i32 { | |
| 15 | return comparef.unordcmp(f64, a, b); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_dcmpun(a: f64, b: f64) callconv(.AAPCS) i32 { | |
| 19 | return comparef.unordcmp(f64, a, b); | |
| 20 | } |
lib/compiler_rt/unordsf2.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const comparef = @import("./comparef.zig"); | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_aeabi) { | |
| 8 | @export(__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = common.linkage }); | |
| 9 | } else { | |
| 10 | @export(__unordsf2, .{ .name = "__unordsf2", .linkage = common.linkage }); | |
| 11 | } | |
| 12 | } | |
| 13 | ||
| 14 | pub fn __unordsf2(a: f32, b: f32) callconv(.C) i32 { | |
| 15 | return comparef.unordcmp(f32, a, b); | |
| 16 | } | |
| 17 | ||
| 18 | fn __aeabi_fcmpun(a: f32, b: f32) callconv(.AAPCS) i32 { | |
| 19 | return comparef.unordcmp(f32, a, b); | |
| 20 | } |
lib/compiler_rt/unordtf2.zig created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | const common = @import("./common.zig"); | |
| 2 | const comparef = @import("./comparef.zig"); | |
| 3 | ||
| 4 | pub const panic = common.panic; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (common.want_ppc_abi) { | |
| 8 | @export(__unordkf2, .{ .name = "__unordkf2", .linkage = common.linkage }); | |
| 9 | } else if (common.want_sparc_abi) { | |
| 10 | // These exports are handled in cmptf2.zig because unordered comparisons | |
| 11 | // are based on calling _Qp_cmp. | |
| 12 | } else { | |
| 13 | @export(__unordtf2, .{ .name = "__unordtf2", .linkage = common.linkage }); | |
| 14 | } | |
| 15 | } | |
| 16 | ||
| 17 | fn __unordtf2(a: f128, b: f128) callconv(.C) i32 { | |
| 18 | return comparef.unordcmp(f128, a, b); | |
| 19 | } | |
| 20 | ||
| 21 | fn __unordkf2(a: f128, b: f128) callconv(.C) i32 { | |
| 22 | return comparef.unordcmp(f128, a, b); | |
| 23 | } |
src/Compilation.zig+85-73| ... | ... | @@ -92,6 +92,9 @@ unwind_tables: bool, |
| 92 | 92 | test_evented_io: bool, |
| 93 | 93 | debug_compiler_runtime_libs: bool, |
| 94 | 94 | debug_compile_errors: bool, |
| 95 | job_queued_compiler_rt_lib: bool = false, | |
| 96 | job_queued_compiler_rt_obj: bool = false, | |
| 97 | alloc_failure_occurred: bool = false, | |
| 95 | 98 | |
| 96 | 99 | c_source_files: []const CSourceFile, |
| 97 | 100 | clang_argv: []const []const u8, |
| ... | ... | @@ -129,11 +132,11 @@ libssp_static_lib: ?CRTFile = null, |
| 129 | 132 | /// Populated when we build the libc static library. A Job to build this is placed in the queue |
| 130 | 133 | /// and resolved before calling linker.flush(). |
| 131 | 134 | libc_static_lib: ?CRTFile = null, |
| 132 | /// Populated when we build the libcompiler_rt static library. A Job to build this is placed in the queue | |
| 133 | /// and resolved before calling linker.flush(). | |
| 134 | compiler_rt_static_lib: ?CRTFile = null, | |
| 135 | /// Populated when we build the compiler_rt_obj object. A Job to build this is placed in the queue | |
| 136 | /// and resolved before calling linker.flush(). | |
| 135 | /// Populated when we build the libcompiler_rt static library. A Job to build this is indicated | |
| 136 | /// by setting `job_queued_compiler_rt_lib` and resolved before calling linker.flush(). | |
| 137 | compiler_rt_lib: ?CRTFile = null, | |
| 138 | /// Populated when we build the compiler_rt_obj object. A Job to build this is indicated | |
| 139 | /// by setting `job_queued_compiler_rt_obj` and resolved before calling linker.flush(). | |
| 137 | 140 | compiler_rt_obj: ?CRTFile = null, |
| 138 | 141 | |
| 139 | 142 | glibc_so_files: ?glibc.BuiltSharedObjects = null, |
| ... | ... | @@ -175,7 +178,7 @@ pub const CRTFile = struct { |
| 175 | 178 | lock: Cache.Lock, |
| 176 | 179 | full_object_path: []const u8, |
| 177 | 180 | |
| 178 | fn deinit(self: *CRTFile, gpa: Allocator) void { | |
| 181 | pub fn deinit(self: *CRTFile, gpa: Allocator) void { | |
| 179 | 182 | self.lock.release(); |
| 180 | 183 | gpa.free(self.full_object_path); |
| 181 | 184 | self.* = undefined; |
| ... | ... | @@ -223,8 +226,6 @@ const Job = union(enum) { |
| 223 | 226 | libcxxabi: void, |
| 224 | 227 | libtsan: void, |
| 225 | 228 | libssp: void, |
| 226 | compiler_rt_lib: void, | |
| 227 | compiler_rt_obj: void, | |
| 228 | 229 | /// needed when not linking libc and using LLVM for code generation because it generates |
| 229 | 230 | /// calls to, for example, memcpy and memset. |
| 230 | 231 | zig_libc: void, |
| ... | ... | @@ -1924,13 +1925,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { |
| 1924 | 1925 | if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) { |
| 1925 | 1926 | if (is_exe_or_dyn_lib) { |
| 1926 | 1927 | log.debug("queuing a job to build compiler_rt_lib", .{}); |
| 1927 | try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} }); | |
| 1928 | comp.job_queued_compiler_rt_lib = true; | |
| 1928 | 1929 | } else if (options.output_mode != .Obj) { |
| 1929 | 1930 | log.debug("queuing a job to build compiler_rt_obj", .{}); |
| 1930 | 1931 | // If build-obj with -fcompiler-rt is requested, that is handled specially |
| 1931 | 1932 | // elsewhere. In this case we are making a static library, so we ask |
| 1932 | 1933 | // for a compiler-rt object to put in it. |
| 1933 | try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} }); | |
| 1934 | comp.job_queued_compiler_rt_obj = true; | |
| 1934 | 1935 | } |
| 1935 | 1936 | } |
| 1936 | 1937 | if (needs_c_symbols) { |
| ... | ... | @@ -1978,7 +1979,7 @@ pub fn destroy(self: *Compilation) void { |
| 1978 | 1979 | if (self.libcxxabi_static_lib) |*crt_file| { |
| 1979 | 1980 | crt_file.deinit(gpa); |
| 1980 | 1981 | } |
| 1981 | if (self.compiler_rt_static_lib) |*crt_file| { | |
| 1982 | if (self.compiler_rt_lib) |*crt_file| { | |
| 1982 | 1983 | crt_file.deinit(gpa); |
| 1983 | 1984 | } |
| 1984 | 1985 | if (self.compiler_rt_obj) |*crt_file| { |
| ... | ... | @@ -2020,6 +2021,7 @@ pub fn destroy(self: *Compilation) void { |
| 2020 | 2021 | } |
| 2021 | 2022 | |
| 2022 | 2023 | pub fn clearMiscFailures(comp: *Compilation) void { |
| 2024 | comp.alloc_failure_occurred = false; | |
| 2023 | 2025 | for (comp.misc_failures.values()) |*value| { |
| 2024 | 2026 | value.deinit(comp.gpa); |
| 2025 | 2027 | } |
| ... | ... | @@ -2532,8 +2534,10 @@ pub fn makeBinFileWritable(self: *Compilation) !void { |
| 2532 | 2534 | return self.bin_file.makeWritable(); |
| 2533 | 2535 | } |
| 2534 | 2536 | |
| 2537 | /// This function is temporally single-threaded. | |
| 2535 | 2538 | pub fn totalErrorCount(self: *Compilation) usize { |
| 2536 | var total: usize = self.failed_c_objects.count() + self.misc_failures.count(); | |
| 2539 | var total: usize = self.failed_c_objects.count() + self.misc_failures.count() + | |
| 2540 | @boolToInt(self.alloc_failure_occurred); | |
| 2537 | 2541 | |
| 2538 | 2542 | if (self.bin_file.options.module) |module| { |
| 2539 | 2543 | total += module.failed_exports.count(); |
| ... | ... | @@ -2590,6 +2594,7 @@ pub fn totalErrorCount(self: *Compilation) usize { |
| 2590 | 2594 | return total; |
| 2591 | 2595 | } |
| 2592 | 2596 | |
| 2597 | /// This function is temporally single-threaded. | |
| 2593 | 2598 | pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 2594 | 2599 | var arena = std.heap.ArenaAllocator.init(self.gpa); |
| 2595 | 2600 | errdefer arena.deinit(); |
| ... | ... | @@ -2622,6 +2627,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { |
| 2622 | 2627 | for (self.misc_failures.values()) |*value| { |
| 2623 | 2628 | try AllErrors.addPlainWithChildren(&arena, &errors, value.msg, value.children); |
| 2624 | 2629 | } |
| 2630 | if (self.alloc_failure_occurred) { | |
| 2631 | try AllErrors.addPlain(&arena, &errors, "memory allocation failure"); | |
| 2632 | } | |
| 2625 | 2633 | if (self.bin_file.options.module) |module| { |
| 2626 | 2634 | { |
| 2627 | 2635 | var it = module.failed_files.iterator(); |
| ... | ... | @@ -2739,6 +2747,8 @@ pub fn performAllTheWork( |
| 2739 | 2747 | comp.work_queue_wait_group.reset(); |
| 2740 | 2748 | defer comp.work_queue_wait_group.wait(); |
| 2741 | 2749 | |
| 2750 | const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1; | |
| 2751 | ||
| 2742 | 2752 | { |
| 2743 | 2753 | const astgen_frame = tracy.namedFrame("astgen"); |
| 2744 | 2754 | defer astgen_frame.end(); |
| ... | ... | @@ -2783,7 +2793,6 @@ pub fn performAllTheWork( |
| 2783 | 2793 | } |
| 2784 | 2794 | } |
| 2785 | 2795 | |
| 2786 | const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1; | |
| 2787 | 2796 | if (!use_stage1) { |
| 2788 | 2797 | const outdated_and_deleted_decls_frame = tracy.namedFrame("outdated_and_deleted_decls"); |
| 2789 | 2798 | defer outdated_and_deleted_decls_frame.end(); |
| ... | ... | @@ -2826,6 +2835,16 @@ pub fn performAllTheWork( |
| 2826 | 2835 | } |
| 2827 | 2836 | break; |
| 2828 | 2837 | } |
| 2838 | ||
| 2839 | if (comp.job_queued_compiler_rt_lib) { | |
| 2840 | comp.job_queued_compiler_rt_lib = false; | |
| 2841 | buildCompilerRtOneShot(comp, .Lib, &comp.compiler_rt_lib); | |
| 2842 | } | |
| 2843 | ||
| 2844 | if (comp.job_queued_compiler_rt_obj) { | |
| 2845 | comp.job_queued_compiler_rt_obj = false; | |
| 2846 | buildCompilerRtOneShot(comp, .Obj, &comp.compiler_rt_obj); | |
| 2847 | } | |
| 2829 | 2848 | } |
| 2830 | 2849 | |
| 2831 | 2850 | fn processOneJob(comp: *Compilation, job: Job) !void { |
| ... | ... | @@ -2996,7 +3015,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 2996 | 3015 | module.semaPkg(pkg) catch |err| switch (err) { |
| 2997 | 3016 | error.CurrentWorkingDirectoryUnlinked, |
| 2998 | 3017 | error.Unexpected, |
| 2999 | => try comp.setMiscFailure( | |
| 3018 | => comp.lockAndSetMiscFailure( | |
| 3000 | 3019 | .analyze_pkg, |
| 3001 | 3020 | "unexpected problem analyzing package '{s}'", |
| 3002 | 3021 | .{pkg.root_src_path}, |
| ... | ... | @@ -3011,7 +3030,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3011 | 3030 | |
| 3012 | 3031 | glibc.buildCRTFile(comp, crt_file) catch |err| { |
| 3013 | 3032 | // TODO Surface more error details. |
| 3014 | try comp.setMiscFailure(.glibc_crt_file, "unable to build glibc CRT file: {s}", .{ | |
| 3033 | comp.lockAndSetMiscFailure(.glibc_crt_file, "unable to build glibc CRT file: {s}", .{ | |
| 3015 | 3034 | @errorName(err), |
| 3016 | 3035 | }); |
| 3017 | 3036 | }; |
| ... | ... | @@ -3022,7 +3041,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3022 | 3041 | |
| 3023 | 3042 | glibc.buildSharedObjects(comp) catch |err| { |
| 3024 | 3043 | // TODO Surface more error details. |
| 3025 | try comp.setMiscFailure( | |
| 3044 | comp.lockAndSetMiscFailure( | |
| 3026 | 3045 | .glibc_shared_objects, |
| 3027 | 3046 | "unable to build glibc shared objects: {s}", |
| 3028 | 3047 | .{@errorName(err)}, |
| ... | ... | @@ -3035,7 +3054,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3035 | 3054 | |
| 3036 | 3055 | musl.buildCRTFile(comp, crt_file) catch |err| { |
| 3037 | 3056 | // TODO Surface more error details. |
| 3038 | try comp.setMiscFailure( | |
| 3057 | comp.lockAndSetMiscFailure( | |
| 3039 | 3058 | .musl_crt_file, |
| 3040 | 3059 | "unable to build musl CRT file: {s}", |
| 3041 | 3060 | .{@errorName(err)}, |
| ... | ... | @@ -3048,7 +3067,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3048 | 3067 | |
| 3049 | 3068 | mingw.buildCRTFile(comp, crt_file) catch |err| { |
| 3050 | 3069 | // TODO Surface more error details. |
| 3051 | try comp.setMiscFailure( | |
| 3070 | comp.lockAndSetMiscFailure( | |
| 3052 | 3071 | .mingw_crt_file, |
| 3053 | 3072 | "unable to build mingw-w64 CRT file: {s}", |
| 3054 | 3073 | .{@errorName(err)}, |
| ... | ... | @@ -3062,7 +3081,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3062 | 3081 | const link_lib = comp.bin_file.options.system_libs.keys()[index]; |
| 3063 | 3082 | mingw.buildImportLib(comp, link_lib) catch |err| { |
| 3064 | 3083 | // TODO Surface more error details. |
| 3065 | try comp.setMiscFailure( | |
| 3084 | comp.lockAndSetMiscFailure( | |
| 3066 | 3085 | .windows_import_lib, |
| 3067 | 3086 | "unable to generate DLL import .lib file: {s}", |
| 3068 | 3087 | .{@errorName(err)}, |
| ... | ... | @@ -3075,7 +3094,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3075 | 3094 | |
| 3076 | 3095 | libunwind.buildStaticLib(comp) catch |err| { |
| 3077 | 3096 | // TODO Surface more error details. |
| 3078 | try comp.setMiscFailure( | |
| 3097 | comp.lockAndSetMiscFailure( | |
| 3079 | 3098 | .libunwind, |
| 3080 | 3099 | "unable to build libunwind: {s}", |
| 3081 | 3100 | .{@errorName(err)}, |
| ... | ... | @@ -3088,7 +3107,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3088 | 3107 | |
| 3089 | 3108 | libcxx.buildLibCXX(comp) catch |err| { |
| 3090 | 3109 | // TODO Surface more error details. |
| 3091 | try comp.setMiscFailure( | |
| 3110 | comp.lockAndSetMiscFailure( | |
| 3092 | 3111 | .libcxx, |
| 3093 | 3112 | "unable to build libcxx: {s}", |
| 3094 | 3113 | .{@errorName(err)}, |
| ... | ... | @@ -3101,7 +3120,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3101 | 3120 | |
| 3102 | 3121 | libcxx.buildLibCXXABI(comp) catch |err| { |
| 3103 | 3122 | // TODO Surface more error details. |
| 3104 | try comp.setMiscFailure( | |
| 3123 | comp.lockAndSetMiscFailure( | |
| 3105 | 3124 | .libcxxabi, |
| 3106 | 3125 | "unable to build libcxxabi: {s}", |
| 3107 | 3126 | .{@errorName(err)}, |
| ... | ... | @@ -3114,7 +3133,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3114 | 3133 | |
| 3115 | 3134 | libtsan.buildTsan(comp) catch |err| { |
| 3116 | 3135 | // TODO Surface more error details. |
| 3117 | try comp.setMiscFailure( | |
| 3136 | comp.lockAndSetMiscFailure( | |
| 3118 | 3137 | .libtsan, |
| 3119 | 3138 | "unable to build TSAN library: {s}", |
| 3120 | 3139 | .{@errorName(err)}, |
| ... | ... | @@ -3127,51 +3146,13 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3127 | 3146 | |
| 3128 | 3147 | wasi_libc.buildCRTFile(comp, crt_file) catch |err| { |
| 3129 | 3148 | // TODO Surface more error details. |
| 3130 | try comp.setMiscFailure( | |
| 3149 | comp.lockAndSetMiscFailure( | |
| 3131 | 3150 | .wasi_libc_crt_file, |
| 3132 | 3151 | "unable to build WASI libc CRT file: {s}", |
| 3133 | 3152 | .{@errorName(err)}, |
| 3134 | 3153 | ); |
| 3135 | 3154 | }; |
| 3136 | 3155 | }, |
| 3137 | .compiler_rt_lib => { | |
| 3138 | const named_frame = tracy.namedFrame("compiler_rt_lib"); | |
| 3139 | defer named_frame.end(); | |
| 3140 | ||
| 3141 | comp.buildOutputFromZig( | |
| 3142 | "compiler_rt.zig", | |
| 3143 | .Lib, | |
| 3144 | &comp.compiler_rt_static_lib, | |
| 3145 | .compiler_rt, | |
| 3146 | ) catch |err| switch (err) { | |
| 3147 | error.OutOfMemory => return error.OutOfMemory, | |
| 3148 | error.SubCompilationFailed => return, // error reported already | |
| 3149 | else => try comp.setMiscFailure( | |
| 3150 | .compiler_rt, | |
| 3151 | "unable to build compiler_rt: {s}", | |
| 3152 | .{@errorName(err)}, | |
| 3153 | ), | |
| 3154 | }; | |
| 3155 | }, | |
| 3156 | .compiler_rt_obj => { | |
| 3157 | const named_frame = tracy.namedFrame("compiler_rt_obj"); | |
| 3158 | defer named_frame.end(); | |
| 3159 | ||
| 3160 | comp.buildOutputFromZig( | |
| 3161 | "compiler_rt.zig", | |
| 3162 | .Obj, | |
| 3163 | &comp.compiler_rt_obj, | |
| 3164 | .compiler_rt, | |
| 3165 | ) catch |err| switch (err) { | |
| 3166 | error.OutOfMemory => return error.OutOfMemory, | |
| 3167 | error.SubCompilationFailed => return, // error reported already | |
| 3168 | else => try comp.setMiscFailure( | |
| 3169 | .compiler_rt, | |
| 3170 | "unable to build compiler_rt: {s}", | |
| 3171 | .{@errorName(err)}, | |
| 3172 | ), | |
| 3173 | }; | |
| 3174 | }, | |
| 3175 | 3156 | .libssp => { |
| 3176 | 3157 | const named_frame = tracy.namedFrame("libssp"); |
| 3177 | 3158 | defer named_frame.end(); |
| ... | ... | @@ -3184,7 +3165,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3184 | 3165 | ) catch |err| switch (err) { |
| 3185 | 3166 | error.OutOfMemory => return error.OutOfMemory, |
| 3186 | 3167 | error.SubCompilationFailed => return, // error reported already |
| 3187 | else => try comp.setMiscFailure( | |
| 3168 | else => comp.lockAndSetMiscFailure( | |
| 3188 | 3169 | .libssp, |
| 3189 | 3170 | "unable to build libssp: {s}", |
| 3190 | 3171 | .{@errorName(err)}, |
| ... | ... | @@ -3203,7 +3184,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void { |
| 3203 | 3184 | ) catch |err| switch (err) { |
| 3204 | 3185 | error.OutOfMemory => return error.OutOfMemory, |
| 3205 | 3186 | error.SubCompilationFailed => return, // error reported already |
| 3206 | else => try comp.setMiscFailure( | |
| 3187 | else => comp.lockAndSetMiscFailure( | |
| 3207 | 3188 | .zig_libc, |
| 3208 | 3189 | "unable to build zig's multitarget libc: {s}", |
| 3209 | 3190 | .{@errorName(err)}, |
| ... | ... | @@ -3307,11 +3288,7 @@ fn workerUpdateBuiltinZigFile( |
| 3307 | 3288 | |
| 3308 | 3289 | comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{ |
| 3309 | 3290 | dir_path, @errorName(err), |
| 3310 | }) catch |oom| switch (oom) { | |
| 3311 | error.OutOfMemory => log.err("unable to write builtin.zig to {s}: {s}", .{ | |
| 3312 | dir_path, @errorName(err), | |
| 3313 | }), | |
| 3314 | }; | |
| 3291 | }); | |
| 3315 | 3292 | }; |
| 3316 | 3293 | } |
| 3317 | 3294 | |
| ... | ... | @@ -3525,6 +3502,21 @@ fn workerUpdateCObject( |
| 3525 | 3502 | }; |
| 3526 | 3503 | } |
| 3527 | 3504 | |
| 3505 | fn buildCompilerRtOneShot( | |
| 3506 | comp: *Compilation, | |
| 3507 | output_mode: std.builtin.OutputMode, | |
| 3508 | out: *?CRTFile, | |
| 3509 | ) void { | |
| 3510 | comp.buildOutputFromZig("compiler_rt.zig", output_mode, out, .compiler_rt) catch |err| switch (err) { | |
| 3511 | error.SubCompilationFailed => return, // error reported already | |
| 3512 | else => comp.lockAndSetMiscFailure( | |
| 3513 | .compiler_rt, | |
| 3514 | "unable to build compiler_rt: {s}", | |
| 3515 | .{@errorName(err)}, | |
| 3516 | ), | |
| 3517 | }; | |
| 3518 | } | |
| 3519 | ||
| 3528 | 3520 | fn reportRetryableCObjectError( |
| 3529 | 3521 | comp: *Compilation, |
| 3530 | 3522 | c_object: *CObject, |
| ... | ... | @@ -4623,14 +4615,21 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { |
| 4623 | 4615 | comp.bin_file.options.object_format != .c; |
| 4624 | 4616 | } |
| 4625 | 4617 | |
| 4626 | fn setMiscFailure( | |
| 4618 | fn setAllocFailure(comp: *Compilation) void { | |
| 4619 | log.debug("memory allocation failure", .{}); | |
| 4620 | comp.alloc_failure_occurred = true; | |
| 4621 | } | |
| 4622 | ||
| 4623 | /// Assumes that Compilation mutex is locked. | |
| 4624 | /// See also `lockAndSetMiscFailure`. | |
| 4625 | pub fn setMiscFailure( | |
| 4627 | 4626 | comp: *Compilation, |
| 4628 | 4627 | tag: MiscTask, |
| 4629 | 4628 | comptime format: []const u8, |
| 4630 | 4629 | args: anytype, |
| 4631 | ) Allocator.Error!void { | |
| 4632 | try comp.misc_failures.ensureUnusedCapacity(comp.gpa, 1); | |
| 4633 | const msg = try std.fmt.allocPrint(comp.gpa, format, args); | |
| 4630 | ) void { | |
| 4631 | comp.misc_failures.ensureUnusedCapacity(comp.gpa, 1) catch return comp.setAllocFailure(); | |
| 4632 | const msg = std.fmt.allocPrint(comp.gpa, format, args) catch return comp.setAllocFailure(); | |
| 4634 | 4633 | const gop = comp.misc_failures.getOrPutAssumeCapacity(tag); |
| 4635 | 4634 | if (gop.found_existing) { |
| 4636 | 4635 | gop.value_ptr.deinit(comp.gpa); |
| ... | ... | @@ -4638,6 +4637,19 @@ fn setMiscFailure( |
| 4638 | 4637 | gop.value_ptr.* = .{ .msg = msg }; |
| 4639 | 4638 | } |
| 4640 | 4639 | |
| 4640 | /// See also `setMiscFailure`. | |
| 4641 | pub fn lockAndSetMiscFailure( | |
| 4642 | comp: *Compilation, | |
| 4643 | tag: MiscTask, | |
| 4644 | comptime format: []const u8, | |
| 4645 | args: anytype, | |
| 4646 | ) void { | |
| 4647 | comp.mutex.lock(); | |
| 4648 | defer comp.mutex.unlock(); | |
| 4649 | ||
| 4650 | return setMiscFailure(comp, tag, format, args); | |
| 4651 | } | |
| 4652 | ||
| 4641 | 4653 | pub fn dump_argv(argv: []const []const u8) void { |
| 4642 | 4654 | for (argv[0 .. argv.len - 1]) |arg| { |
| 4643 | 4655 | std.debug.print("{s} ", .{arg}); |
src/ThreadPool.zig+49-32| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const ThreadPool = @This(); |
| 4 | const WaitGroup = @import("WaitGroup.zig"); | |
| 4 | 5 | |
| 5 | 6 | mutex: std.Thread.Mutex = .{}, |
| 6 | 7 | cond: std.Thread.Condition = .{}, |
| ... | ... | @@ -19,8 +20,8 @@ const RunProto = switch (builtin.zig_backend) { |
| 19 | 20 | else => *const fn (*Runnable) void, |
| 20 | 21 | }; |
| 21 | 22 | |
| 22 | pub fn init(self: *ThreadPool, allocator: std.mem.Allocator) !void { | |
| 23 | self.* = .{ | |
| 23 | pub fn init(pool: *ThreadPool, allocator: std.mem.Allocator) !void { | |
| 24 | pool.* = .{ | |
| 24 | 25 | .allocator = allocator, |
| 25 | 26 | .threads = &[_]std.Thread{}, |
| 26 | 27 | }; |
| ... | ... | @@ -30,48 +31,48 @@ pub fn init(self: *ThreadPool, allocator: std.mem.Allocator) !void { |
| 30 | 31 | } |
| 31 | 32 | |
| 32 | 33 | const thread_count = std.math.max(1, std.Thread.getCpuCount() catch 1); |
| 33 | self.threads = try allocator.alloc(std.Thread, thread_count); | |
| 34 | errdefer allocator.free(self.threads); | |
| 34 | pool.threads = try allocator.alloc(std.Thread, thread_count); | |
| 35 | errdefer allocator.free(pool.threads); | |
| 35 | 36 | |
| 36 | 37 | // kill and join any threads we spawned previously on error. |
| 37 | 38 | var spawned: usize = 0; |
| 38 | errdefer self.join(spawned); | |
| 39 | errdefer pool.join(spawned); | |
| 39 | 40 | |
| 40 | for (self.threads) |*thread| { | |
| 41 | thread.* = try std.Thread.spawn(.{}, worker, .{self}); | |
| 41 | for (pool.threads) |*thread| { | |
| 42 | thread.* = try std.Thread.spawn(.{}, worker, .{pool}); | |
| 42 | 43 | spawned += 1; |
| 43 | 44 | } |
| 44 | 45 | } |
| 45 | 46 | |
| 46 | pub fn deinit(self: *ThreadPool) void { | |
| 47 | self.join(self.threads.len); // kill and join all threads. | |
| 48 | self.* = undefined; | |
| 47 | pub fn deinit(pool: *ThreadPool) void { | |
| 48 | pool.join(pool.threads.len); // kill and join all threads. | |
| 49 | pool.* = undefined; | |
| 49 | 50 | } |
| 50 | 51 | |
| 51 | fn join(self: *ThreadPool, spawned: usize) void { | |
| 52 | fn join(pool: *ThreadPool, spawned: usize) void { | |
| 52 | 53 | if (builtin.single_threaded) { |
| 53 | 54 | return; |
| 54 | 55 | } |
| 55 | 56 | |
| 56 | 57 | { |
| 57 | self.mutex.lock(); | |
| 58 | defer self.mutex.unlock(); | |
| 58 | pool.mutex.lock(); | |
| 59 | defer pool.mutex.unlock(); | |
| 59 | 60 | |
| 60 | 61 | // ensure future worker threads exit the dequeue loop |
| 61 | self.is_running = false; | |
| 62 | pool.is_running = false; | |
| 62 | 63 | } |
| 63 | 64 | |
| 64 | 65 | // wake up any sleeping threads (this can be done outside the mutex) |
| 65 | 66 | // then wait for all the threads we know are spawned to complete. |
| 66 | self.cond.broadcast(); | |
| 67 | for (self.threads[0..spawned]) |thread| { | |
| 67 | pool.cond.broadcast(); | |
| 68 | for (pool.threads[0..spawned]) |thread| { | |
| 68 | 69 | thread.join(); |
| 69 | 70 | } |
| 70 | 71 | |
| 71 | self.allocator.free(self.threads); | |
| 72 | pool.allocator.free(pool.threads); | |
| 72 | 73 | } |
| 73 | 74 | |
| 74 | pub fn spawn(self: *ThreadPool, comptime func: anytype, args: anytype) !void { | |
| 75 | pub fn spawn(pool: *ThreadPool, comptime func: anytype, args: anytype) !void { | |
| 75 | 76 | if (builtin.single_threaded) { |
| 76 | 77 | @call(.{}, func, args); |
| 77 | 78 | return; |
| ... | ... | @@ -98,41 +99,57 @@ pub fn spawn(self: *ThreadPool, comptime func: anytype, args: anytype) !void { |
| 98 | 99 | }; |
| 99 | 100 | |
| 100 | 101 | { |
| 101 | self.mutex.lock(); | |
| 102 | defer self.mutex.unlock(); | |
| 102 | pool.mutex.lock(); | |
| 103 | defer pool.mutex.unlock(); | |
| 103 | 104 | |
| 104 | const closure = try self.allocator.create(Closure); | |
| 105 | const closure = try pool.allocator.create(Closure); | |
| 105 | 106 | closure.* = .{ |
| 106 | 107 | .arguments = args, |
| 107 | .pool = self, | |
| 108 | .pool = pool, | |
| 108 | 109 | }; |
| 109 | 110 | |
| 110 | self.run_queue.prepend(&closure.run_node); | |
| 111 | pool.run_queue.prepend(&closure.run_node); | |
| 111 | 112 | } |
| 112 | 113 | |
| 113 | 114 | // Notify waiting threads outside the lock to try and keep the critical section small. |
| 114 | self.cond.signal(); | |
| 115 | pool.cond.signal(); | |
| 115 | 116 | } |
| 116 | 117 | |
| 117 | fn worker(self: *ThreadPool) void { | |
| 118 | self.mutex.lock(); | |
| 119 | defer self.mutex.unlock(); | |
| 118 | fn worker(pool: *ThreadPool) void { | |
| 119 | pool.mutex.lock(); | |
| 120 | defer pool.mutex.unlock(); | |
| 120 | 121 | |
| 121 | 122 | while (true) { |
| 122 | while (self.run_queue.popFirst()) |run_node| { | |
| 123 | while (pool.run_queue.popFirst()) |run_node| { | |
| 123 | 124 | // Temporarily unlock the mutex in order to execute the run_node |
| 124 | self.mutex.unlock(); | |
| 125 | defer self.mutex.lock(); | |
| 125 | pool.mutex.unlock(); | |
| 126 | defer pool.mutex.lock(); | |
| 126 | 127 | |
| 127 | 128 | const runFn = run_node.data.runFn; |
| 128 | 129 | runFn(&run_node.data); |
| 129 | 130 | } |
| 130 | 131 | |
| 131 | 132 | // Stop executing instead of waiting if the thread pool is no longer running. |
| 132 | if (self.is_running) { | |
| 133 | self.cond.wait(&self.mutex); | |
| 133 | if (pool.is_running) { | |
| 134 | pool.cond.wait(&pool.mutex); | |
| 134 | 135 | } else { |
| 135 | 136 | break; |
| 136 | 137 | } |
| 137 | 138 | } |
| 138 | 139 | } |
| 140 | ||
| 141 | pub fn waitAndWork(pool: *ThreadPool, wait_group: *WaitGroup) void { | |
| 142 | while (!wait_group.isDone()) { | |
| 143 | if (blk: { | |
| 144 | pool.mutex.lock(); | |
| 145 | defer pool.mutex.unlock(); | |
| 146 | break :blk pool.run_queue.popFirst(); | |
| 147 | }) |run_node| { | |
| 148 | run_node.data.runFn(&run_node.data); | |
| 149 | continue; | |
| 150 | } | |
| 151 | ||
| 152 | wait_group.wait(); | |
| 153 | return; | |
| 154 | } | |
| 155 | } |
src/WaitGroup.zig+7| ... | ... | @@ -37,3 +37,10 @@ pub fn reset(self: *WaitGroup) void { |
| 37 | 37 | self.state.store(0, .Monotonic); |
| 38 | 38 | self.event.reset(); |
| 39 | 39 | } |
| 40 | ||
| 41 | pub fn isDone(wg: *WaitGroup) bool { | |
| 42 | const state = wg.state.load(.Acquire); | |
| 43 | assert(state & is_waiting == 0); | |
| 44 | ||
| 45 | return (state / one_pending) == 0; | |
| 46 | } |
src/link.zig+2-5| ... | ... | @@ -792,11 +792,8 @@ pub const File = struct { |
| 792 | 792 | }), |
| 793 | 793 | } |
| 794 | 794 | } |
| 795 | if (base.options.object_format == .macho) { | |
| 796 | try base.cast(MachO).?.flushObject(comp, prog_node); | |
| 797 | } else { | |
| 798 | try base.flushModule(comp, prog_node); | |
| 799 | } | |
| 795 | try base.flushModule(comp, prog_node); | |
| 796 | ||
| 800 | 797 | const dirname = fs.path.dirname(full_out_path_z) orelse "."; |
| 801 | 798 | break :blk try fs.path.join(arena, &.{ dirname, base.intermediary_basename.? }); |
| 802 | 799 | } else null; |
src/link/Coff.zig+1-1| ... | ... | @@ -1354,7 +1354,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 1354 | 1354 | } |
| 1355 | 1355 | // MSVC compiler_rt is missing some stuff, so we build it unconditionally but |
| 1356 | 1356 | // and rely on weak linkage to allow MSVC compiler_rt functions to override ours. |
| 1357 | if (comp.compiler_rt_static_lib) |lib| { | |
| 1357 | if (comp.compiler_rt_lib) |lib| { | |
| 1358 | 1358 | try argv.append(lib.full_object_path); |
| 1359 | 1359 | } |
| 1360 | 1360 | } |
src/link/Elf.zig+1-1| ... | ... | @@ -1272,7 +1272,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v |
| 1272 | 1272 | const stack_size = self.base.options.stack_size_override orelse 16777216; |
| 1273 | 1273 | const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; |
| 1274 | 1274 | const compiler_rt_path: ?[]const u8 = blk: { |
| 1275 | if (comp.compiler_rt_static_lib) |x| break :blk x.full_object_path; | |
| 1275 | if (comp.compiler_rt_lib) |x| break :blk x.full_object_path; | |
| 1276 | 1276 | if (comp.compiler_rt_obj) |x| break :blk x.full_object_path; |
| 1277 | 1277 | break :blk null; |
| 1278 | 1278 | }; |
src/link/MachO.zig+24-26| ... | ... | @@ -436,7 +436,7 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) !v |
| 436 | 436 | return error.TODOImplementWritingStaticLibFiles; |
| 437 | 437 | } |
| 438 | 438 | } |
| 439 | try self.flushModule(comp, prog_node); | |
| 439 | return self.flushModule(comp, prog_node); | |
| 440 | 440 | } |
| 441 | 441 | |
| 442 | 442 | pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) !void { |
| ... | ... | @@ -444,8 +444,23 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 444 | 444 | defer tracy.end(); |
| 445 | 445 | |
| 446 | 446 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| 447 | if (!use_stage1 and self.base.options.output_mode == .Obj) | |
| 448 | return self.flushObject(comp, prog_node); | |
| 447 | ||
| 448 | if (build_options.have_llvm and !use_stage1) { | |
| 449 | if (self.llvm_object) |llvm_object| { | |
| 450 | try llvm_object.flushModule(comp, prog_node); | |
| 451 | ||
| 452 | llvm_object.destroy(self.base.allocator); | |
| 453 | self.llvm_object = null; | |
| 454 | ||
| 455 | if (self.base.options.output_mode == .Lib and self.base.options.link_mode == .Static) { | |
| 456 | return; | |
| 457 | } | |
| 458 | } | |
| 459 | } | |
| 460 | ||
| 461 | var sub_prog_node = prog_node.start("MachO Flush", 0); | |
| 462 | sub_prog_node.activate(); | |
| 463 | defer sub_prog_node.end(); | |
| 449 | 464 | |
| 450 | 465 | var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator); |
| 451 | 466 | defer arena_allocator.deinit(); |
| ... | ... | @@ -454,12 +469,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 454 | 469 | const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type. |
| 455 | 470 | const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path}); |
| 456 | 471 | |
| 457 | if (self.d_sym) |*d_sym| { | |
| 458 | if (self.base.options.module) |module| { | |
| 459 | try d_sym.dwarf.flushModule(&self.base, module); | |
| 460 | } | |
| 461 | } | |
| 462 | ||
| 463 | 472 | // If there is no Zig code to compile, then we should skip flushing the output file because it |
| 464 | 473 | // will not be part of the linker line anyway. |
| 465 | 474 | const module_obj_path: ?[]const u8 = if (self.base.options.module) |module| blk: { |
| ... | ... | @@ -482,8 +491,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 482 | 491 | |
| 483 | 492 | const obj_basename = self.base.intermediary_basename orelse break :blk null; |
| 484 | 493 | |
| 485 | try self.flushObject(comp, prog_node); | |
| 486 | ||
| 487 | 494 | if (fs.path.dirname(full_out_path)) |dirname| { |
| 488 | 495 | break :blk try fs.path.join(arena, &.{ dirname, obj_basename }); |
| 489 | 496 | } else { |
| ... | ... | @@ -491,9 +498,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 491 | 498 | } |
| 492 | 499 | } else null; |
| 493 | 500 | |
| 494 | var sub_prog_node = prog_node.start("MachO Flush", 0); | |
| 495 | sub_prog_node.activate(); | |
| 496 | defer sub_prog_node.end(); | |
| 501 | if (self.d_sym) |*d_sym| { | |
| 502 | if (self.base.options.module) |module| { | |
| 503 | try d_sym.dwarf.flushModule(&self.base, module); | |
| 504 | } | |
| 505 | } | |
| 497 | 506 | |
| 498 | 507 | const is_lib = self.base.options.output_mode == .Lib; |
| 499 | 508 | const is_dyn_lib = self.base.options.link_mode == .Dynamic and is_lib; |
| ... | ... | @@ -738,7 +747,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 738 | 747 | try positionals.append(p); |
| 739 | 748 | } |
| 740 | 749 | |
| 741 | if (comp.compiler_rt_static_lib) |lib| { | |
| 750 | if (comp.compiler_rt_lib) |lib| { | |
| 742 | 751 | try positionals.append(lib.full_object_path); |
| 743 | 752 | } |
| 744 | 753 | |
| ... | ... | @@ -1119,17 +1128,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 1119 | 1128 | self.cold_start = false; |
| 1120 | 1129 | } |
| 1121 | 1130 | |
| 1122 | pub fn flushObject(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) !void { | |
| 1123 | const tracy = trace(@src()); | |
| 1124 | defer tracy.end(); | |
| 1125 | ||
| 1126 | if (build_options.have_llvm) | |
| 1127 | if (self.llvm_object) |llvm_object| | |
| 1128 | return llvm_object.flushModule(comp, prog_node); | |
| 1129 | ||
| 1130 | return error.TODOImplementWritingObjFiles; | |
| 1131 | } | |
| 1132 | ||
| 1133 | 1131 | fn resolveSearchDir( |
| 1134 | 1132 | arena: Allocator, |
| 1135 | 1133 | dir: []const u8, |
src/link/Wasm.zig+1-1| ... | ... | @@ -2255,7 +2255,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! |
| 2255 | 2255 | const is_obj = self.base.options.output_mode == .Obj; |
| 2256 | 2256 | |
| 2257 | 2257 | const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt and !is_obj) |
| 2258 | comp.compiler_rt_static_lib.?.full_object_path | |
| 2258 | comp.compiler_rt_lib.?.full_object_path | |
| 2259 | 2259 | else |
| 2260 | 2260 | null; |
| 2261 | 2261 |
src/musl.zig-1| ... | ... | @@ -4,7 +4,6 @@ const mem = std.mem; |
| 4 | 4 | const path = std.fs.path; |
| 5 | 5 | const assert = std.debug.assert; |
| 6 | 6 | |
| 7 | const target_util = @import("target.zig"); | |
| 8 | 7 | const Compilation = @import("Compilation.zig"); |
| 9 | 8 | const build_options = @import("build_options"); |
| 10 | 9 |