authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-06-20 00:26:39+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-06-20 00:26:39+02:00
log74442f35030a9c4f4ff65db01a18e8fb2f2a1ecf
tree0a3417d662326ce757cc8d89ca7e19498ead9207
parent33cf6ef621114daad63d14067b6ff374e664d410
parent1d4dbf8d3c891346e6dc978764e8bce9c85ad044
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11847 from ziglang/better-libcompiler_rt


204 files changed, 7587 insertions(+), 6205 deletions(-)

CMakeLists.txt+113-10
......@@ -480,8 +480,15 @@ set(ZIG_STAGE2_SOURCES
480480 "${CMAKE_SOURCE_DIR}/lib/std/sort.zig"
481481 "${CMAKE_SOURCE_DIR}/lib/compiler_rt.zig"
482482 "${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"
484488 "${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"
485492 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/arm.zig"
486493 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/atomics.zig"
487494 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/aulldiv.zig"
......@@ -490,7 +497,12 @@ set(ZIG_STAGE2_SOURCES
490497 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/ceil.zig"
491498 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/clear_cache.zig"
492499 "${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"
494506 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cos.zig"
495507 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/count0bits.zig"
496508 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/divdf3.zig"
......@@ -501,25 +513,101 @@ set(ZIG_STAGE2_SOURCES
501513 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/emutls.zig"
502514 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/exp.zig"
503515 "${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"
506526 "${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"
509588 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floor.zig"
510589 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fma.zig"
511590 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fmax.zig"
512591 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fmin.zig"
513592 "${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"
514597 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/int.zig"
598 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/int_to_float.zig"
515599 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log.zig"
516600 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log10.zig"
517601 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log2.zig"
518602 "${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"
520604 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/muldi3.zig"
605 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulf3.zig"
521606 "${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"
522609 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/multi3.zig"
610 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulxf3.zig"
523611 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negXf2.zig"
524612 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negXi2.zig"
525613 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negv.zig"
......@@ -533,19 +621,34 @@ set(ZIG_STAGE2_SOURCES
533621 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/shift.zig"
534622 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sin.zig"
535623 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sincos.zig"
536 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sparc.zig"
537624 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/sqrt.zig"
538625 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/stack_probe.zig"
626 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subdf3.zig"
539627 "${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"
540631 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/tan.zig"
541632 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trig.zig"
542633 "${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"
545645 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivmod.zig"
546646 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivmodti4.zig"
547647 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivti3.zig"
548648 "${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"
549652 "${CMAKE_SOURCE_DIR}/lib/std/start.zig"
550653 "${CMAKE_SOURCE_DIR}/lib/std/std.zig"
551654 "${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
7575release/bin/zig build test-run-translated-c -Denable-macos-sdk
7676release/bin/zig build docs -Denable-macos-sdk
7777release/bin/zig build test-fmt -Denable-macos-sdk
78release/bin/zig build test-cases -Denable-macos-sdk
78release/bin/zig build test-cases -Denable-macos-sdk -Dsingle-threaded
7979
8080if [ "${BUILD_REASON}" != "PullRequest" ]; then
8181 mv ../LICENSE release/
lib/compiler_rt.zig+177-880
......@@ -1,885 +1,182 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const os_tag = builtin.os.tag;
5const arch = builtin.cpu.arch;
6const abi = builtin.abi;
7
8const is_gnu = abi.isGnu();
9const is_mingw = os_tag == .windows and is_gnu;
10const is_darwin = std.Target.Os.Tag.isDarwin(os_tag);
11const is_ppc = arch.isPPC() or arch.isPPC64();
12
13const linkage = if (is_test)
14 std.builtin.GlobalLinkage.Internal
15else
16 std.builtin.GlobalLinkage.Weak;
17
18const strong_linkage = if (is_test)
19 std.builtin.GlobalLinkage.Internal
20else
21 std.builtin.GlobalLinkage.Strong;
1pub const panic = @import("compiler_rt/common.zig").panic;
222
233comptime {
24 // These files do their own comptime exporting logic.
254 _ = @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
826inline 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}
8745
875// Avoid dragging in the runtime safety mechanisms into this .o file,
876// unless we're trying to test this file.
877pub 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");
885182}
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
5inline fn absvXi(comptime ST: type, a: ST) ST {
1/// absv - absolute oVerflow
2/// * @panic if value can not be represented
3pub inline fn absv(comptime ST: type, a: ST) ST {
64 const UT = switch (ST) {
75 i32 => u32,
86 i64 => u64,
......@@ -21,18 +19,6 @@ inline fn absvXi(comptime ST: type, a: ST) ST {
2119 return x;
2220}
2321
24pub fn __absvsi2(a: i32) callconv(.C) i32 {
25 return absvXi(i32, a);
26}
27
28pub fn __absvdi2(a: i64) callconv(.C) i64 {
29 return absvXi(i64, a);
30}
31
32pub fn __absvti2(a: i128) callconv(.C) i128 {
33 return absvXi(i128, a);
34}
35
3622test {
3723 _ = @import("absvsi2_test.zig");
3824 _ = @import("absvdi2_test.zig");
lib/compiler_rt/absvdi2.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const absv = @import("./absv.zig").absv;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__absvdi2, .{ .name = "__absvdi2", .linkage = common.linkage });
8}
9
10pub 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 @@
1const absv = @import("absv.zig");
21const testing = @import("std").testing;
32
3const __absvdi2 = @import("absvdi2.zig").__absvdi2;
4
45fn test__absvdi2(a: i64, expected: i64) !void {
5 var result = absv.__absvdi2(a);
6 var result = __absvdi2(a);
67 try testing.expectEqual(expected, result);
78}
89
lib/compiler_rt/absvsi2.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const absv = @import("./absv.zig").absv;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__absvsi2, .{ .name = "__absvsi2", .linkage = common.linkage });
8}
9
10pub 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 @@
1const absv = @import("absv.zig");
21const testing = @import("std").testing;
32
3const __absvsi2 = @import("absvsi2.zig").__absvsi2;
4
45fn test__absvsi2(a: i32, expected: i32) !void {
5 var result = absv.__absvsi2(a);
6 var result = __absvsi2(a);
67 try testing.expectEqual(expected, result);
78}
89
lib/compiler_rt/absvti2.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const absv = @import("./absv.zig").absv;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__absvti2, .{ .name = "__absvti2", .linkage = common.linkage });
8}
9
10pub 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 @@
1const absv = @import("absv.zig");
21const testing = @import("std").testing;
32
3const __absvti2 = @import("absvti2.zig").__absvti2;
4
45fn test__absvti2(a: i128, expected: i128) !void {
5 var result = absv.__absvti2(a);
6 var result = __absvti2(a);
67 try testing.expectEqual(expected, result);
78}
89
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
5const std = @import("std");
6const math = std.math;
7const builtin = @import("builtin");
8const compiler_rt = @import("../compiler_rt.zig");
9
10pub fn __addsf3(a: f32, b: f32) callconv(.C) f32 {
11 return addXf3(f32, a, b);
12}
13
14pub fn __adddf3(a: f64, b: f64) callconv(.C) f64 {
15 return addXf3(f64, a, b);
16}
17
18pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 {
19 return addXf3(f80, a, b);
20}
21
22pub 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
28pub fn __addtf3(a: f128, b: f128) callconv(.C) f128 {
29 return addXf3(f128, a, b);
30}
31
32pub 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
37pub 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
42pub 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
47pub fn __aeabi_fadd(a: f32, b: f32) callconv(.AAPCS) f32 {
48 @setRuntimeSafety(false);
49 return @call(.{ .modifier = .always_inline }, __addsf3, .{ a, b });
50}
51
52pub fn __aeabi_dadd(a: f64, b: f64) callconv(.AAPCS) f64 {
53 @setRuntimeSafety(false);
54 return @call(.{ .modifier = .always_inline }, __adddf3, .{ a, b });
55}
56
57pub fn __aeabi_fsub(a: f32, b: f32) callconv(.AAPCS) f32 {
58 @setRuntimeSafety(false);
59 return @call(.{ .modifier = .always_inline }, __subsf3, .{ a, b });
60}
61
62pub 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
68fn 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
81fn 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
242test {
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
6const std = @import("std");
7const math = std.math;
8const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64);
9
10const __addtf3 = @import("addXf3.zig").__addtf3;
11
12fn 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
34test "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
51const __subtf3 = @import("addXf3.zig").__subtf3;
52
53fn 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
75test "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
90const __addxf3 = @import("addXf3.zig").__addxf3;
91const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1)));
92
93fn 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
106test "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 @@
1const common = @import("./common.zig");
2const addf3 = @import("./addf3.zig").addf3;
3
4pub const panic = common.panic;
5
6comptime {
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
14fn __adddf3(a: f64, b: f64) callconv(.C) f64 {
15 return addf3(f64, a, b);
16}
17
18fn __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 @@
1const std = @import("std");
2const math = std.math;
3const common = @import("./common.zig");
4const 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
9pub 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
170test {
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
6const std = @import("std");
7const math = std.math;
8const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64);
9
10const __addtf3 = @import("addtf3.zig").__addtf3;
11const __addxf3 = @import("addxf3.zig").__addxf3;
12const __subtf3 = @import("subtf3.zig").__subtf3;
13
14fn 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
36test "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
53fn 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
75test "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
90const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1)));
91
92fn 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
105test "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 @@
1const std = @import("std");
12const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
5pub const panic = @import("common.zig").panic;
6
7comptime {
8 @export(__addosi4, .{ .name = "__addosi4", .linkage = linkage });
9 @export(__addodi4, .{ .name = "__addodi4", .linkage = linkage });
10 @export(__addoti4, .{ .name = "__addoti4", .linkage = linkage });
11}
212
313// addo - add overflow
414// * return a+%b.
lib/compiler_rt/addsf3.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const addf3 = @import("./addf3.zig").addf3;
3
4pub const panic = common.panic;
5
6comptime {
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
14fn __addsf3(a: f32, b: f32) callconv(.C) f32 {
15 return addf3(f32, a, b);
16}
17
18fn __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 @@
1const common = @import("./common.zig");
2const addf3 = @import("./addf3.zig").addf3;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __addtf3(a: f128, b: f128) callconv(.C) f128 {
17 return addf3(f128, a, b);
18}
19
20fn __addkf3(a: f128, b: f128) callconv(.C) f128 {
21 return addf3(f128, a, b);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const addf3 = @import("./addf3.zig").addf3;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__addxf3, .{ .name = "__addxf3", .linkage = common.linkage });
8}
9
10pub 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 @@
11// ARM specific builtins
2const std = @import("std");
23const builtin = @import("builtin");
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
344
445const __divmodsi4 = @import("int.zig").__divmodsi4;
546const __udivmodsi4 = @import("int.zig").__udivmodsi4;
......@@ -14,11 +55,27 @@ pub fn __aeabi_memcpy(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
1455 @setRuntimeSafety(false);
1556 _ = memcpy(dest, src, n);
1657}
58pub fn __aeabi_memcpy4(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
59 @setRuntimeSafety(false);
60 _ = memcpy(dest, src, n);
61}
62pub fn __aeabi_memcpy8(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
63 @setRuntimeSafety(false);
64 _ = memcpy(dest, src, n);
65}
1766
1867pub fn __aeabi_memmove(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
1968 @setRuntimeSafety(false);
2069 _ = memmove(dest, src, n);
2170}
71pub fn __aeabi_memmove4(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
72 @setRuntimeSafety(false);
73 _ = memmove(dest, src, n);
74}
75pub fn __aeabi_memmove8(dest: [*]u8, src: [*]u8, n: usize) callconv(.AAPCS) void {
76 @setRuntimeSafety(false);
77 _ = memmove(dest, src, n);
78}
2279
2380pub fn __aeabi_memset(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void {
2481 @setRuntimeSafety(false);
......@@ -26,16 +83,32 @@ pub fn __aeabi_memset(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void {
2683 // two arguments swapped
2784 _ = memset(dest, c, n);
2885}
86pub fn __aeabi_memset4(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void {
87 @setRuntimeSafety(false);
88 _ = memset(dest, c, n);
89}
90pub fn __aeabi_memset8(dest: [*]u8, n: usize, c: u8) callconv(.AAPCS) void {
91 @setRuntimeSafety(false);
92 _ = memset(dest, c, n);
93}
2994
3095pub fn __aeabi_memclr(dest: [*]u8, n: usize) callconv(.AAPCS) void {
3196 @setRuntimeSafety(false);
3297 _ = memset(dest, 0, n);
3398}
99pub fn __aeabi_memclr4(dest: [*]u8, n: usize) callconv(.AAPCS) void {
100 @setRuntimeSafety(false);
101 _ = memset(dest, 0, n);
102}
103pub fn __aeabi_memclr8(dest: [*]u8, n: usize) callconv(.AAPCS) void {
104 @setRuntimeSafety(false);
105 _ = memset(dest, 0, n);
106}
34107
35108// Dummy functions to avoid errors during the linking phase
36pub fn __aeabi_unwind_cpp_pr0() callconv(.C) void {}
37pub fn __aeabi_unwind_cpp_pr1() callconv(.C) void {}
38pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void {}
109pub fn __aeabi_unwind_cpp_pr0() callconv(.AAPCS) void {}
110pub fn __aeabi_unwind_cpp_pr1() callconv(.AAPCS) void {}
111pub fn __aeabi_unwind_cpp_pr2() callconv(.AAPCS) void {}
39112
40113// This function can only clobber r0 according to the ABI
41114pub fn __aeabi_read_tp() callconv(.Naked) void {
lib/compiler_rt/atomics.zig+1-1
......@@ -2,8 +2,8 @@ const std = @import("std");
22const builtin = @import("builtin");
33const cpu = builtin.cpu;
44const arch = cpu.arch;
5
65const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
6pub const panic = @import("common.zig").panic;
77
88// This parameter is true iff the target architecture supports the bare minimum
99// to implement the atomic load/store intrinsics.
lib/compiler_rt/aulldiv.zig+14-1
......@@ -1,7 +1,20 @@
1const std = @import("std");
12const builtin = @import("builtin");
3const arch = builtin.cpu.arch;
4const abi = builtin.abi;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
216
317pub fn _alldiv(a: i64, b: i64) callconv(.Stdcall) i64 {
4 @setRuntimeSafety(builtin.is_test);
518 const s_a = a >> (64 - 1);
619 const s_b = b >> (64 - 1);
720
lib/compiler_rt/aullrem.zig+14-1
......@@ -1,7 +1,20 @@
1const std = @import("std");
12const builtin = @import("builtin");
3const arch = builtin.cpu.arch;
4const abi = builtin.abi;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
216
317pub fn _allrem(a: i64, b: i64) callconv(.Stdcall) i64 {
4 @setRuntimeSafety(builtin.is_test);
518 const s_a = a >> (64 - 1);
619 const s_b = b >> (64 - 1);
720
lib/compiler_rt/bswap.zig+9-1
......@@ -1,5 +1,14 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const common = @import("common.zig");
4
5pub const panic = common.panic;
6
7comptime {
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}
312
413// bswap - byteswap
514// - bswapXi2 for unoptimized big and little endian
......@@ -12,7 +21,6 @@ const builtin = @import("builtin");
1221// 00 00 00 ff << 3*8 (rightmost byte)
1322
1423inline fn bswapXi2(comptime T: type, a: T) T {
15 @setRuntimeSafety(builtin.is_test);
1624 switch (@bitSizeOf(T)) {
1725 32 => {
1826 // 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
66
77const std = @import("std");
8const builtin = @import("builtin");
9const arch = builtin.cpu.arch;
810const math = std.math;
911const expect = std.testing.expect;
12const common = @import("common.zig");
13
14pub const panic = common.panic;
15
16comptime {
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}
1025
1126pub fn __ceilh(x: f16) callconv(.C) f16 {
1227 // TODO: more efficient implementation
lib/compiler_rt/clear_cache.zig+8-1
......@@ -2,6 +2,7 @@ const std = @import("std");
22const builtin = @import("builtin");
33const arch = builtin.cpu.arch;
44const os = builtin.os.tag;
5pub const panic = @import("common.zig").panic;
56
67// Ported from llvm-project d32170dbd5b0d54436537b6b75beaf44324e0c28
78
......@@ -10,7 +11,13 @@ const os = builtin.os.tag;
1011// It is expected to invalidate the instruction cache for the
1112// specified range.
1213
13pub fn clear_cache(start: usize, end: usize) callconv(.C) void {
14comptime {
15 if (builtin.zig_backend != .stage2_llvm) {
16 _ = clear_cache;
17 }
18}
19
20fn clear_cache(start: usize, end: usize) callconv(.C) void {
1421 const x86 = switch (arch) {
1522 .i386, .x86_64 => true,
1623 else => false,
lib/compiler_rt/cmp.zig+13-1
......@@ -1,5 +1,18 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const common = @import("common.zig");
5
6pub const panic = common.panic;
7
8comptime {
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}
316
417// cmp - signed compare
518// - cmpXi2_generic for unoptimized little and big endian
......@@ -12,7 +25,6 @@ const builtin = @import("builtin");
1225// a > b => 2
1326
1427inline fn XcmpXi2(comptime T: type, a: T, b: T) i32 {
15 @setRuntimeSafety(builtin.is_test);
1628 var cmp1: i32 = 0;
1729 var cmp2: i32 = 0;
1830 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
3const common = @import("./common.zig");
4const comparef = @import("./comparef.zig");
5
6pub const panic = common.panic;
7
8comptime {
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`.
28fn __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."
34pub 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.
41pub 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.
48pub 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."
54pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 {
55 return __cmpdf2(a, b);
56}
57
58fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.AAPCS) i32 {
59 return @boolToInt(comparef.cmpf2(f64, comparef.LE, a, b) == .Equal);
60}
61
62fn __aeabi_dcmplt(a: f64, b: f64) callconv(.AAPCS) i32 {
63 return @boolToInt(comparef.cmpf2(f64, comparef.LE, a, b) == .Less);
64}
65
66fn __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
3const common = @import("./common.zig");
4const comparef = @import("./comparef.zig");
5
6pub const panic = common.panic;
7
8comptime {
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`.
28fn __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."
34pub 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.
41pub 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.
48pub 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."
54pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 {
55 return __cmpsf2(a, b);
56}
57
58fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.AAPCS) i32 {
59 return @boolToInt(comparef.cmpf2(f32, comparef.LE, a, b) == .Equal);
60}
61
62fn __aeabi_fcmplt(a: f32, b: f32) callconv(.AAPCS) i32 {
63 return @boolToInt(comparef.cmpf2(f32, comparef.LE, a, b) == .Less);
64}
65
66fn __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
3const common = @import("./common.zig");
4const comparef = @import("./comparef.zig");
5
6pub const panic = common.panic;
7
8comptime {
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`.
37fn __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."
43fn __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.
50fn __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.
57fn __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."
63fn __lttf2(a: f128, b: f128) callconv(.C) i32 {
64 return __cmptf2(a, b);
65}
66
67fn __eqkf2(a: f128, b: f128) callconv(.C) i32 {
68 return __cmptf2(a, b);
69}
70
71fn __nekf2(a: f128, b: f128) callconv(.C) i32 {
72 return __cmptf2(a, b);
73}
74
75fn __ltkf2(a: f128, b: f128) callconv(.C) i32 {
76 return __cmptf2(a, b);
77}
78
79fn __lekf2(a: f128, b: f128) callconv(.C) i32 {
80 return __cmptf2(a, b);
81}
82
83const SparcFCMP = enum(i32) {
84 Equal = 0,
85 Less = 1,
86 Greater = 2,
87 Unordered = 3,
88};
89
90fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.C) i32 {
91 return @enumToInt(comparef.cmpf2(f128, SparcFCMP, a.*, b.*));
92}
93
94fn _Qp_feq(a: *const f128, b: *const f128) callconv(.C) bool {
95 return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) == .Equal;
96}
97
98fn _Qp_fne(a: *const f128, b: *const f128) callconv(.C) bool {
99 return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) != .Equal;
100}
101
102fn _Qp_flt(a: *const f128, b: *const f128) callconv(.C) bool {
103 return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) == .Less;
104}
105
106fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.C) bool {
107 return @intToEnum(SparcFCMP, _Qp_cmp(a, b)) == .Greater;
108}
109
110fn _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
117fn _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
3const common = @import("./common.zig");
4const comparef = @import("./comparef.zig");
5
6pub const panic = common.panic;
7
8comptime {
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`.
22fn __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."
28fn __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.
35fn __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.
42fn __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."
48fn __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 @@
1const std = @import("std");
2const builtin = @import("builtin");
3
4pub const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
5pub 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};
18pub 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
38pub 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
49pub 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.
53pub 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.
67pub const F16T = if (builtin.cpu.arch.isAARCH64()) f16 else u16;
68
69pub 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
183pub 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
5const std = @import("std");
6const builtin = @import("builtin");
7
8const LE = enum(i32) {
9 Less = -1,
10 Equal = 0,
11 Greater = 1,
12
13 const Unordered: LE = .Greater;
14};
15
16const GE = enum(i32) {
17 Less = -1,
18 Equal = 0,
19 Greater = 1,
20
21 const Unordered: GE = .Less;
22};
23
24pub 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
70pub 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
89pub 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
95pub 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
101pub fn __eqsf2(a: f32, b: f32) callconv(.C) i32 {
102 return __lesf2(a, b);
103}
104
105pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 {
106 return __lesf2(a, b);
107}
108
109pub fn __nesf2(a: f32, b: f32) callconv(.C) i32 {
110 return __lesf2(a, b);
111}
112
113pub fn __gtsf2(a: f32, b: f32) callconv(.C) i32 {
114 return __gesf2(a, b);
115}
116
117// Comparison between f64
118
119pub 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
125pub 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
131pub fn __eqdf2(a: f64, b: f64) callconv(.C) i32 {
132 return __ledf2(a, b);
133}
134
135pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 {
136 return __ledf2(a, b);
137}
138
139pub fn __nedf2(a: f64, b: f64) callconv(.C) i32 {
140 return __ledf2(a, b);
141}
142
143pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 {
144 return __gedf2(a, b);
145}
146
147// Comparison between f80
148
149pub 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
186pub 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
192pub 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
198pub fn __eqxf2(a: f80, b: f80) callconv(.C) i32 {
199 return __lexf2(a, b);
200}
201
202pub fn __ltxf2(a: f80, b: f80) callconv(.C) i32 {
203 return __lexf2(a, b);
204}
205
206pub fn __nexf2(a: f80, b: f80) callconv(.C) i32 {
207 return __lexf2(a, b);
208}
209
210pub fn __gtxf2(a: f80, b: f80) callconv(.C) i32 {
211 return __gexf2(a, b);
212}
213
214// Comparison between f128
215
216pub 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
222pub 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
228pub fn __eqtf2(a: f128, b: f128) callconv(.C) i32 {
229 return __letf2(a, b);
230}
231
232pub fn __lttf2(a: f128, b: f128) callconv(.C) i32 {
233 return __letf2(a, b);
234}
235
236pub fn __netf2(a: f128, b: f128) callconv(.C) i32 {
237 return __letf2(a, b);
238}
239
240pub fn __gttf2(a: f128, b: f128) callconv(.C) i32 {
241 return __getf2(a, b);
242}
243
244// Unordered comparison between f32/f64/f128
245
246pub fn __unordsf2(a: f32, b: f32) callconv(.C) i32 {
247 @setRuntimeSafety(builtin.is_test);
248 return unordcmp(f32, a, b);
249}
250
251pub fn __unorddf2(a: f64, b: f64) callconv(.C) i32 {
252 @setRuntimeSafety(builtin.is_test);
253 return unordcmp(f64, a, b);
254}
255
256pub 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
263pub 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
268pub 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
273pub 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
278pub 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
283pub 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
288pub fn __aeabi_fcmpun(a: f32, b: f32) callconv(.AAPCS) i32 {
289 @setRuntimeSafety(false);
290 return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b });
291}
292
293pub 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
298pub 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
303pub 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
308pub 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
313pub 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
318pub fn __aeabi_dcmpun(a: f64, b: f64) callconv(.AAPCS) i32 {
319 @setRuntimeSafety(false);
320 return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b });
321}
322
323test "comparesf2" {
324 _ = @import("comparesf2_test.zig");
325}
326test "comparedf2" {
327 _ = @import("comparedf2_test.zig");
328}
lib/compiler_rt/comparedf2_test.zig+16-8
......@@ -6,7 +6,15 @@ const std = @import("std");
66const builtin = @import("builtin");
77const is_test = builtin.is_test;
88
9const comparedf2 = @import("compareXf2.zig");
9const __eqdf2 = @import("./cmpdf2.zig").__eqdf2;
10const __ledf2 = @import("./cmpdf2.zig").__ledf2;
11const __ltdf2 = @import("./cmpdf2.zig").__ltdf2;
12const __nedf2 = @import("./cmpdf2.zig").__nedf2;
13
14const __gedf2 = @import("./gedf2.zig").__gedf2;
15const __gtdf2 = @import("./gedf2.zig").__gtdf2;
16
17const __unorddf2 = @import("./unorddf2.zig").__unorddf2;
1018
1119const TestVector = struct {
1220 a: f64,
......@@ -21,25 +29,25 @@ const TestVector = struct {
2129};
2230
2331fn test__cmpdf2(vector: TestVector) bool {
24 if (comparedf2.__eqdf2(vector.a, vector.b) != vector.eqReference) {
32 if (__eqdf2(vector.a, vector.b) != vector.eqReference) {
2533 return false;
2634 }
27 if (comparedf2.__gedf2(vector.a, vector.b) != vector.geReference) {
35 if (__gedf2(vector.a, vector.b) != vector.geReference) {
2836 return false;
2937 }
30 if (comparedf2.__gtdf2(vector.a, vector.b) != vector.gtReference) {
38 if (__gtdf2(vector.a, vector.b) != vector.gtReference) {
3139 return false;
3240 }
33 if (comparedf2.__ledf2(vector.a, vector.b) != vector.leReference) {
41 if (__ledf2(vector.a, vector.b) != vector.leReference) {
3442 return false;
3543 }
36 if (comparedf2.__ltdf2(vector.a, vector.b) != vector.ltReference) {
44 if (__ltdf2(vector.a, vector.b) != vector.ltReference) {
3745 return false;
3846 }
39 if (comparedf2.__nedf2(vector.a, vector.b) != vector.neReference) {
47 if (__nedf2(vector.a, vector.b) != vector.neReference) {
4048 return false;
4149 }
42 if (comparedf2.__unorddf2(vector.a, vector.b) != vector.unReference) {
50 if (__unorddf2(vector.a, vector.b) != vector.unReference) {
4351 return false;
4452 }
4553 return true;
lib/compiler_rt/comparef.zig created+118
......@@ -0,0 +1,118 @@
1const std = @import("std");
2
3pub const LE = enum(i32) {
4 Less = -1,
5 Equal = 0,
6 Greater = 1,
7
8 const Unordered: LE = .Greater;
9};
10
11pub const GE = enum(i32) {
12 Less = -1,
13 Equal = 0,
14 Greater = 1,
15
16 const Unordered: GE = .Less;
17};
18
19pub 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
63pub 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
100pub 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
115test {
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");
66const builtin = @import("builtin");
77const is_test = builtin.is_test;
88
9const comparesf2 = @import("compareXf2.zig");
9const __eqsf2 = @import("./cmpsf2.zig").__eqsf2;
10const __lesf2 = @import("./cmpsf2.zig").__lesf2;
11const __ltsf2 = @import("./cmpsf2.zig").__ltsf2;
12const __nesf2 = @import("./cmpsf2.zig").__nesf2;
13
14const __gesf2 = @import("./gesf2.zig").__gesf2;
15const __gtsf2 = @import("./gesf2.zig").__gtsf2;
16
17const __unordsf2 = @import("./unordsf2.zig").__unordsf2;
1018
1119const TestVector = struct {
1220 a: f32,
......@@ -21,25 +29,25 @@ const TestVector = struct {
2129};
2230
2331fn test__cmpsf2(vector: TestVector) bool {
24 if (comparesf2.__eqsf2(vector.a, vector.b) != vector.eqReference) {
32 if (__eqsf2(vector.a, vector.b) != vector.eqReference) {
2533 return false;
2634 }
27 if (comparesf2.__gesf2(vector.a, vector.b) != vector.geReference) {
35 if (__gesf2(vector.a, vector.b) != vector.geReference) {
2836 return false;
2937 }
30 if (comparesf2.__gtsf2(vector.a, vector.b) != vector.gtReference) {
38 if (__gtsf2(vector.a, vector.b) != vector.gtReference) {
3139 return false;
3240 }
33 if (comparesf2.__lesf2(vector.a, vector.b) != vector.leReference) {
41 if (__lesf2(vector.a, vector.b) != vector.leReference) {
3442 return false;
3543 }
36 if (comparesf2.__ltsf2(vector.a, vector.b) != vector.ltReference) {
44 if (__ltsf2(vector.a, vector.b) != vector.ltReference) {
3745 return false;
3846 }
39 if (comparesf2.__nesf2(vector.a, vector.b) != vector.neReference) {
47 if (__nesf2(vector.a, vector.b) != vector.neReference) {
4048 return false;
4149 }
42 if (comparesf2.__unordsf2(vector.a, vector.b) != vector.unReference) {
50 if (__unordsf2(vector.a, vector.b) != vector.unReference) {
4351 return false;
4452 }
4553 return true;
lib/compiler_rt/cos.zig+15
......@@ -1,11 +1,26 @@
11const std = @import("std");
2const builtin = @import("builtin");
3const arch = builtin.cpu.arch;
24const math = std.math;
35const expect = std.testing.expect;
6const common = @import("common.zig");
7
8pub const panic = common.panic;
49
510const trig = @import("trig.zig");
611const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
712const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
813
14comptime {
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
924pub fn __cosh(a: f16) callconv(.C) f16 {
1025 // TODO: more efficient implementation
1126 return @floatCast(f16, cosf(a));
lib/compiler_rt/count0bits.zig+16-6
......@@ -1,5 +1,21 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const common = @import("common.zig");
5
6pub const panic = common.panic;
7
8comptime {
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}
319
420// clz - count leading zeroes
521// - clzXi2 for unoptimized little and big endian
......@@ -15,8 +31,6 @@ const builtin = @import("builtin");
1531// - ffsXi2 for unoptimized little and big endian
1632
1733inline fn clzXi2(comptime T: type, a: T) i32 {
18 @setRuntimeSafety(builtin.is_test);
19
2034 var x = switch (@bitSizeOf(T)) {
2135 32 => @bitCast(u32, a),
2236 64 => @bitCast(u64, a),
......@@ -154,8 +168,6 @@ pub fn __clzti2(a: i128) callconv(.C) i32 {
154168}
155169
156170inline fn ctzXi2(comptime T: type, a: T) i32 {
157 @setRuntimeSafety(builtin.is_test);
158
159171 var x = switch (@bitSizeOf(T)) {
160172 32 => @bitCast(u32, a),
161173 64 => @bitCast(u64, a),
......@@ -191,8 +203,6 @@ pub fn __ctzti2(a: i128) callconv(.C) i32 {
191203}
192204
193205inline fn ffsXi2(comptime T: type, a: T) i32 {
194 @setRuntimeSafety(builtin.is_test);
195
196206 var x = switch (@bitSizeOf(T)) {
197207 32 => @bitCast(u32, a),
198208 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
44
55const std = @import("std");
66const builtin = @import("builtin");
7const arch = builtin.cpu.arch;
8const is_test = builtin.is_test;
9const common = @import("common.zig");
10
11const normalize = common.normalize;
12const wideMultiply = common.wideMultiply;
13
14pub const panic = common.panic;
15
16comptime {
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}
723
824pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {
9 @setRuntimeSafety(builtin.is_test);
25 return div(a, b);
26}
27
28fn __aeabi_ddiv(a: f64, b: f64) callconv(.AAPCS) f64 {
29 return div(a, b);
30}
31
32inline fn div(a: f64, b: f64) f64 {
1033 const Z = std.meta.Int(.unsigned, 64);
1134 const SignedZ = std.meta.Int(.signed, 64);
1235
......@@ -202,130 +225,6 @@ pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {
202225 }
203226}
204227
205pub 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
314pub 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
324pub fn __aeabi_ddiv(a: f64, b: f64) callconv(.AAPCS) f64 {
325 @setRuntimeSafety(false);
326 return @call(.{ .modifier = .always_inline }, __divdf3, .{ a, b });
327}
328
329228test {
330229 _ = @import("divdf3_test.zig");
331230}
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
44
55const std = @import("std");
66const builtin = @import("builtin");
7const arch = builtin.cpu.arch;
8
9const common = @import("common.zig");
10const normalize = common.normalize;
11
12pub const panic = common.panic;
13
14comptime {
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}
721
822pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
9 @setRuntimeSafety(builtin.is_test);
23 return div(a, b);
24}
25
26fn __aeabi_fdiv(a: f32, b: f32) callconv(.AAPCS) f32 {
27 return div(a, b);
28}
29
30inline fn div(a: f32, b: f32) f32 {
1031 const Z = std.meta.Int(.unsigned, 32);
1132
1233 const significandBits = std.math.floatMantissaBits(f32);
......@@ -184,22 +205,6 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
184205 }
185206}
186207
187fn 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
198pub fn __aeabi_fdiv(a: f32, b: f32) callconv(.AAPCS) f32 {
199 @setRuntimeSafety(false);
200 return @call(.{ .modifier = .always_inline }, __divsf3, .{ a, b });
201}
202
203208test {
204209 _ = @import("divsf3_test.zig");
205210}
lib/compiler_rt/divtf3.zig+27-3
......@@ -1,11 +1,35 @@
11const std = @import("std");
22const builtin = @import("builtin");
33
4const normalize = @import("divdf3.zig").normalize;
5const wideMultiply = @import("divdf3.zig").wideMultiply;
4const common = @import("common.zig");
5const normalize = common.normalize;
6const wideMultiply = common.wideMultiply;
7
8pub const panic = common.panic;
9
10comptime {
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}
619
720pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 {
8 @setRuntimeSafety(builtin.is_test);
21 return div(a, b);
22}
23
24fn __divkf3(a: f128, b: f128) callconv(.C) f128 {
25 return div(a, b);
26}
27
28fn _Qp_div(c: *f128, a: *const f128, b: *const f128) callconv(.C) void {
29 c.* = div(a.*, b.*);
30}
31
32inline fn div(a: f128, b: f128) f128 {
933 const Z = std.meta.Int(.unsigned, 128);
1034
1135 const significandBits = std.math.floatMantissaBits(f128);
lib/compiler_rt/divti3.zig+36-10
......@@ -1,9 +1,43 @@
1const udivmod = @import("udivmod.zig").udivmod;
1const std = @import("std");
22const builtin = @import("builtin");
3const udivmod = @import("udivmod.zig").udivmod;
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
329
430pub fn __divti3(a: i128, b: i128) callconv(.C) i128 {
5 @setRuntimeSafety(builtin.is_test);
31 return div(a, b);
32}
633
34const v128 = @import("std").meta.Vector(2, u64);
35
36fn __divti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {
37 return @bitCast(v128, div(@bitCast(i128, a), @bitCast(i128, b)));
38}
39
40inline fn div(a: i128, b: i128) i128 {
741 const s_a = a >> (128 - 1);
842 const s_b = b >> (128 - 1);
943
......@@ -15,14 +49,6 @@ pub fn __divti3(a: i128, b: i128) callconv(.C) i128 {
1549 return (@bitCast(i128, r) ^ s) -% s;
1650}
1751
18const v128 = @import("std").meta.Vector(2, u64);
19pub 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
2652test {
2753 _ = @import("divti3_test.zig");
2854}
lib/compiler_rt/divxf3.zig+11-3
......@@ -1,10 +1,18 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const normalize = @import("divdf3.zig").normalize;
4const wideMultiply = @import("divdf3.zig").wideMultiply;
3const arch = builtin.cpu.arch;
4
5const common = @import("common.zig");
6const normalize = common.normalize;
7const wideMultiply = common.wideMultiply;
8
9pub const panic = common.panic;
10
11comptime {
12 @export(__divxf3, .{ .name = "__divxf3", .linkage = common.linkage });
13}
514
615pub fn __divxf3(a: f80, b: f80) callconv(.C) f80 {
7 @setRuntimeSafety(builtin.is_test);
816 const T = f80;
917 const Z = std.meta.Int(.unsigned, @bitSizeOf(T));
1018
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
65
76const std = @import("std");
87const builtin = @import("builtin");
8const common = @import("common.zig");
99
1010const abort = std.os.abort;
1111const assert = std.debug.assert;
1212const expect = std.testing.expect;
1313
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)));
1616const gcc_word = usize;
1717
18pub const panic = common.panic;
19
1820comptime {
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 }
2024}
2125
2226/// public entrypoint for generated code using EmulatedTLS
......@@ -319,6 +323,8 @@ const emutls_control = extern struct {
319323};
320324
321325test "simple_allocator" {
326 if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest;
327
322328 var data1: *[64]u8 = simple_allocator.alloc([64]u8);
323329 defer simple_allocator.free(data1);
324330 for (data1) |*c| {
......@@ -333,6 +339,8 @@ test "simple_allocator" {
333339}
334340
335341test "__emutls_get_address zeroed" {
342 if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest;
343
336344 var ctl = emutls_control.init(usize, null);
337345 try expect(ctl.object.index == 0);
338346
......@@ -352,6 +360,8 @@ test "__emutls_get_address zeroed" {
352360}
353361
354362test "__emutls_get_address with default_value" {
363 if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest;
364
355365 var value: usize = 5678; // default value
356366 var ctl = emutls_control.init(usize, &value);
357367 try expect(ctl.object.index == 0);
......@@ -370,6 +380,8 @@ test "__emutls_get_address with default_value" {
370380}
371381
372382test "test default_value with differents sizes" {
383 if (!builtin.link_libc or builtin.os.tag != .openbsd) return error.SkipZigTest;
384
373385 const testType = struct {
374386 fn _testType(comptime T: type, value: T) !void {
375387 var def: T = value;
lib/compiler_rt/exp.zig+15
......@@ -5,8 +5,23 @@
55// https://git.musl-libc.org/cgit/musl/tree/src/math/exp.c
66
77const std = @import("std");
8const builtin = @import("builtin");
9const arch = builtin.cpu.arch;
810const math = std.math;
911const expect = std.testing.expect;
12const common = @import("common.zig");
13
14pub const panic = common.panic;
15
16comptime {
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}
1025
1126pub fn __exph(a: f16) callconv(.C) f16 {
1227 // TODO: more efficient implementation
lib/compiler_rt/exp2.zig+15
......@@ -5,8 +5,23 @@
55// https://git.musl-libc.org/cgit/musl/tree/src/math/exp2.c
66
77const std = @import("std");
8const builtin = @import("builtin");
9const arch = builtin.cpu.arch;
810const math = std.math;
911const expect = std.testing.expect;
12const common = @import("common.zig");
13
14pub const panic = common.panic;
15
16comptime {
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}
1025
1126pub fn __exp2h(x: f16) callconv(.C) f16 {
1227 // TODO: more efficient implementation
lib/compiler_rt/extendXfYf2.zig deleted-112
......@@ -1,112 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const native_arch = builtin.cpu.arch;
5
6pub fn __extendsfdf2(a: f32) callconv(.C) f64 {
7 return extendXfYf2(f64, f32, @bitCast(u32, a));
8}
9
10pub fn __extenddftf2(a: f64) callconv(.C) f128 {
11 return extendXfYf2(f128, f64, @bitCast(u64, a));
12}
13
14pub 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.
20pub const F16T = if (native_arch.isAARCH64()) f16 else u16;
21
22pub fn __extendhfsf2(a: F16T) callconv(.C) f32 {
23 return extendXfYf2(f32, f16, @bitCast(u16, a));
24}
25
26pub fn __extendhftf2(a: F16T) callconv(.C) f128 {
27 return extendXfYf2(f128, f16, @bitCast(u16, a));
28}
29
30pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 {
31 @setRuntimeSafety(false);
32 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, arg });
33}
34
35pub 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
40inline 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
110test {
111 _ = @import("extendXfYf2_test.zig");
112}
lib/compiler_rt/extendXfYf2_test.zig deleted-206
......@@ -1,206 +0,0 @@
1const builtin = @import("builtin");
2const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;
3const __extendhftf2 = @import("extendXfYf2.zig").__extendhftf2;
4const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;
5const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
6const F16T = @import("extendXfYf2.zig").F16T;
7
8fn 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
30fn 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
46fn 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
68test "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
90test "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
123test "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
138fn makeQNaN64() f64 {
139 return @bitCast(f64, @as(u64, 0x7ff8000000000000));
140}
141
142fn makeInf64() f64 {
143 return @bitCast(f64, @as(u64, 0x7ff0000000000000));
144}
145
146fn makeNaN64(rand: u64) f64 {
147 return @bitCast(f64, 0x7ff0000000000000 | (rand & 0xfffffffffffff));
148}
149
150fn makeQNaN32() f32 {
151 return @bitCast(f32, @as(u32, 0x7fc00000));
152}
153
154fn makeNaN32(rand: u32) f32 {
155 return @bitCast(f32, 0x7f800000 | (rand & 0x7fffff));
156}
157
158fn makeInf32() f32 {
159 return @bitCast(f32, @as(u32, 0x7f800000));
160}
161
162fn 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
184test "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 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const 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.
8pub const F16T = if (native_arch.isAARCH64()) f16 else u16;
9
10pub fn __extendhfxf2(a: F16T) callconv(.C) f80 {
11 return extendF80(f16, @bitCast(u16, a));
12}
13
14pub fn __extendsfxf2(a: f32) callconv(.C) f80 {
15 return extendF80(f32, @bitCast(u32, a));
16}
17
18pub fn __extenddfxf2(a: f64) callconv(.C) f80 {
19 return extendF80(f64, @bitCast(u64, a));
20}
21
22inline 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
89pub 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 @@
1const common = @import("./common.zig");
2const extendf = @import("./extendf.zig").extendf;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __extenddftf2(a: f64) callconv(.C) f128 {
17 return extendf(f128, f64, @bitCast(u64, a));
18}
19
20fn __extenddfkf2(a: f64) callconv(.C) f128 {
21 return extendf(f128, f64, @bitCast(u64, a));
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const extend_f80 = @import("./extendf.zig").extend_f80;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__extenddfxf2, .{ .name = "__extenddfxf2", .linkage = common.linkage });
8}
9
10fn __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 @@
1const std = @import("std");
2
3pub 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
75pub 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
140test {
141 _ = @import("extendf_test.zig");
142}
lib/compiler_rt/extendf_test.zig created+206
......@@ -0,0 +1,206 @@
1const builtin = @import("builtin");
2const __extendhfsf2 = @import("extendhfsf2.zig").__extendhfsf2;
3const __extendhftf2 = @import("extendhftf2.zig").__extendhftf2;
4const __extendsftf2 = @import("extendsftf2.zig").__extendsftf2;
5const __extenddftf2 = @import("extenddftf2.zig").__extenddftf2;
6const F16T = @import("./common.zig").F16T;
7
8fn 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
30fn 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
46fn 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
68test "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
90test "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
123test "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
138fn makeQNaN64() f64 {
139 return @bitCast(f64, @as(u64, 0x7ff8000000000000));
140}
141
142fn makeInf64() f64 {
143 return @bitCast(f64, @as(u64, 0x7ff0000000000000));
144}
145
146fn makeNaN64(rand: u64) f64 {
147 return @bitCast(f64, 0x7ff0000000000000 | (rand & 0xfffffffffffff));
148}
149
150fn makeQNaN32() f32 {
151 return @bitCast(f32, @as(u32, 0x7fc00000));
152}
153
154fn makeNaN32(rand: u32) f32 {
155 return @bitCast(f32, 0x7f800000 | (rand & 0x7fffff));
156}
157
158fn makeInf32() f32 {
159 return @bitCast(f32, @as(u32, 0x7f800000));
160}
161
162fn 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
184test "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 @@
1const common = @import("./common.zig");
2const extendf = @import("./extendf.zig").extendf;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __extendhfsf2(a: common.F16T) callconv(.C) f32 {
17 return extendf(f32, f16, @bitCast(u16, a));
18}
19
20fn __gnu_h2f_ieee(a: common.F16T) callconv(.C) f32 {
21 return extendf(f32, f16, @bitCast(u16, a));
22}
23
24fn __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 @@
1const common = @import("./common.zig");
2const extendf = @import("./extendf.zig").extendf;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__extendhftf2, .{ .name = "__extendhftf2", .linkage = common.linkage });
8}
9
10pub 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 @@
1const common = @import("./common.zig");
2const extend_f80 = @import("./extendf.zig").extend_f80;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__extendhfxf2, .{ .name = "__extendhfxf2", .linkage = common.linkage });
8}
9
10fn __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 @@
1const common = @import("./common.zig");
2const extendf = @import("./extendf.zig").extendf;
3
4pub const panic = common.panic;
5
6comptime {
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
14fn __extendsfdf2(a: f32) callconv(.C) f64 {
15 return extendf(f64, f32, @bitCast(u32, a));
16}
17
18fn __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 @@
1const common = @import("./common.zig");
2const extendf = @import("./extendf.zig").extendf;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __extendsftf2(a: f32) callconv(.C) f128 {
17 return extendf(f128, f32, @bitCast(u32, a));
18}
19
20fn __extendsfkf2(a: f32) callconv(.C) f128 {
21 return extendf(f128, f32, @bitCast(u32, a));
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const extend_f80 = @import("./extendf.zig").extend_f80;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__extendsfxf2, .{ .name = "__extendsfxf2", .linkage = common.linkage });
8}
9
10fn __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 @@
1const std = @import("std");
2const common = @import("./common.zig");
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__extendxftf2, .{ .name = "__extendxftf2", .linkage = common.linkage });
8}
9
10fn __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 @@
11const std = @import("std");
2const builtin = @import("builtin");
3const arch = builtin.cpu.arch;
4const common = @import("common.zig");
5
6pub const panic = common.panic;
7
8comptime {
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}
217
318pub fn __fabsh(a: f16) callconv(.C) f16 {
419 return generic_fabs(a);
lib/compiler_rt/fixXfYi.zig deleted-224
......@@ -1,224 +0,0 @@
1const std = @import("std");
2const math = std.math;
3const Log2Int = math.Log2Int;
4const is_test = @import("builtin").is_test;
5
6pub 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
58pub fn __fixhfsi(a: f16) callconv(.C) i32 {
59 return fixXfYi(i32, a);
60}
61
62pub fn __fixunshfsi(a: f16) callconv(.C) u32 {
63 return fixXfYi(u32, a);
64}
65
66pub fn __fixhfdi(a: f16) callconv(.C) i64 {
67 return fixXfYi(i64, a);
68}
69
70pub fn __fixunshfdi(a: f16) callconv(.C) u64 {
71 return fixXfYi(u64, a);
72}
73
74pub fn __fixhfti(a: f16) callconv(.C) i128 {
75 return fixXfYi(i128, a);
76}
77
78pub fn __fixunshfti(a: f16) callconv(.C) u128 {
79 return fixXfYi(u128, a);
80}
81
82// Conversion from f32
83
84pub fn __fixsfsi(a: f32) callconv(.C) i32 {
85 return fixXfYi(i32, a);
86}
87
88pub fn __fixunssfsi(a: f32) callconv(.C) u32 {
89 return fixXfYi(u32, a);
90}
91
92pub fn __fixsfdi(a: f32) callconv(.C) i64 {
93 return fixXfYi(i64, a);
94}
95
96pub fn __fixunssfdi(a: f32) callconv(.C) u64 {
97 return fixXfYi(u64, a);
98}
99
100pub fn __fixsfti(a: f32) callconv(.C) i128 {
101 return fixXfYi(i128, a);
102}
103
104pub fn __fixunssfti(a: f32) callconv(.C) u128 {
105 return fixXfYi(u128, a);
106}
107
108// Conversion from f64
109
110pub fn __fixdfsi(a: f64) callconv(.C) i32 {
111 return fixXfYi(i32, a);
112}
113
114pub fn __fixunsdfsi(a: f64) callconv(.C) u32 {
115 return fixXfYi(u32, a);
116}
117
118pub fn __fixdfdi(a: f64) callconv(.C) i64 {
119 return fixXfYi(i64, a);
120}
121
122pub fn __fixunsdfdi(a: f64) callconv(.C) u64 {
123 return fixXfYi(u64, a);
124}
125
126pub fn __fixdfti(a: f64) callconv(.C) i128 {
127 return fixXfYi(i128, a);
128}
129
130pub fn __fixunsdfti(a: f64) callconv(.C) u128 {
131 return fixXfYi(u128, a);
132}
133
134// Conversion from f80
135
136pub fn __fixxfsi(a: f80) callconv(.C) i32 {
137 return fixXfYi(i32, a);
138}
139
140pub fn __fixunsxfsi(a: f80) callconv(.C) u32 {
141 return fixXfYi(u32, a);
142}
143
144pub fn __fixxfdi(a: f80) callconv(.C) i64 {
145 return fixXfYi(i64, a);
146}
147
148pub fn __fixunsxfdi(a: f80) callconv(.C) u64 {
149 return fixXfYi(u64, a);
150}
151
152pub fn __fixxfti(a: f80) callconv(.C) i128 {
153 return fixXfYi(i128, a);
154}
155
156pub fn __fixunsxfti(a: f80) callconv(.C) u128 {
157 return fixXfYi(u128, a);
158}
159
160// Conversion from f128
161
162pub fn __fixtfsi(a: f128) callconv(.C) i32 {
163 return fixXfYi(i32, a);
164}
165
166pub fn __fixunstfsi(a: f128) callconv(.C) u32 {
167 return fixXfYi(u32, a);
168}
169
170pub fn __fixtfdi(a: f128) callconv(.C) i64 {
171 return fixXfYi(i64, a);
172}
173
174pub fn __fixunstfdi(a: f128) callconv(.C) u64 {
175 return fixXfYi(u64, a);
176}
177
178pub fn __fixtfti(a: f128) callconv(.C) i128 {
179 return fixXfYi(i128, a);
180}
181
182pub fn __fixunstfti(a: f128) callconv(.C) u128 {
183 return fixXfYi(u128, a);
184}
185
186// Conversion from f32
187
188pub fn __aeabi_f2iz(a: f32) callconv(.AAPCS) i32 {
189 return fixXfYi(i32, a);
190}
191
192pub fn __aeabi_f2uiz(a: f32) callconv(.AAPCS) u32 {
193 return fixXfYi(u32, a);
194}
195
196pub fn __aeabi_f2lz(a: f32) callconv(.AAPCS) i64 {
197 return fixXfYi(i64, a);
198}
199
200pub fn __aeabi_f2ulz(a: f32) callconv(.AAPCS) u64 {
201 return fixXfYi(u64, a);
202}
203
204// Conversion from f64
205
206pub fn __aeabi_d2iz(a: f64) callconv(.AAPCS) i32 {
207 return fixXfYi(i32, a);
208}
209
210pub fn __aeabi_d2uiz(a: f64) callconv(.AAPCS) u32 {
211 return fixXfYi(u32, a);
212}
213
214pub fn __aeabi_d2lz(a: f64) callconv(.AAPCS) i64 {
215 return fixXfYi(i64, a);
216}
217
218pub fn __aeabi_d2ulz(a: f64) callconv(.AAPCS) u64 {
219 return fixXfYi(u64, a);
220}
221
222test {
223 _ = @import("fixXfYi_test.zig");
224}
lib/compiler_rt/fixXfYi_test.zig deleted-948
......@@ -1,948 +0,0 @@
1const std = @import("std");
2const testing = std.testing;
3const math = std.math;
4const fixXfYi = @import("fixXfYi.zig").fixXfYi;
5
6// Conversion from f32
7const __fixsfsi = @import("fixXfYi.zig").__fixsfsi;
8const __fixunssfsi = @import("fixXfYi.zig").__fixunssfsi;
9const __fixsfdi = @import("fixXfYi.zig").__fixsfdi;
10const __fixunssfdi = @import("fixXfYi.zig").__fixunssfdi;
11const __fixsfti = @import("fixXfYi.zig").__fixsfti;
12const __fixunssfti = @import("fixXfYi.zig").__fixunssfti;
13
14// Conversion from f64
15const __fixdfsi = @import("fixXfYi.zig").__fixdfsi;
16const __fixunsdfsi = @import("fixXfYi.zig").__fixunsdfsi;
17const __fixdfdi = @import("fixXfYi.zig").__fixdfdi;
18const __fixunsdfdi = @import("fixXfYi.zig").__fixunsdfdi;
19const __fixdfti = @import("fixXfYi.zig").__fixdfti;
20const __fixunsdfti = @import("fixXfYi.zig").__fixunsdfti;
21
22// Conversion from f128
23const __fixtfsi = @import("fixXfYi.zig").__fixtfsi;
24const __fixunstfsi = @import("fixXfYi.zig").__fixunstfsi;
25const __fixtfdi = @import("fixXfYi.zig").__fixtfdi;
26const __fixunstfdi = @import("fixXfYi.zig").__fixunstfdi;
27const __fixtfti = @import("fixXfYi.zig").__fixtfti;
28const __fixunstfti = @import("fixXfYi.zig").__fixunstfti;
29
30fn test__fixsfsi(a: f32, expected: i32) !void {
31 const x = __fixsfsi(a);
32 try testing.expect(x == expected);
33}
34
35fn test__fixunssfsi(a: f32, expected: u32) !void {
36 const x = __fixunssfsi(a);
37 try testing.expect(x == expected);
38}
39
40test "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
103test "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
132fn test__fixsfdi(a: f32, expected: i64) !void {
133 const x = __fixsfdi(a);
134 try testing.expect(x == expected);
135}
136
137fn test__fixunssfdi(a: f32, expected: u64) !void {
138 const x = __fixunssfdi(a);
139 try testing.expect(x == expected);
140}
141
142test "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
197test "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
225fn test__fixsfti(a: f32, expected: i128) !void {
226 const x = __fixsfti(a);
227 try testing.expect(x == expected);
228}
229
230fn test__fixunssfti(a: f32, expected: u128) !void {
231 const x = __fixunssfti(a);
232 try testing.expect(x == expected);
233}
234
235test "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
306test "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
342fn test__fixdfsi(a: f64, expected: i32) !void {
343 const x = __fixdfsi(a);
344 try testing.expect(x == expected);
345}
346
347fn test__fixunsdfsi(a: f64, expected: u32) !void {
348 const x = __fixunsdfsi(a);
349 try testing.expect(x == expected);
350}
351
352test "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
413test "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
445fn test__fixdfdi(a: f64, expected: i64) !void {
446 const x = __fixdfdi(a);
447 try testing.expect(x == expected);
448}
449
450fn test__fixunsdfdi(a: f64, expected: u64) !void {
451 const x = __fixunsdfdi(a);
452 try testing.expect(x == expected);
453}
454
455test "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
508test "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
540fn test__fixdfti(a: f64, expected: i128) !void {
541 const x = __fixdfti(a);
542 try testing.expect(x == expected);
543}
544
545fn test__fixunsdfti(a: f64, expected: u128) !void {
546 const x = __fixunsdfti(a);
547 try testing.expect(x == expected);
548}
549
550test "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
603test "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
642fn test__fixtfsi(a: f128, expected: i32) !void {
643 const x = __fixtfsi(a);
644 try testing.expect(x == expected);
645}
646
647fn test__fixunstfsi(a: f128, expected: u32) !void {
648 const x = __fixunstfsi(a);
649 try testing.expect(x == expected);
650}
651
652test "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
715test "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
728fn test__fixtfdi(a: f128, expected: i64) !void {
729 const x = __fixtfdi(a);
730 try testing.expect(x == expected);
731}
732
733fn test__fixunstfdi(a: f128, expected: u64) !void {
734 const x = __fixunstfdi(a);
735 try testing.expect(x == expected);
736}
737
738test "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
801test "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
843fn test__fixtfti(a: f128, expected: i128) !void {
844 const x = __fixtfti(a);
845 try testing.expect(x == expected);
846}
847
848fn test__fixunstfti(a: f128, expected: u128) !void {
849 const x = __fixunstfti(a);
850 try testing.expect(x == expected);
851}
852
853test "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
906test "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
929fn test__fixunshfti(a: f16, expected: u128) !void {
930 const x = fixXfYi(u128, a);
931 try testing.expect(x == expected);
932}
933
934test "fixXfYi for f16" {
935 try test__fixunshfti(math.inf(f16), math.maxInt(u128));
936 try test__fixunshfti(math.floatMax(f16), 65504);
937}
938
939fn test__fixunsxfti(a: f80, expected: u128) !void {
940 const x = fixXfYi(u128, a);
941 try testing.expect(x == expected);
942}
943
944test "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 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __fixdfdi(a: f64) callconv(.C) i64 {
15 return floatToInt(i64, a);
16}
17
18fn __aeabi_d2lz(a: f64) callconv(.AAPCS) i64 {
19 return floatToInt(i64, a);
20}
lib/compiler_rt/fixdfsi.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __fixdfsi(a: f64) callconv(.C) i32 {
15 return floatToInt(i32, a);
16}
17
18fn __aeabi_d2iz(a: f64) callconv(.AAPCS) i32 {
19 return floatToInt(i32, a);
20}
lib/compiler_rt/fixdfti.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixdfti, .{ .name = "__fixdfti", .linkage = common.linkage });
8}
9
10pub fn __fixdfti(a: f64) callconv(.C) i128 {
11 return floatToInt(i128, a);
12}
lib/compiler_rt/fixhfdi.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixhfdi, .{ .name = "__fixhfdi", .linkage = common.linkage });
8}
9
10fn __fixhfdi(a: f16) callconv(.C) i64 {
11 return floatToInt(i64, a);
12}
lib/compiler_rt/fixhfsi.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixhfsi, .{ .name = "__fixhfsi", .linkage = common.linkage });
8}
9
10fn __fixhfsi(a: f16) callconv(.C) i32 {
11 return floatToInt(i32, a);
12}
lib/compiler_rt/fixhfti.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixhfti, .{ .name = "__fixhfti", .linkage = common.linkage });
8}
9
10fn __fixhfti(a: f16) callconv(.C) i128 {
11 return floatToInt(i128, a);
12}
lib/compiler_rt/fixsfdi.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __fixsfdi(a: f32) callconv(.C) i64 {
15 return floatToInt(i64, a);
16}
17
18fn __aeabi_f2lz(a: f32) callconv(.AAPCS) i64 {
19 return floatToInt(i64, a);
20}
lib/compiler_rt/fixsfsi.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __fixsfsi(a: f32) callconv(.C) i32 {
15 return floatToInt(i32, a);
16}
17
18fn __aeabi_f2iz(a: f32) callconv(.AAPCS) i32 {
19 return floatToInt(i32, a);
20}
lib/compiler_rt/fixsfti.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixsfti, .{ .name = "__fixsfti", .linkage = common.linkage });
8}
9
10pub fn __fixsfti(a: f32) callconv(.C) i128 {
11 return floatToInt(i128, a);
12}
lib/compiler_rt/fixtfdi.zig created+26
......@@ -0,0 +1,26 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __fixtfdi(a: f128) callconv(.C) i64 {
17 return floatToInt(i64, a);
18}
19
20fn __fixkfdi(a: f128) callconv(.C) i64 {
21 return floatToInt(i64, a);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __fixtfsi(a: f128) callconv(.C) i32 {
17 return floatToInt(i32, a);
18}
19
20fn __fixkfsi(a: f128) callconv(.C) i32 {
21 return floatToInt(i32, a);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixtfti, .{ .name = "__fixtfti", .linkage = common.linkage });
8}
9
10pub fn __fixtfti(a: f128) callconv(.C) i128 {
11 return floatToInt(i128, a);
12}
lib/compiler_rt/fixunsdfdi.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __fixunsdfdi(a: f64) callconv(.C) u64 {
15 return floatToInt(u64, a);
16}
17
18fn __aeabi_d2ulz(a: f64) callconv(.AAPCS) u64 {
19 return floatToInt(u64, a);
20}
lib/compiler_rt/fixunsdfsi.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __fixunsdfsi(a: f64) callconv(.C) u32 {
15 return floatToInt(u32, a);
16}
17
18fn __aeabi_d2uiz(a: f64) callconv(.AAPCS) u32 {
19 return floatToInt(u32, a);
20}
lib/compiler_rt/fixunsdfti.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = common.linkage });
8}
9
10pub fn __fixunsdfti(a: f64) callconv(.C) u128 {
11 return floatToInt(u128, a);
12}
lib/compiler_rt/fixunshfdi.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixunshfdi, .{ .name = "__fixunshfdi", .linkage = common.linkage });
8}
9
10fn __fixunshfdi(a: f16) callconv(.C) u64 {
11 return floatToInt(u64, a);
12}
lib/compiler_rt/fixunshfsi.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixunshfsi, .{ .name = "__fixunshfsi", .linkage = common.linkage });
8}
9
10fn __fixunshfsi(a: f16) callconv(.C) u32 {
11 return floatToInt(u32, a);
12}
lib/compiler_rt/fixunshfti.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixunshfti, .{ .name = "__fixunshfti", .linkage = common.linkage });
8}
9
10pub fn __fixunshfti(a: f16) callconv(.C) u128 {
11 return floatToInt(u128, a);
12}
lib/compiler_rt/fixunssfdi.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __fixunssfdi(a: f32) callconv(.C) u64 {
15 return floatToInt(u64, a);
16}
17
18fn __aeabi_f2ulz(a: f32) callconv(.AAPCS) u64 {
19 return floatToInt(u64, a);
20}
lib/compiler_rt/fixunssfsi.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __fixunssfsi(a: f32) callconv(.C) u32 {
15 return floatToInt(u32, a);
16}
17
18fn __aeabi_f2uiz(a: f32) callconv(.AAPCS) u32 {
19 return floatToInt(u32, a);
20}
lib/compiler_rt/fixunssfti.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = common.linkage });
8}
9
10pub fn __fixunssfti(a: f32) callconv(.C) u128 {
11 return floatToInt(u128, a);
12}
lib/compiler_rt/fixunstfdi.zig created+26
......@@ -0,0 +1,26 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __fixunstfdi(a: f128) callconv(.C) u64 {
17 return floatToInt(u64, a);
18}
19
20fn __fixunskfdi(a: f128) callconv(.C) u64 {
21 return floatToInt(u64, a);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __fixunstfsi(a: f128) callconv(.C) u32 {
17 return floatToInt(u32, a);
18}
19
20fn __fixunskfsi(a: f128) callconv(.C) u32 {
21 return floatToInt(u32, a);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = common.linkage });
8}
9
10pub fn __fixunstfti(a: f128) callconv(.C) u128 {
11 return floatToInt(u128, a);
12}
lib/compiler_rt/fixunsxfdi.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixunsxfdi, .{ .name = "__fixunsxfdi", .linkage = common.linkage });
8}
9
10fn __fixunsxfdi(a: f80) callconv(.C) u64 {
11 return floatToInt(u64, a);
12}
lib/compiler_rt/fixunsxfsi.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixunsxfsi, .{ .name = "__fixunsxfsi", .linkage = common.linkage });
8}
9
10fn __fixunsxfsi(a: f80) callconv(.C) u32 {
11 return floatToInt(u32, a);
12}
lib/compiler_rt/fixunsxfti.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixunsxfti, .{ .name = "__fixunsxfti", .linkage = common.linkage });
8}
9
10pub fn __fixunsxfti(a: f80) callconv(.C) u128 {
11 return floatToInt(u128, a);
12}
lib/compiler_rt/fixxfdi.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixxfdi, .{ .name = "__fixxfdi", .linkage = common.linkage });
8}
9
10fn __fixxfdi(a: f80) callconv(.C) i64 {
11 return floatToInt(i64, a);
12}
lib/compiler_rt/fixxfsi.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixxfsi, .{ .name = "__fixxfsi", .linkage = common.linkage });
8}
9
10fn __fixxfsi(a: f80) callconv(.C) i32 {
11 return floatToInt(i32, a);
12}
lib/compiler_rt/fixxfti.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const floatToInt = @import("./float_to_int.zig").floatToInt;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__fixxfti, .{ .name = "__fixxfti", .linkage = common.linkage });
8}
9
10fn __fixxfti(a: f80) callconv(.C) i128 {
11 return floatToInt(i128, a);
12}
lib/compiler_rt/floatXiYf.zig deleted-222
......@@ -1,222 +0,0 @@
1const builtin = @import("builtin");
2const is_test = builtin.is_test;
3const std = @import("std");
4const math = std.math;
5const expect = std.testing.expect;
6
7pub 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
62pub fn __floatsihf(a: i32) callconv(.C) f16 {
63 return floatXiYf(f16, a);
64}
65
66pub fn __floatunsihf(a: u32) callconv(.C) f16 {
67 return floatXiYf(f16, a);
68}
69
70pub fn __floatdihf(a: i64) callconv(.C) f16 {
71 return floatXiYf(f16, a);
72}
73
74pub fn __floatundihf(a: u64) callconv(.C) f16 {
75 return floatXiYf(f16, a);
76}
77
78pub fn __floattihf(a: i128) callconv(.C) f16 {
79 return floatXiYf(f16, a);
80}
81
82pub fn __floatuntihf(a: u128) callconv(.C) f16 {
83 return floatXiYf(f16, a);
84}
85
86// Conversion to f32
87pub fn __floatsisf(a: i32) callconv(.C) f32 {
88 return floatXiYf(f32, a);
89}
90
91pub fn __floatunsisf(a: u32) callconv(.C) f32 {
92 return floatXiYf(f32, a);
93}
94
95pub fn __floatdisf(a: i64) callconv(.C) f32 {
96 return floatXiYf(f32, a);
97}
98
99pub fn __floatundisf(a: u64) callconv(.C) f32 {
100 return floatXiYf(f32, a);
101}
102
103pub fn __floattisf(a: i128) callconv(.C) f32 {
104 return floatXiYf(f32, a);
105}
106
107pub fn __floatuntisf(a: u128) callconv(.C) f32 {
108 return floatXiYf(f32, a);
109}
110
111// Conversion to f64
112pub fn __floatsidf(a: i32) callconv(.C) f64 {
113 return floatXiYf(f64, a);
114}
115
116pub fn __floatunsidf(a: u32) callconv(.C) f64 {
117 return floatXiYf(f64, a);
118}
119
120pub fn __floatdidf(a: i64) callconv(.C) f64 {
121 return floatXiYf(f64, a);
122}
123
124pub fn __floatundidf(a: u64) callconv(.C) f64 {
125 return floatXiYf(f64, a);
126}
127
128pub fn __floattidf(a: i128) callconv(.C) f64 {
129 return floatXiYf(f64, a);
130}
131
132pub fn __floatuntidf(a: u128) callconv(.C) f64 {
133 return floatXiYf(f64, a);
134}
135
136// Conversion to f80
137pub fn __floatsixf(a: i32) callconv(.C) f80 {
138 return floatXiYf(f80, a);
139}
140
141pub fn __floatunsixf(a: u32) callconv(.C) f80 {
142 return floatXiYf(f80, a);
143}
144
145pub fn __floatdixf(a: i64) callconv(.C) f80 {
146 return floatXiYf(f80, a);
147}
148
149pub fn __floatundixf(a: u64) callconv(.C) f80 {
150 return floatXiYf(f80, a);
151}
152
153pub fn __floattixf(a: i128) callconv(.C) f80 {
154 return floatXiYf(f80, a);
155}
156
157pub fn __floatuntixf(a: u128) callconv(.C) f80 {
158 return floatXiYf(f80, a);
159}
160
161// Conversion to f128
162pub fn __floatsitf(a: i32) callconv(.C) f128 {
163 return floatXiYf(f128, a);
164}
165
166pub fn __floatunsitf(a: u32) callconv(.C) f128 {
167 return floatXiYf(f128, a);
168}
169
170pub fn __floatditf(a: i64) callconv(.C) f128 {
171 return floatXiYf(f128, a);
172}
173
174pub fn __floatunditf(a: u64) callconv(.C) f128 {
175 return floatXiYf(f128, a);
176}
177
178pub fn __floattitf(a: i128) callconv(.C) f128 {
179 return floatXiYf(f128, a);
180}
181
182pub fn __floatuntitf(a: u128) callconv(.C) f128 {
183 return floatXiYf(f128, a);
184}
185
186// Conversion to f32
187pub fn __aeabi_ui2f(arg: u32) callconv(.AAPCS) f32 {
188 return floatXiYf(f32, arg);
189}
190
191pub fn __aeabi_i2f(arg: i32) callconv(.AAPCS) f32 {
192 return floatXiYf(f32, arg);
193}
194
195pub fn __aeabi_ul2f(arg: u64) callconv(.AAPCS) f32 {
196 return floatXiYf(f32, arg);
197}
198
199pub fn __aeabi_l2f(arg: i64) callconv(.AAPCS) f32 {
200 return floatXiYf(f32, arg);
201}
202
203// Conversion to f64
204pub fn __aeabi_ui2d(arg: u32) callconv(.AAPCS) f64 {
205 return floatXiYf(f64, arg);
206}
207
208pub fn __aeabi_i2d(arg: i32) callconv(.AAPCS) f64 {
209 return floatXiYf(f64, arg);
210}
211
212pub fn __aeabi_ul2d(arg: u64) callconv(.AAPCS) f64 {
213 return floatXiYf(f64, arg);
214}
215
216pub fn __aeabi_l2d(arg: i64) callconv(.AAPCS) f64 {
217 return floatXiYf(f64, arg);
218}
219
220test {
221 _ = @import("floatXiYf_test.zig");
222}
lib/compiler_rt/floatXiYf_test.zig deleted-835
......@@ -1,835 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const testing = std.testing;
4const math = std.math;
5const floatXiYf = @import("floatXiYf.zig").floatXiYf;
6
7// Conversion to f32
8const __floatsisf = @import("floatXiYf.zig").__floatsisf;
9const __floatunsisf = @import("floatXiYf.zig").__floatunsisf;
10const __floatdisf = @import("floatXiYf.zig").__floatdisf;
11const __floatundisf = @import("floatXiYf.zig").__floatundisf;
12const __floattisf = @import("floatXiYf.zig").__floattisf;
13const __floatuntisf = @import("floatXiYf.zig").__floatuntisf;
14
15// Conversion to f64
16const __floatsidf = @import("floatXiYf.zig").__floatsidf;
17const __floatunsidf = @import("floatXiYf.zig").__floatunsidf;
18const __floatdidf = @import("floatXiYf.zig").__floatdidf;
19const __floatundidf = @import("floatXiYf.zig").__floatundidf;
20const __floattidf = @import("floatXiYf.zig").__floattidf;
21const __floatuntidf = @import("floatXiYf.zig").__floatuntidf;
22
23// Conversion to f128
24const __floatsitf = @import("floatXiYf.zig").__floatsitf;
25const __floatunsitf = @import("floatXiYf.zig").__floatunsitf;
26const __floatditf = @import("floatXiYf.zig").__floatditf;
27const __floatunditf = @import("floatXiYf.zig").__floatunditf;
28const __floattitf = @import("floatXiYf.zig").__floattitf;
29const __floatuntitf = @import("floatXiYf.zig").__floatuntitf;
30
31fn test__floatsisf(a: i32, expected: u32) !void {
32 const r = __floatsisf(a);
33 try std.testing.expect(@bitCast(u32, r) == expected);
34}
35
36fn test_one_floatunsisf(a: u32, expected: u32) !void {
37 const r = __floatunsisf(a);
38 try std.testing.expect(@bitCast(u32, r) == expected);
39}
40
41test "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
49test "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
58fn test__floatdisf(a: i64, expected: f32) !void {
59 const x = __floatdisf(a);
60 try testing.expect(x == expected);
61}
62
63fn test__floatundisf(a: u64, expected: f32) !void {
64 try std.testing.expectEqual(expected, __floatundisf(a));
65}
66
67test "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
92test "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
117fn test__floattisf(a: i128, expected: f32) !void {
118 const x = __floattisf(a);
119 try testing.expect(x == expected);
120}
121
122fn test__floatuntisf(a: u128, expected: f32) !void {
123 const x = __floatuntisf(a);
124 try testing.expect(x == expected);
125}
126
127test "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
173test "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
234fn test_one_floatsidf(a: i32, expected: u64) !void {
235 const r = __floatsidf(a);
236 try std.testing.expect(@bitCast(u64, r) == expected);
237}
238
239fn test_one_floatunsidf(a: u32, expected: u64) !void {
240 const r = __floatunsidf(a);
241 try std.testing.expect(@bitCast(u64, r) == expected);
242}
243
244test "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
252test "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
260fn test__floatdidf(a: i64, expected: f64) !void {
261 const r = __floatdidf(a);
262 try testing.expect(r == expected);
263}
264
265fn test__floatundidf(a: u64, expected: f64) !void {
266 const r = __floatundidf(a);
267 try testing.expect(r == expected);
268}
269
270test "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
316test "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
359fn test__floattidf(a: i128, expected: f64) !void {
360 const x = __floattidf(a);
361 try testing.expect(x == expected);
362}
363
364fn test__floatuntidf(a: u128, expected: f64) !void {
365 const x = __floatuntidf(a);
366 try testing.expect(x == expected);
367}
368
369test "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
439test "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
506fn test__floatsitf(a: i32, expected: u128) !void {
507 const r = __floatsitf(a);
508 try std.testing.expect(@bitCast(u128, r) == expected);
509}
510
511test "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
520fn 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
540test "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
547fn test__floatditf(a: i64, expected: f128) !void {
548 const x = __floatditf(a);
549 try testing.expect(x == expected);
550}
551
552fn 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
572test "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
584test "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
595fn test__floattitf(a: i128, expected: f128) !void {
596 const x = __floattitf(a);
597 try testing.expect(x == expected);
598}
599
600fn test__floatuntitf(a: u128, expected: f128) !void {
601 const x = __floatuntitf(a);
602 try testing.expect(x == expected);
603}
604
605test "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
687test "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
772fn 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
779fn make_uti(high: u64, low: u64) u128 {
780 var result: u128 = high;
781 result <<= 64;
782 result |= low;
783 return result;
784}
785
786fn 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
793test "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
800test "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
812test "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 @@
1const Int = @import("std").meta.Int;
2const math = @import("std").math;
3const Log2Int = math.Log2Int;
4
5pub 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
53test {
54 _ = @import("float_to_int_test.zig");
55}
lib/compiler_rt/float_to_int_test.zig created+950
......@@ -0,0 +1,950 @@
1const std = @import("std");
2const testing = std.testing;
3const math = std.math;
4
5const __fixunshfti = @import("fixunshfti.zig").__fixunshfti;
6const __fixunsxfti = @import("fixunsxfti.zig").__fixunsxfti;
7
8// Conversion from f32
9const __fixsfsi = @import("fixsfsi.zig").__fixsfsi;
10const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi;
11const __fixsfdi = @import("fixsfdi.zig").__fixsfdi;
12const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi;
13const __fixsfti = @import("fixsfti.zig").__fixsfti;
14const __fixunssfti = @import("fixunssfti.zig").__fixunssfti;
15
16// Conversion from f64
17const __fixdfsi = @import("fixdfsi.zig").__fixdfsi;
18const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi;
19const __fixdfdi = @import("fixdfdi.zig").__fixdfdi;
20const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi;
21const __fixdfti = @import("fixdfti.zig").__fixdfti;
22const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti;
23
24// Conversion from f128
25const __fixtfsi = @import("fixtfsi.zig").__fixtfsi;
26const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi;
27const __fixtfdi = @import("fixtfdi.zig").__fixtfdi;
28const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi;
29const __fixtfti = @import("fixtfti.zig").__fixtfti;
30const __fixunstfti = @import("fixunstfti.zig").__fixunstfti;
31
32fn test__fixsfsi(a: f32, expected: i32) !void {
33 const x = __fixsfsi(a);
34 try testing.expect(x == expected);
35}
36
37fn test__fixunssfsi(a: f32, expected: u32) !void {
38 const x = __fixunssfsi(a);
39 try testing.expect(x == expected);
40}
41
42test "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
105test "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
134fn test__fixsfdi(a: f32, expected: i64) !void {
135 const x = __fixsfdi(a);
136 try testing.expect(x == expected);
137}
138
139fn test__fixunssfdi(a: f32, expected: u64) !void {
140 const x = __fixunssfdi(a);
141 try testing.expect(x == expected);
142}
143
144test "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
199test "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
227fn test__fixsfti(a: f32, expected: i128) !void {
228 const x = __fixsfti(a);
229 try testing.expect(x == expected);
230}
231
232fn test__fixunssfti(a: f32, expected: u128) !void {
233 const x = __fixunssfti(a);
234 try testing.expect(x == expected);
235}
236
237test "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
308test "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
344fn test__fixdfsi(a: f64, expected: i32) !void {
345 const x = __fixdfsi(a);
346 try testing.expect(x == expected);
347}
348
349fn test__fixunsdfsi(a: f64, expected: u32) !void {
350 const x = __fixunsdfsi(a);
351 try testing.expect(x == expected);
352}
353
354test "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
415test "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
447fn test__fixdfdi(a: f64, expected: i64) !void {
448 const x = __fixdfdi(a);
449 try testing.expect(x == expected);
450}
451
452fn test__fixunsdfdi(a: f64, expected: u64) !void {
453 const x = __fixunsdfdi(a);
454 try testing.expect(x == expected);
455}
456
457test "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
510test "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
542fn test__fixdfti(a: f64, expected: i128) !void {
543 const x = __fixdfti(a);
544 try testing.expect(x == expected);
545}
546
547fn test__fixunsdfti(a: f64, expected: u128) !void {
548 const x = __fixunsdfti(a);
549 try testing.expect(x == expected);
550}
551
552test "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
605test "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
644fn test__fixtfsi(a: f128, expected: i32) !void {
645 const x = __fixtfsi(a);
646 try testing.expect(x == expected);
647}
648
649fn test__fixunstfsi(a: f128, expected: u32) !void {
650 const x = __fixunstfsi(a);
651 try testing.expect(x == expected);
652}
653
654test "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
717test "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
730fn test__fixtfdi(a: f128, expected: i64) !void {
731 const x = __fixtfdi(a);
732 try testing.expect(x == expected);
733}
734
735fn test__fixunstfdi(a: f128, expected: u64) !void {
736 const x = __fixunstfdi(a);
737 try testing.expect(x == expected);
738}
739
740test "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
803test "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
845fn test__fixtfti(a: f128, expected: i128) !void {
846 const x = __fixtfti(a);
847 try testing.expect(x == expected);
848}
849
850fn test__fixunstfti(a: f128, expected: u128) !void {
851 const x = __fixunstfti(a);
852 try testing.expect(x == expected);
853}
854
855test "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
908test "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
931fn test__fixunshfti(a: f16, expected: u128) !void {
932 const x = __fixunshfti(a);
933 try testing.expect(x == expected);
934}
935
936test "fixunshfti for f16" {
937 try test__fixunshfti(math.inf(f16), math.maxInt(u128));
938 try test__fixunshfti(math.floatMax(f16), 65504);
939}
940
941fn test__fixunsxfti(a: f80, expected: u128) !void {
942 const x = __fixunsxfti(a);
943 try testing.expect(x == expected);
944}
945
946test "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 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __floatdidf(a: i64) callconv(.C) f64 {
15 return intToFloat(f64, a);
16}
17
18fn __aeabi_l2d(a: i64) callconv(.AAPCS) f64 {
19 return intToFloat(f64, a);
20}
lib/compiler_rt/floatdihf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatdihf, .{ .name = "__floatdihf", .linkage = common.linkage });
8}
9
10fn __floatdihf(a: i64) callconv(.C) f16 {
11 return intToFloat(f16, a);
12}
lib/compiler_rt/floatdisf.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __floatdisf(a: i64) callconv(.C) f32 {
15 return intToFloat(f32, a);
16}
17
18fn __aeabi_l2f(a: i64) callconv(.AAPCS) f32 {
19 return intToFloat(f32, a);
20}
lib/compiler_rt/floatditf.zig created+26
......@@ -0,0 +1,26 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __floatditf(a: i64) callconv(.C) f128 {
17 return intToFloat(f128, a);
18}
19
20fn __floatdikf(a: i64) callconv(.C) f128 {
21 return intToFloat(f128, a);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatdixf, .{ .name = "__floatdixf", .linkage = common.linkage });
8}
9
10fn __floatdixf(a: i64) callconv(.C) f80 {
11 return intToFloat(f80, a);
12}
lib/compiler_rt/floatsidf.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __floatsidf(a: i32) callconv(.C) f64 {
15 return intToFloat(f64, a);
16}
17
18fn __aeabi_i2d(a: i32) callconv(.AAPCS) f64 {
19 return intToFloat(f64, a);
20}
lib/compiler_rt/floatsihf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatsihf, .{ .name = "__floatsihf", .linkage = common.linkage });
8}
9
10fn __floatsihf(a: i32) callconv(.C) f16 {
11 return intToFloat(f16, a);
12}
lib/compiler_rt/floatsisf.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __floatsisf(a: i32) callconv(.C) f32 {
15 return intToFloat(f32, a);
16}
17
18fn __aeabi_i2f(a: i32) callconv(.AAPCS) f32 {
19 return intToFloat(f32, a);
20}
lib/compiler_rt/floatsitf.zig created+26
......@@ -0,0 +1,26 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __floatsitf(a: i32) callconv(.C) f128 {
17 return intToFloat(f128, a);
18}
19
20fn __floatsikf(a: i32) callconv(.C) f128 {
21 return intToFloat(f128, a);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatsixf, .{ .name = "__floatsixf", .linkage = common.linkage });
8}
9
10fn __floatsixf(a: i32) callconv(.C) f80 {
11 return intToFloat(f80, a);
12}
lib/compiler_rt/floattidf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floattidf, .{ .name = "__floattidf", .linkage = common.linkage });
8}
9
10pub fn __floattidf(a: i128) callconv(.C) f64 {
11 return intToFloat(f64, a);
12}
lib/compiler_rt/floattihf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floattihf, .{ .name = "__floattihf", .linkage = common.linkage });
8}
9
10fn __floattihf(a: i128) callconv(.C) f16 {
11 return intToFloat(f16, a);
12}
lib/compiler_rt/floattisf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floattisf, .{ .name = "__floattisf", .linkage = common.linkage });
8}
9
10pub fn __floattisf(a: i128) callconv(.C) f32 {
11 return intToFloat(f32, a);
12}
lib/compiler_rt/floattitf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floattitf, .{ .name = "__floattitf", .linkage = common.linkage });
8}
9
10pub fn __floattitf(a: i128) callconv(.C) f128 {
11 return intToFloat(f128, a);
12}
lib/compiler_rt/floattixf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floattixf, .{ .name = "__floattixf", .linkage = common.linkage });
8}
9
10fn __floattixf(a: i128) callconv(.C) f80 {
11 return intToFloat(f80, a);
12}
lib/compiler_rt/floatundidf.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __floatundidf(a: u64) callconv(.C) f64 {
15 return intToFloat(f64, a);
16}
17
18fn __aeabi_ul2d(a: u64) callconv(.AAPCS) f64 {
19 return intToFloat(f64, a);
20}
lib/compiler_rt/floatundihf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatundihf, .{ .name = "__floatundihf", .linkage = common.linkage });
8}
9
10fn __floatundihf(a: u64) callconv(.C) f16 {
11 return intToFloat(f16, a);
12}
lib/compiler_rt/floatundisf.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __floatundisf(a: u64) callconv(.C) f32 {
15 return intToFloat(f32, a);
16}
17
18fn __aeabi_ul2f(a: u64) callconv(.AAPCS) f32 {
19 return intToFloat(f32, a);
20}
lib/compiler_rt/floatunditf.zig created+26
......@@ -0,0 +1,26 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __floatunditf(a: u64) callconv(.C) f128 {
17 return intToFloat(f128, a);
18}
19
20fn __floatundikf(a: u64) callconv(.C) f128 {
21 return intToFloat(f128, a);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatundixf, .{ .name = "__floatundixf", .linkage = common.linkage });
8}
9
10fn __floatundixf(a: u64) callconv(.C) f80 {
11 return intToFloat(f80, a);
12}
lib/compiler_rt/floatunsidf.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __floatunsidf(a: u32) callconv(.C) f64 {
15 return intToFloat(f64, a);
16}
17
18fn __aeabi_ui2d(a: u32) callconv(.AAPCS) f64 {
19 return intToFloat(f64, a);
20}
lib/compiler_rt/floatunsihf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatunsihf, .{ .name = "__floatunsihf", .linkage = common.linkage });
8}
9
10pub fn __floatunsihf(a: u32) callconv(.C) f16 {
11 return intToFloat(f16, a);
12}
lib/compiler_rt/floatunsisf.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __floatunsisf(a: u32) callconv(.C) f32 {
15 return intToFloat(f32, a);
16}
17
18fn __aeabi_ui2f(a: u32) callconv(.AAPCS) f32 {
19 return intToFloat(f32, a);
20}
lib/compiler_rt/floatunsitf.zig created+26
......@@ -0,0 +1,26 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __floatunsitf(a: u32) callconv(.C) f128 {
17 return intToFloat(f128, a);
18}
19
20fn __floatunsikf(a: u32) callconv(.C) f128 {
21 return intToFloat(f128, a);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatunsixf, .{ .name = "__floatunsixf", .linkage = common.linkage });
8}
9
10fn __floatunsixf(a: u32) callconv(.C) f80 {
11 return intToFloat(f80, a);
12}
lib/compiler_rt/floatuntidf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = common.linkage });
8}
9
10pub fn __floatuntidf(a: u128) callconv(.C) f64 {
11 return intToFloat(f64, a);
12}
lib/compiler_rt/floatuntihf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatuntihf, .{ .name = "__floatuntihf", .linkage = common.linkage });
8}
9
10fn __floatuntihf(a: u128) callconv(.C) f16 {
11 return intToFloat(f16, a);
12}
lib/compiler_rt/floatuntisf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = common.linkage });
8}
9
10pub fn __floatuntisf(a: u128) callconv(.C) f32 {
11 return intToFloat(f32, a);
12}
lib/compiler_rt/floatuntitf.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __floatuntitf(a: u128) callconv(.C) f128 {
15 return intToFloat(f128, a);
16}
17
18fn __floatuntikf(a: u128) callconv(.C) f128 {
19 return intToFloat(f128, a);
20}
lib/compiler_rt/floatuntixf.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const intToFloat = @import("./int_to_float.zig").intToFloat;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__floatuntixf, .{ .name = "__floatuntixf", .linkage = common.linkage });
8}
9
10pub 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
66
77const std = @import("std");
8const builtin = @import("builtin");
89const math = std.math;
910const expect = std.testing.expect;
11const arch = builtin.cpu.arch;
12const common = @import("common.zig");
13
14pub const panic = common.panic;
15
16comptime {
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}
1025
1126pub fn __floorh(x: f16) callconv(.C) f16 {
1227 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
77
88const std = @import("std");
9const builtin = @import("builtin");
910const math = std.math;
1011const expect = std.testing.expect;
12const arch = builtin.cpu.arch;
13const common = @import("common.zig");
14
15pub const panic = common.panic;
16
17comptime {
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}
1126
1227pub fn __fmah(x: f16, y: f16, z: f16) callconv(.C) f16 {
1328 // TODO: more efficient implementation
lib/compiler_rt/fmax.zig+15
......@@ -1,5 +1,20 @@
11const std = @import("std");
2const builtin = @import("builtin");
23const math = std.math;
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
318
419pub fn __fmaxh(x: f16, y: f16) callconv(.C) f16 {
520 return generic_fmax(f16, x, y);
lib/compiler_rt/fmin.zig+15
......@@ -1,5 +1,20 @@
11const std = @import("std");
2const builtin = @import("builtin");
23const math = std.math;
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
318
419pub fn __fminh(x: f16, y: f16) callconv(.C) f16 {
520 return generic_fmin(f16, x, y);
lib/compiler_rt/fmod.zig+15-6
......@@ -2,7 +2,21 @@ const builtin = @import("builtin");
22const std = @import("std");
33const math = std.math;
44const assert = std.debug.assert;
5const normalize = @import("divdf3.zig").normalize;
5const arch = builtin.cpu.arch;
6const common = @import("common.zig");
7const normalize = common.normalize;
8
9pub const panic = common.panic;
10
11comptime {
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}
620
721pub fn __fmodh(x: f16, y: f16) callconv(.C) f16 {
822 // TODO: more efficient implementation
......@@ -20,8 +34,6 @@ pub fn fmod(x: f64, y: f64) callconv(.C) f64 {
2034/// fmodx - floating modulo large, returns the remainder of division for f80 types
2135/// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits
2236pub fn __fmodx(a: f80, b: f80) callconv(.C) f80 {
23 @setRuntimeSafety(builtin.is_test);
24
2537 const T = f80;
2638 const Z = std.meta.Int(.unsigned, @bitSizeOf(T));
2739
......@@ -120,7 +132,6 @@ pub fn __fmodx(a: f80, b: f80) callconv(.C) f80 {
120132/// fmodq - floating modulo large, returns the remainder of division for f128 types
121133/// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits
122134pub fn fmodq(a: f128, b: f128) callconv(.C) f128 {
123 @setRuntimeSafety(builtin.is_test);
124135 var amod = a;
125136 var bmod = b;
126137 const aPtr_u64 = @ptrCast([*]u64, &amod);
......@@ -249,8 +260,6 @@ pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.C) c_longdouble {
249260}
250261
251262inline fn generic_fmod(comptime T: type, x: T, y: T) T {
252 @setRuntimeSafety(false);
253
254263 const bits = @typeInfo(T).Float.bits;
255264 const uint = std.meta.Int(.unsigned, bits);
256265 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
3const common = @import("./common.zig");
4const comparef = @import("./comparef.zig");
5
6pub const panic = common.panic;
7
8comptime {
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."
20pub 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."
26pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 {
27 return __gedf2(a, b);
28}
29
30fn __aeabi_dcmpge(a: f64, b: f64) callconv(.AAPCS) i32 {
31 return @boolToInt(comparef.cmpf2(f64, comparef.GE, a, b) != .Less);
32}
33
34fn __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
3const common = @import("./common.zig");
4const comparef = @import("./comparef.zig");
5
6pub const panic = common.panic;
7
8comptime {
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."
20pub 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."
26pub fn __gtsf2(a: f32, b: f32) callconv(.C) i32 {
27 return __gesf2(a, b);
28}
29
30fn __aeabi_fcmpge(a: f32, b: f32) callconv(.AAPCS) i32 {
31 return @boolToInt(comparef.cmpf2(f32, comparef.GE, a, b) != .Less);
32}
33
34fn __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
3const common = @import("./common.zig");
4const comparef = @import("./comparef.zig");
5
6pub const panic = common.panic;
7
8comptime {
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."
23fn __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."
29fn __gttf2(a: f128, b: f128) callconv(.C) i32 {
30 return __getf2(a, b);
31}
32
33fn __gekf2(a: f128, b: f128) callconv(.C) i32 {
34 return __getf2(a, b);
35}
36
37fn __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 @@
1const common = @import("./common.zig");
2const comparef = @import("./comparef.zig");
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__gexf2, .{ .name = "__gexf2", .linkage = common.linkage });
8 @export(__gtxf2, .{ .name = "__gtxf2", .linkage = common.linkage });
9}
10
11fn __gexf2(a: f80, b: f80) callconv(.C) i32 {
12 return @enumToInt(comparef.cmp_f80(comparef.GE, a, b));
13}
14
15fn __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
23const builtin = @import("builtin");
34const std = @import("std");
45const testing = std.testing;
56const maxInt = std.math.maxInt;
67const minInt = std.math.minInt;
7
8const arch = builtin.cpu.arch;
9const is_test = builtin.is_test;
10const common = @import("common.zig");
811const udivmod = @import("udivmod.zig").udivmod;
912
10pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.C) i64 {
11 @setRuntimeSafety(builtin.is_test);
13pub const panic = common.panic;
14
15comptime {
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}
1235
36pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.C) i64 {
1337 const d = __divdi3(a, b);
1438 rem.* = a -% (d *% b);
1539 return d;
1640}
1741
1842pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.C) u64 {
19 @setRuntimeSafety(builtin.is_test);
2043 return udivmod(u64, a, b, maybe_rem);
2144}
2245
......@@ -25,8 +48,6 @@ test "test_udivmoddi4" {
2548}
2649
2750pub fn __divdi3(a: i64, b: i64) callconv(.C) i64 {
28 @setRuntimeSafety(builtin.is_test);
29
3051 // Set aside the sign of the quotient.
3152 const sign = @bitCast(u64, (a ^ b) >> 63);
3253 // 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 {
6485}
6586
6687pub fn __moddi3(a: i64, b: i64) callconv(.C) i64 {
67 @setRuntimeSafety(builtin.is_test);
68
6988 // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
7089 const abs_a = (a ^ (a >> 63)) -% (a >> 63);
7190 const abs_b = (b ^ (b >> 63)) -% (b >> 63);
......@@ -104,13 +123,10 @@ fn test_one_moddi3(a: i64, b: i64, expected_r: i64) !void {
104123}
105124
106125pub fn __udivdi3(a: u64, b: u64) callconv(.C) u64 {
107 @setRuntimeSafety(builtin.is_test);
108126 return __udivmoddi4(a, b, null);
109127}
110128
111129pub fn __umoddi3(a: u64, b: u64) callconv(.C) u64 {
112 @setRuntimeSafety(builtin.is_test);
113
114130 var r: u64 = undefined;
115131 _ = __udivmoddi4(a, b, &r);
116132 return r;
......@@ -130,8 +146,6 @@ fn test_one_umoddi3(a: u64, b: u64, expected_r: u64) !void {
130146}
131147
132148pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.C) i32 {
133 @setRuntimeSafety(builtin.is_test);
134
135149 const d = __divsi3(a, b);
136150 rem.* = a -% (d * b);
137151 return d;
......@@ -166,16 +180,20 @@ fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void {
166180}
167181
168182pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.C) u32 {
169 @setRuntimeSafety(builtin.is_test);
170
171183 const d = __udivsi3(a, b);
172184 rem.* = @bitCast(u32, @bitCast(i32, a) -% (@bitCast(i32, d) * @bitCast(i32, b)));
173185 return d;
174186}
175187
176188pub fn __divsi3(n: i32, d: i32) callconv(.C) i32 {
177 @setRuntimeSafety(builtin.is_test);
189 return div_i32(n, d);
190}
178191
192fn __aeabi_idiv(n: i32, d: i32) callconv(.AAPCS) i32 {
193 return div_i32(n, d);
194}
195
196inline fn div_i32(n: i32, d: i32) i32 {
179197 // Set aside the sign of the quotient.
180198 const sign = @bitCast(u32, (n ^ d) >> 31);
181199 // 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 {
213231}
214232
215233pub fn __udivsi3(n: u32, d: u32) callconv(.C) u32 {
216 @setRuntimeSafety(builtin.is_test);
234 return div_u32(n, d);
235}
217236
237fn __aeabi_uidiv(n: u32, d: u32) callconv(.AAPCS) u32 {
238 return div_u32(n, d);
239}
240
241inline fn div_u32(n: u32, d: u32) u32 {
218242 const n_uword_bits: c_uint = 32;
219243 // special cases
220244 if (d == 0) return 0; // ?!
......@@ -400,8 +424,6 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void {
400424}
401425
402426pub fn __modsi3(n: i32, d: i32) callconv(.C) i32 {
403 @setRuntimeSafety(builtin.is_test);
404
405427 return n -% __divsi3(n, d) *% d;
406428}
407429
......@@ -431,8 +453,6 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void {
431453}
432454
433455pub fn __umodsi3(n: u32, d: u32) callconv(.C) u32 {
434 @setRuntimeSafety(builtin.is_test);
435
436456 return n -% __udivsi3(n, d) *% d;
437457}
438458
......@@ -583,8 +603,6 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void {
583603}
584604
585605pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 {
586 @setRuntimeSafety(builtin.is_test);
587
588606 var ua = @bitCast(u32, a);
589607 var ub = @bitCast(u32, b);
590608 var r: u32 = 0;
lib/compiler_rt/int_to_float.zig created+58
......@@ -0,0 +1,58 @@
1const Int = @import("std").meta.Int;
2const math = @import("std").math;
3
4pub 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
56test {
57 _ = @import("int_to_float_test.zig");
58}
lib/compiler_rt/int_to_float_test.zig created+838
......@@ -0,0 +1,838 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const testing = std.testing;
4const math = std.math;
5
6const __floatunsihf = @import("floatunsihf.zig").__floatunsihf;
7
8// Conversion to f32
9const __floatsisf = @import("floatsisf.zig").__floatsisf;
10const __floatunsisf = @import("floatunsisf.zig").__floatunsisf;
11const __floatdisf = @import("floatdisf.zig").__floatdisf;
12const __floatundisf = @import("floatundisf.zig").__floatundisf;
13const __floattisf = @import("floattisf.zig").__floattisf;
14const __floatuntisf = @import("floatuntisf.zig").__floatuntisf;
15
16// Conversion to f64
17const __floatsidf = @import("floatsidf.zig").__floatsidf;
18const __floatunsidf = @import("floatunsidf.zig").__floatunsidf;
19const __floatdidf = @import("floatdidf.zig").__floatdidf;
20const __floatundidf = @import("floatundidf.zig").__floatundidf;
21const __floattidf = @import("floattidf.zig").__floattidf;
22const __floatuntidf = @import("floatuntidf.zig").__floatuntidf;
23
24// Conversion to f128
25const __floatsitf = @import("floatsitf.zig").__floatsitf;
26const __floatunsitf = @import("floatunsitf.zig").__floatunsitf;
27const __floatditf = @import("floatditf.zig").__floatditf;
28const __floatunditf = @import("floatunditf.zig").__floatunditf;
29const __floattitf = @import("floattitf.zig").__floattitf;
30const __floatuntitf = @import("floatuntitf.zig").__floatuntitf;
31
32fn test__floatsisf(a: i32, expected: u32) !void {
33 const r = __floatsisf(a);
34 try std.testing.expect(@bitCast(u32, r) == expected);
35}
36
37fn test_one_floatunsisf(a: u32, expected: u32) !void {
38 const r = __floatunsisf(a);
39 try std.testing.expect(@bitCast(u32, r) == expected);
40}
41
42test "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
50test "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
59fn test__floatdisf(a: i64, expected: f32) !void {
60 const x = __floatdisf(a);
61 try testing.expect(x == expected);
62}
63
64fn test__floatundisf(a: u64, expected: f32) !void {
65 try std.testing.expectEqual(expected, __floatundisf(a));
66}
67
68test "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
93test "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
118fn test__floattisf(a: i128, expected: f32) !void {
119 const x = __floattisf(a);
120 try testing.expect(x == expected);
121}
122
123fn test__floatuntisf(a: u128, expected: f32) !void {
124 const x = __floatuntisf(a);
125 try testing.expect(x == expected);
126}
127
128test "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
174test "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
235fn test_one_floatsidf(a: i32, expected: u64) !void {
236 const r = __floatsidf(a);
237 try std.testing.expect(@bitCast(u64, r) == expected);
238}
239
240fn test_one_floatunsidf(a: u32, expected: u64) !void {
241 const r = __floatunsidf(a);
242 try std.testing.expect(@bitCast(u64, r) == expected);
243}
244
245test "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
253test "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
261fn test__floatdidf(a: i64, expected: f64) !void {
262 const r = __floatdidf(a);
263 try testing.expect(r == expected);
264}
265
266fn test__floatundidf(a: u64, expected: f64) !void {
267 const r = __floatundidf(a);
268 try testing.expect(r == expected);
269}
270
271test "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
317test "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
360fn test__floattidf(a: i128, expected: f64) !void {
361 const x = __floattidf(a);
362 try testing.expect(x == expected);
363}
364
365fn test__floatuntidf(a: u128, expected: f64) !void {
366 const x = __floatuntidf(a);
367 try testing.expect(x == expected);
368}
369
370test "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
440test "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
507fn test__floatsitf(a: i32, expected: u128) !void {
508 const r = __floatsitf(a);
509 try std.testing.expect(@bitCast(u128, r) == expected);
510}
511
512test "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
521fn 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
541test "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
548fn test__floatditf(a: i64, expected: f128) !void {
549 const x = __floatditf(a);
550 try testing.expect(x == expected);
551}
552
553fn 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
573test "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
585test "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
596fn test__floattitf(a: i128, expected: f128) !void {
597 const x = __floattitf(a);
598 try testing.expect(x == expected);
599}
600
601fn test__floatuntitf(a: u128, expected: f128) !void {
602 const x = __floatuntitf(a);
603 try testing.expect(x == expected);
604}
605
606test "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
688test "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
773fn 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
780fn make_uti(high: u64, low: u64) u128 {
781 var result: u128 = high;
782 result <<= 64;
783 result |= low;
784 return result;
785}
786
787fn 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
794test "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
801test "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
813test "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
66
77const std = @import("std");
8const builtin = @import("builtin");
89const math = std.math;
910const testing = std.testing;
11const arch = builtin.cpu.arch;
12const common = @import("common.zig");
13
14pub const panic = common.panic;
15
16comptime {
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}
1025
1126pub fn __logh(a: f16) callconv(.C) f16 {
1227 // 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
66
77const std = @import("std");
8const builtin = @import("builtin");
89const math = std.math;
910const testing = std.testing;
1011const maxInt = std.math.maxInt;
12const arch = builtin.cpu.arch;
13const common = @import("common.zig");
14
15pub const panic = common.panic;
16
17comptime {
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}
1126
1227pub fn __log10h(a: f16) callconv(.C) f16 {
1328 // 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
66
77const std = @import("std");
8const builtin = @import("builtin");
89const math = std.math;
910const expect = std.testing.expect;
1011const maxInt = std.math.maxInt;
12const arch = builtin.cpu.arch;
13const common = @import("common.zig");
14
15pub const panic = common.panic;
16
17comptime {
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}
1126
1227pub fn __log2h(a: f16) callconv(.C) f16 {
1328 // 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
44
5const udivmod = @import("udivmod.zig").udivmod;
5const std = @import("std");
66const builtin = @import("builtin");
7const compiler_rt = @import("../compiler_rt.zig");
7const udivmod = @import("udivmod.zig").udivmod;
8const arch = builtin.cpu.arch;
9const common = @import("common.zig");
10
11pub const panic = common.panic;
12
13comptime {
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}
833
934pub fn __modti3(a: i128, b: i128) callconv(.C) i128 {
10 @setRuntimeSafety(builtin.is_test);
35 return mod(a, b);
36}
1137
38const v128 = @import("std").meta.Vector(2, u64);
39
40fn __modti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {
41 return @bitCast(v128, mod(@bitCast(i128, a), @bitCast(i128, b)));
42}
43
44inline fn mod(a: i128, b: i128) i128 {
1245 const s_a = a >> (128 - 1); // s = a < 0 ? -1 : 0
1346 const s_b = b >> (128 - 1); // s = b < 0 ? -1 : 0
1447
......@@ -20,14 +53,6 @@ pub fn __modti3(a: i128, b: i128) callconv(.C) i128 {
2053 return (@bitCast(i128, r) ^ s_a) -% s_a; // negate if s == -1
2154}
2255
23const v128 = @import("std").meta.Vector(2, u64);
24pub 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
3156test {
3257 _ = @import("modti3_test.zig");
3358}
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
5const std = @import("std");
6const math = std.math;
7const builtin = @import("builtin");
8const compiler_rt = @import("../compiler_rt.zig");
9
10pub fn __multf3(a: f128, b: f128) callconv(.C) f128 {
11 return mulXf3(f128, a, b);
12}
13pub fn __mulxf3(a: f80, b: f80) callconv(.C) f80 {
14 return mulXf3(f80, a, b);
15}
16pub fn __muldf3(a: f64, b: f64) callconv(.C) f64 {
17 return mulXf3(f64, a, b);
18}
19pub fn __mulsf3(a: f32, b: f32) callconv(.C) f32 {
20 return mulXf3(f32, a, b);
21}
22
23pub fn __aeabi_fmul(a: f32, b: f32) callconv(.C) f32 {
24 @setRuntimeSafety(false);
25 return @call(.{ .modifier = .always_inline }, __mulsf3, .{ a, b });
26}
27
28pub fn __aeabi_dmul(a: f64, b: f64) callconv(.C) f64 {
29 @setRuntimeSafety(false);
30 return @call(.{ .modifier = .always_inline }, __muldf3, .{ a, b });
31}
32
33fn 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
186fn 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
303fn PowerOfTwoSignificandZ(comptime T: type) type {
304 const bits = math.ceilPowerOfTwoAssert(u16, math.floatFractionalBits(T) + 1);
305 return std.meta.Int(.unsigned, bits);
306}
307
308fn 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`
321fn 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
342test {
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
5const std = @import("std");
6const math = std.math;
7const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64);
8const inf128 = @bitCast(f128, @as(u128, 0x7fff000000000000) << 64);
9
10const __multf3 = @import("mulXf3.zig").__multf3;
11const __mulxf3 = @import("mulXf3.zig").__mulxf3;
12const __muldf3 = @import("mulXf3.zig").__muldf3;
13const __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
18fn 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
37fn 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
46fn 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}
51test "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
111const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1)));
112
113fn 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
126test "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 @@
1const common = @import("./common.zig");
2const mulf3 = @import("./mulf3.zig").mulf3;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __muldf3(a: f64, b: f64) callconv(.C) f64 {
15 return mulf3(f64, a, b);
16}
17
18fn __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
14const std = @import("std");
25const builtin = @import("builtin");
3const is_test = builtin.is_test;
46const native_endian = builtin.cpu.arch.endian();
7const common = @import("common.zig");
8
9pub const panic = common.panic;
10
11comptime {
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
19pub fn __muldi3(a: i64, b: i64) callconv(.C) i64 {
20 return mul(a, b);
21}
522
6// Ported from
7// https://github.com/llvm/llvm-project/blob/llvmorg-9.0.0/compiler-rt/lib/builtins/muldi3.c
23fn __aeabi_lmul(a: i64, b: i64) callconv(.AAPCS) i64 {
24 return mul(a, b);
25}
26
27inline 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}
834
935const dwords = extern union {
1036 all: i64,
......@@ -20,9 +46,7 @@ const dwords = extern union {
2046 },
2147};
2248
23fn __muldsi3(a: u32, b: u32) i64 {
24 @setRuntimeSafety(is_test);
25
49fn muldsi3(a: u32, b: u32) i64 {
2650 const bits_in_word_2 = @sizeOf(i32) * 8 / 2;
2751 const lower_mask = (~@as(u32, 0)) >> bits_in_word_2;
2852
......@@ -42,16 +66,6 @@ fn __muldsi3(a: u32, b: u32) i64 {
4266 return r.all;
4367}
4468
45pub 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
5569test {
5670 _ = @import("muldi3_test.zig");
5771}
lib/compiler_rt/mulf3.zig created+203
......@@ -0,0 +1,203 @@
1const std = @import("std");
2const math = std.math;
3const builtin = @import("builtin");
4const 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
8pub 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`
164fn 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
185fn 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
196fn PowerOfTwoSignificandZ(comptime T: type) type {
197 const bits = math.ceilPowerOfTwoAssert(u16, math.floatFractionalBits(T) + 1);
198 return std.meta.Int(.unsigned, bits);
199}
200
201test {
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
5const std = @import("std");
6const math = std.math;
7const qnan128 = @bitCast(f128, @as(u128, 0x7fff800000000000) << 64);
8const inf128 = @bitCast(f128, @as(u128, 0x7fff000000000000) << 64);
9
10const __multf3 = @import("multf3.zig").__multf3;
11const __mulxf3 = @import("mulxf3.zig").__mulxf3;
12const __muldf3 = @import("muldf3.zig").__muldf3;
13const __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
18fn 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
37fn 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
46fn 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}
51test "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
111const qnan80 = @bitCast(f80, @bitCast(u80, math.nan(f80)) | (1 << (math.floatFractionalBits(f80) - 1)));
112
113fn 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
126test "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 @@
1const builtin = @import("builtin");
21const std = @import("std");
2const builtin = @import("builtin");
33const math = std.math;
4const common = @import("common.zig");
5
6pub const panic = common.panic;
7
8comptime {
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}
413
514// mulo - multiplication overflow
615// * return a*%b.
......@@ -9,7 +18,6 @@ const math = std.math;
918// - muloXi4_genericFast for 2*bitsize <= usize
1019
1120inline fn muloXi4_genericSmall(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
12 @setRuntimeSafety(builtin.is_test);
1321 overflow.* = 0;
1422 const min = math.minInt(ST);
1523 var res: ST = a *% b;
......@@ -24,7 +32,6 @@ inline fn muloXi4_genericSmall(comptime ST: type, a: ST, b: ST, overflow: *c_int
2432}
2533
2634inline fn muloXi4_genericFast(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
27 @setRuntimeSafety(builtin.is_test);
2835 overflow.* = 0;
2936 const EST = switch (ST) {
3037 i32 => i64,
lib/compiler_rt/mulsf3.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const mulf3 = @import("./mulf3.zig").mulf3;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __mulsf3(a: f32, b: f32) callconv(.C) f32 {
15 return mulf3(f32, a, b);
16}
17
18fn __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 @@
1const common = @import("./common.zig");
2const mulf3 = @import("./mulf3.zig").mulf3;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __multf3(a: f128, b: f128) callconv(.C) f128 {
17 return mulf3(f128, a, b);
18}
19
20fn __mulkf3(a: f128, b: f128) callconv(.C) f128 {
21 return mulf3(f128, a, b);
22}
23
24fn _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 @@
1const 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
25const std = @import("std");
36const builtin = @import("builtin");
4const is_test = builtin.is_test;
7const arch = builtin.cpu.arch;
58const native_endian = builtin.cpu.arch.endian();
9const common = @import("common.zig");
10
11pub const panic = common.panic;
612
7// Ported from git@github.com:llvm-project/llvm-project-20170507.git
8// ae684fad6d34858c014c94da69c15e7774a633c3
9// 2018-08-13
13comptime {
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}
1030
1131pub fn __multi3(a: i128, b: i128) callconv(.C) i128 {
12 @setRuntimeSafety(is_test);
32 return mul(a, b);
33}
34
35const v128 = @Vector(2, u64);
36
37fn __multi3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {
38 return @bitCast(v128, mul(@bitCast(i128, a), @bitCast(i128, b)));
39}
40
41inline fn mul(a: i128, b: i128) i128 {
1342 const x = twords{ .all = a };
1443 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) };
1645 r.s.high +%= x.s.high *% y.s.low +% x.s.low *% y.s.high;
1746 return r.all;
1847}
1948
20const v128 = @Vector(2, u64);
21pub 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
28fn __mulddi3(a: u64, b: u64) i128 {
49fn mulddi3(a: u64, b: u64) i128 {
2950 const bits_in_dword_2 = (@sizeOf(i64) * 8) / 2;
3051 const lower_mask = ~@as(u64, 0) >> bits_in_dword_2;
3152 var r: twords = undefined;
lib/compiler_rt/mulxf3.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const mulf3 = @import("./mulf3.zig").mulf3;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__mulxf3, .{ .name = "__mulxf3", .linkage = common.linkage });
8}
9
10pub 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 @@
11const std = @import("std");
2const builtin = @import("builtin");
3const common = @import("common.zig");
4
5pub const panic = common.panic;
6
7comptime {
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}
216
317pub fn __negsf2(a: f32) callconv(.C) f32 {
418 return negXf2(f32, a);
519}
620
7pub fn __negdf2(a: f64) callconv(.C) f64 {
8 return negXf2(f64, a);
21fn __aeabi_fneg(a: f32) callconv(.AAPCS) f32 {
22 return negXf2(f32, a);
923}
1024
11pub fn __aeabi_fneg(arg: f32) callconv(.AAPCS) f32 {
12 @setRuntimeSafety(false);
13 return @call(.{ .modifier = .always_inline }, __negsf2, .{arg});
25pub fn __negdf2(a: f64) callconv(.C) f64 {
26 return negXf2(f64, a);
1427}
1528
16pub fn __aeabi_dneg(arg: f64) callconv(.AAPCS) f64 {
17 @setRuntimeSafety(false);
18 return @call(.{ .modifier = .always_inline }, __negdf2, .{arg});
29fn __aeabi_dneg(a: f64) callconv(.AAPCS) f64 {
30 return negXf2(f64, a);
1931}
2032
21fn negXf2(comptime T: type, a: T) T {
33inline fn negXf2(comptime T: type, a: T) T {
2234 const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
2335
2436 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
19const std = @import("std");
210const builtin = @import("builtin");
11const common = @import("common.zig");
312
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
13pub const panic = common.panic;
1314
14inline fn negXi2(comptime T: type, a: T) T {
15 @setRuntimeSafety(builtin.is_test);
16 return -a;
15comptime {
16 @export(__negsi2, .{ .name = "__negsi2", .linkage = common.linkage });
17 @export(__negdi2, .{ .name = "__negdi2", .linkage = common.linkage });
18 @export(__negti2, .{ .name = "__negti2", .linkage = common.linkage });
1719}
1820
1921pub fn __negsi2(a: i32) callconv(.C) i32 {
......@@ -28,6 +30,10 @@ pub fn __negti2(a: i128) callconv(.C) i128 {
2830 return negXi2(i128, a);
2931}
3032
33inline fn negXi2(comptime T: type, a: T) T {
34 return -a;
35}
36
3137test {
3238 _ = @import("negsi2_test.zig");
3339 _ = @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
4const std = @import("std");
5const builtin = @import("builtin");
6const common = @import("common.zig");
47
5// assume -0 == 0 is gracefully handled by the hardware
6inline 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;
8pub const panic = common.panic;
9
10comptime {
11 @export(__negvsi2, .{ .name = "__negvsi2", .linkage = common.linkage });
12 @export(__negvdi2, .{ .name = "__negvdi2", .linkage = common.linkage });
13 @export(__negvti2, .{ .name = "__negvti2", .linkage = common.linkage });
1814}
1915
2016pub fn __negvsi2(a: i32) callconv(.C) i32 {
......@@ -29,6 +25,20 @@ pub fn __negvti2(a: i128) callconv(.C) i128 {
2925 return negvXi(i128, a);
3026}
3127
28inline 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
3242test {
3343 _ = @import("negvsi2_test.zig");
3444 _ = @import("negvdi2_test.zig");
lib/compiler_rt/os_version_check.zig+32-21
......@@ -1,5 +1,14 @@
1const testing = @import("std").testing;
1const std = @import("std");
2const testing = std.testing;
23const builtin = @import("builtin");
4const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
5pub const panic = @import("common.zig").panic;
6
7comptime {
8 if (builtin.os.tag.isDarwin()) {
9 @export(__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = linkage });
10 }
11}
312
413// Ported from llvm-project 13.0.0 d7b669b3a30345cfcdb2fde2af6f48aa4b94845d
514//
......@@ -16,30 +25,32 @@ const builtin = @import("builtin");
1625// the newer codepath, which merely calls out to the Darwin _availability_version_check API which is
1726// available on macOS 10.15+, iOS 13+, tvOS 13+ and watchOS 6+.
1827
19inline fn constructVersion(major: u32, minor: u32, subminor: u32) u32 {
20 return ((major & 0xffff) << 16) | ((minor & 0xff) << 8) | (subminor & 0xff);
21}
28const __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 }
2232
23// Darwin-only
24pub 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 }
3141
32// _availability_version_check darwin API support.
33const dyld_platform_t = u32;
34const dyld_build_version_t = extern struct {
35 platform: dyld_platform_t,
36 version: u32,
37};
38// Darwin-only
39extern "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 {};
4051
4152test "isPlatformVersionAtLeast" {
42 if (!builtin.os.tag.isDarwin()) return error.SkipZigTest;
53 if (!comptime builtin.os.tag.isDarwin()) return error.SkipZigTest;
4354
4455 // Note: this test depends on the actual host OS version since it is merely calling into the
4556 // 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
14const std = @import("std");
25const builtin = @import("builtin");
6const common = @import("common.zig");
37
4// parity - if number of bits set is even => 0, else => 1
5// - pariytXi2_generic for big and little endian
8pub const panic = common.panic;
69
7inline fn parityXi2(comptime T: type, a: T) i32 {
8 @setRuntimeSafety(builtin.is_test);
10comptime {
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
16pub fn __paritysi2(a: i32) callconv(.C) i32 {
17 return parityXi2(i32, a);
18}
19
20pub fn __paritydi2(a: i64) callconv(.C) i32 {
21 return parityXi2(i64, a);
22}
23
24pub fn __parityti2(a: i128) callconv(.C) i32 {
25 return parityXi2(i128, a);
26}
927
28inline fn parityXi2(comptime T: type, a: T) i32 {
1029 var x = switch (@bitSizeOf(T)) {
1130 32 => @bitCast(u32, a),
1231 64 => @bitCast(u64, a),
......@@ -23,18 +42,6 @@ inline fn parityXi2(comptime T: type, a: T) i32 {
2342 return (@intCast(u16, 0x6996) >> @intCast(u4, x)) & 1; // optimization for >>2 and >>1
2443}
2544
26pub fn __paritysi2(a: i32) callconv(.C) i32 {
27 return parityXi2(i32, a);
28}
29
30pub fn __paritydi2(a: i64) callconv(.C) i32 {
31 return parityXi2(i64, a);
32}
33
34pub fn __parityti2(a: i128) callconv(.C) i32 {
35 return parityXi2(i128, a);
36}
37
3845test {
3946 _ = @import("paritysi2_test.zig");
4047 _ = @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
19const builtin = @import("builtin");
210const std = @import("std");
11const common = @import("common.zig");
12
13pub const panic = common.panic;
14
15comptime {
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}
320
4// popcount - population count
5// counts the number of 1 bits
21pub fn __popcountsi2(a: i32) callconv(.C) i32 {
22 return popcountXi2(i32, a);
23}
624
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".
25pub fn __popcountdi2(a: i64) callconv(.C) i32 {
26 return popcountXi2(i64, a);
27}
28
29pub fn __popcountti2(a: i128) callconv(.C) i32 {
30 return popcountXi2(i128, a);
31}
1232
1333inline fn popcountXi2(comptime ST: type, a: ST) i32 {
14 @setRuntimeSafety(builtin.is_test);
1534 const UT = switch (ST) {
1635 i32 => u32,
1736 i64 => u64,
......@@ -30,18 +49,6 @@ inline fn popcountXi2(comptime ST: type, a: ST) i32 {
3049 return @intCast(i32, x);
3150}
3251
33pub fn __popcountsi2(a: i32) callconv(.C) i32 {
34 return popcountXi2(i32, a);
35}
36
37pub fn __popcountdi2(a: i64) callconv(.C) i32 {
38 return popcountXi2(i64, a);
39}
40
41pub fn __popcountti2(a: i128) callconv(.C) i32 {
42 return popcountXi2(i128, a);
43}
44
4552test {
4653 _ = @import("popcountsi2_test.zig");
4754 _ = @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
66
77const std = @import("std");
8const builtin = @import("builtin");
89const math = std.math;
910const expect = std.testing.expect;
11const arch = builtin.cpu.arch;
12const common = @import("common.zig");
13
14pub const panic = common.panic;
15
16comptime {
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}
1025
1126pub fn __roundh(x: f16) callconv(.C) f16 {
1227 // TODO: more efficient implementation
lib/compiler_rt/shift.zig+42-18
......@@ -1,13 +1,33 @@
11const std = @import("std");
2const builtin = @import("builtin");
23const Log2Int = std.math.Log2Int;
3const native_endian = @import("builtin").cpu.arch.endian();
4const native_endian = builtin.cpu.arch.endian();
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
424
525fn Dwords(comptime T: type, comptime signed_half: bool) type {
626 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;
1131
1232 all: T,
1333 s: if (native_endian == .Little)
......@@ -19,7 +39,7 @@ fn Dwords(comptime T: type, comptime signed_half: bool) type {
1939
2040// Arithmetic shift left
2141// Precondition: 0 <= b < bits_in_dword
22pub inline fn ashlXi3(comptime T: type, a: T, b: i32) T {
42inline fn ashlXi3(comptime T: type, a: T, b: i32) T {
2343 const dwords = Dwords(T, false);
2444 const S = Log2Int(dwords.HalfT);
2545
......@@ -42,7 +62,7 @@ pub inline fn ashlXi3(comptime T: type, a: T, b: i32) T {
4262
4363// Arithmetic shift right
4464// Precondition: 0 <= b < T.bit_count
45pub inline fn ashrXi3(comptime T: type, a: T, b: i32) T {
65inline fn ashrXi3(comptime T: type, a: T, b: i32) T {
4666 const dwords = Dwords(T, true);
4767 const S = Log2Int(dwords.HalfT);
4868
......@@ -69,7 +89,7 @@ pub inline fn ashrXi3(comptime T: type, a: T, b: i32) T {
6989
7090// Logical shift right
7191// Precondition: 0 <= b < T.bit_count
72pub inline fn lshrXi3(comptime T: type, a: T, b: i32) T {
92inline fn lshrXi3(comptime T: type, a: T, b: i32) T {
7393 const dwords = Dwords(T, false);
7494 const S = Log2Int(dwords.HalfT);
7595
......@@ -93,30 +113,34 @@ pub inline fn lshrXi3(comptime T: type, a: T, b: i32) T {
93113pub fn __ashldi3(a: i64, b: i32) callconv(.C) i64 {
94114 return ashlXi3(i64, a, b);
95115}
116fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 {
117 return ashlXi3(i64, a, b);
118}
119
96120pub fn __ashlti3(a: i128, b: i32) callconv(.C) i128 {
97121 return ashlXi3(i128, a, b);
98122}
123
99124pub fn __ashrdi3(a: i64, b: i32) callconv(.C) i64 {
100125 return ashrXi3(i64, a, b);
101126}
127fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 {
128 return ashrXi3(i64, a, b);
129}
130
102131pub fn __ashrti3(a: i128, b: i32) callconv(.C) i128 {
103132 return ashrXi3(i128, a, b);
104133}
134
105135pub fn __lshrdi3(a: i64, b: i32) callconv(.C) i64 {
106136 return lshrXi3(i64, a, b);
107137}
108pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 {
109 return lshrXi3(i128, a, b);
138fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 {
139 return lshrXi3(i64, a, b);
110140}
111141
112pub fn __aeabi_llsl(a: i64, b: i32) callconv(.AAPCS) i64 {
113 return ashlXi3(i64, a, b);
114}
115pub fn __aeabi_lasr(a: i64, b: i32) callconv(.AAPCS) i64 {
116 return ashrXi3(i64, a, b);
117}
118pub fn __aeabi_llsr(a: i64, b: i32) callconv(.AAPCS) i64 {
119 return lshrXi3(i64, a, b);
142pub fn __lshrti3(a: i128, b: i32) callconv(.C) i128 {
143 return lshrXi3(i128, a, b);
120144}
121145
122146test {
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
66
77const std = @import("std");
8const builtin = @import("builtin");
9const arch = builtin.cpu.arch;
810const math = std.math;
911const expect = std.testing.expect;
12const common = @import("common.zig");
1013
1114const trig = @import("trig.zig");
1215const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
1316const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
1417
18pub const panic = common.panic;
19
20comptime {
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
1530pub fn __sinh(x: f16) callconv(.C) f16 {
1631 // TODO: more efficient implementation
1732 return @floatCast(f16, sinf(x));
lib/compiler_rt/sincos.zig+16-3
......@@ -1,10 +1,23 @@
11const std = @import("std");
2const builtin = @import("builtin");
3const arch = builtin.cpu.arch;
24const math = std.math;
3const sin = @import("sin.zig");
4const cos = @import("cos.zig");
55const trig = @import("trig.zig");
66const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
77const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
8const common = @import("common.zig");
9
10pub const panic = common.panic;
11
12comptime {
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}
821
922pub fn __sincosh(x: f16, r_sin: *f16, r_cos: *f16) callconv(.C) void {
1023 // TODO: more efficient implementation
......@@ -192,7 +205,7 @@ pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) call
192205 }
193206}
194207
195const rem_pio2_generic = @compileError("TODO");
208pub const rem_pio2_generic = @compileError("TODO");
196209
197210/// Ported from musl sincosl.c. Needs the following dependencies to be complete:
198211/// * 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
4const std = @import("std");
5const builtin = @import("builtin");
6
7// The SPARC Architecture Manual, Version 9:
8// A.13 Floating-Point Compare
9const FCMP = enum(i32) {
10 Equal = 0,
11 Less = 1,
12 Greater = 2,
13 Unordered = 3,
14};
15
16// Basic arithmetic
17
18pub fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.C) void {
19 c.* = @import("addXf3.zig").__addtf3(a.*, b.*);
20}
21
22pub fn _Qp_div(c: *f128, a: *f128, b: *f128) callconv(.C) void {
23 c.* = @import("divtf3.zig").__divtf3(a.*, b.*);
24}
25
26pub fn _Qp_mul(c: *f128, a: *f128, b: *f128) callconv(.C) void {
27 c.* = @import("mulXf3.zig").__multf3(a.*, b.*);
28}
29
30pub 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
36pub fn _Qp_cmp(a: *f128, b: *f128) callconv(.C) i32 {
37 return @enumToInt(@import("compareXf2.zig").cmp(f128, FCMP, a.*, b.*));
38}
39
40pub fn _Qp_feq(a: *f128, b: *f128) callconv(.C) bool {
41 return _Qp_cmp(a, b) == @enumToInt(FCMP.Equal);
42}
43
44pub fn _Qp_fne(a: *f128, b: *f128) callconv(.C) bool {
45 return _Qp_cmp(a, b) != @enumToInt(FCMP.Equal);
46}
47
48pub fn _Qp_flt(a: *f128, b: *f128) callconv(.C) bool {
49 return _Qp_cmp(a, b) == @enumToInt(FCMP.Less);
50}
51
52pub 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
57pub fn _Qp_fgt(a: *f128, b: *f128) callconv(.C) bool {
58 return _Qp_cmp(a, b) == @enumToInt(FCMP.Greater);
59}
60
61pub 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
68pub fn _Qp_itoq(c: *f128, a: i32) callconv(.C) void {
69 c.* = @import("floatXiYf.zig").__floatsitf(a);
70}
71
72pub fn _Qp_uitoq(c: *f128, a: u32) callconv(.C) void {
73 c.* = @import("floatXiYf.zig").__floatunsitf(a);
74}
75
76pub fn _Qp_xtoq(c: *f128, a: i64) callconv(.C) void {
77 c.* = @import("floatXiYf.zig").__floatditf(a);
78}
79
80pub fn _Qp_uxtoq(c: *f128, a: u64) callconv(.C) void {
81 c.* = @import("floatXiYf.zig").__floatunditf(a);
82}
83
84pub fn _Qp_stoq(c: *f128, a: f32) callconv(.C) void {
85 c.* = @import("extendXfYf2.zig").__extendsftf2(a);
86}
87
88pub fn _Qp_dtoq(c: *f128, a: f64) callconv(.C) void {
89 c.* = @import("extendXfYf2.zig").__extenddftf2(a);
90}
91
92pub fn _Qp_qtoi(a: *f128) callconv(.C) i32 {
93 return @import("fixXfYi.zig").__fixtfsi(a.*);
94}
95
96pub fn _Qp_qtoui(a: *f128) callconv(.C) u32 {
97 return @import("fixXfYi.zig").__fixunstfsi(a.*);
98}
99
100pub fn _Qp_qtox(a: *f128) callconv(.C) i64 {
101 return @import("fixXfYi.zig").__fixtfdi(a.*);
102}
103
104pub fn _Qp_qtoux(a: *f128) callconv(.C) u64 {
105 return @import("fixXfYi.zig").__fixunstfdi(a.*);
106}
107
108pub fn _Qp_qtos(a: *f128) callconv(.C) f32 {
109 return @import("truncXfYf2.zig").__trunctfsf2(a.*);
110}
111
112pub 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 @@
11const std = @import("std");
2const builtin = @import("builtin");
3const arch = builtin.cpu.arch;
24const math = std.math;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
318
419pub fn __sqrth(x: f16) callconv(.C) f16 {
520 // TODO: more efficient implementation
lib/compiler_rt/stack_probe.zig+46-7
......@@ -1,4 +1,43 @@
1const native_arch = @import("builtin").cpu.arch;
1const std = @import("std");
2const builtin = @import("builtin");
3const os_tag = builtin.os.tag;
4const arch = builtin.cpu.arch;
5const abi = builtin.abi;
6const is_test = builtin.is_test;
7
8const is_gnu = abi.isGnu();
9const is_mingw = os_tag == .windows and is_gnu;
10
11const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
12const strong_linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Strong;
13pub const panic = @import("common.zig").panic;
14
15comptime {
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}
241
342// Zig's own stack-probe routine (available only on x86 and x86_64)
443pub fn zig_probe_stack() callconv(.Naked) void {
......@@ -8,7 +47,7 @@ pub fn zig_probe_stack() callconv(.Naked) void {
847 // invalid so let's update it on the go, otherwise we'll get a segfault
948 // instead of triggering the stack growth.
1049
11 switch (native_arch) {
50 switch (arch) {
1251 .x86_64 => {
1352 // %rax = probe length, %rsp = stack pointer
1453 asm volatile (
......@@ -60,7 +99,7 @@ pub fn zig_probe_stack() callconv(.Naked) void {
6099fn win_probe_stack_only() void {
61100 @setRuntimeSafety(false);
62101
63 switch (native_arch) {
102 switch (arch) {
64103 .x86_64 => {
65104 asm volatile (
66105 \\ push %%rcx
......@@ -105,7 +144,7 @@ fn win_probe_stack_only() void {
105144 },
106145 else => {},
107146 }
108 if (comptime native_arch.isAARCH64()) {
147 if (comptime arch.isAARCH64()) {
109148 // NOTE: page size hardcoded to 4096 for now
110149 asm volatile (
111150 \\ lsl x16, x15, #4
......@@ -127,7 +166,7 @@ fn win_probe_stack_only() void {
127166fn win_probe_stack_adjust_sp() void {
128167 @setRuntimeSafety(false);
129168
130 switch (native_arch) {
169 switch (arch) {
131170 .x86_64 => {
132171 asm volatile (
133172 \\ push %%rcx
......@@ -201,9 +240,9 @@ pub fn _chkstk() callconv(.Naked) void {
201240}
202241pub fn __chkstk() callconv(.Naked) void {
203242 @setRuntimeSafety(false);
204 if (comptime native_arch.isAARCH64()) {
243 if (comptime arch.isAARCH64()) {
205244 @call(.{ .modifier = .always_inline }, win_probe_stack_only, .{});
206 } else switch (native_arch) {
245 } else switch (arch) {
207246 .i386 => @call(.{ .modifier = .always_inline }, win_probe_stack_adjust_sp, .{}),
208247 .x86_64 => @call(.{ .modifier = .always_inline }, win_probe_stack_only, .{}),
209248 else => unreachable,
lib/compiler_rt/subdf3.zig created+21
......@@ -0,0 +1,21 @@
1const common = @import("./common.zig");
2
3pub const panic = common.panic;
4
5comptime {
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
13fn __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
18fn __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
6const std = @import("std");
17const builtin = @import("builtin");
8const common = @import("common.zig");
9
10pub const panic = common.panic;
211
3// subo - subtract overflow
4// * return a-%b.
5// * return if a-b overflows => 1 else => 0
6// - suboXi4_generic as default
12comptime {
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
18pub fn __subosi4(a: i32, b: i32, overflow: *c_int) callconv(.C) i32 {
19 return suboXi4_generic(i32, a, b, overflow);
20}
21pub fn __subodi4(a: i64, b: i64, overflow: *c_int) callconv(.C) i64 {
22 return suboXi4_generic(i64, a, b, overflow);
23}
24pub fn __suboti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 {
25 return suboXi4_generic(i128, a, b, overflow);
26}
727
828inline fn suboXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
9 @setRuntimeSafety(builtin.is_test);
1029 overflow.* = 0;
1130 var sum: ST = a -% b;
1231 // 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
2140 return sum;
2241}
2342
24pub fn __subosi4(a: i32, b: i32, overflow: *c_int) callconv(.C) i32 {
25 return suboXi4_generic(i32, a, b, overflow);
26}
27pub fn __subodi4(a: i64, b: i64, overflow: *c_int) callconv(.C) i64 {
28 return suboXi4_generic(i64, a, b, overflow);
29}
30pub fn __suboti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 {
31 return suboXi4_generic(i128, a, b, overflow);
32}
33
3443test {
3544 _ = @import("subosi4_test.zig");
3645 _ = @import("subodi4_test.zig");
lib/compiler_rt/subsf3.zig created+21
......@@ -0,0 +1,21 @@
1const common = @import("./common.zig");
2
3pub const panic = common.panic;
4
5comptime {
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
13fn __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
18fn __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 @@
1const common = @import("./common.zig");
2
3pub const panic = common.panic;
4
5comptime {
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
15pub fn __subtf3(a: f128, b: f128) callconv(.C) f128 {
16 return sub(a, b);
17}
18
19fn __subkf3(a: f128, b: f128) callconv(.C) f128 {
20 return sub(a, b);
21}
22
23fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.C) void {
24 c.* = sub(a.*, b.*);
25}
26
27inline 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 @@
1const std = @import("std");
2const common = @import("./common.zig");
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__subxf3, .{ .name = "__subxf3", .linkage = common.linkage });
8}
9
10fn __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
77
88const std = @import("std");
9const builtin = @import("builtin");
910const math = std.math;
1011const expect = std.testing.expect;
1112
......@@ -13,6 +14,21 @@ const kernel = @import("trig.zig");
1314const rem_pio2 = @import("rem_pio2.zig").rem_pio2;
1415const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f;
1516
17const arch = builtin.cpu.arch;
18const common = @import("common.zig");
19
20pub const panic = common.panic;
21
22comptime {
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
1632pub fn __tanh(x: f16) callconv(.C) f16 {
1733 // TODO: more efficient implementation
1834 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
66
77const std = @import("std");
8const builtin = @import("builtin");
9const arch = builtin.cpu.arch;
810const math = std.math;
911const expect = std.testing.expect;
12const common = @import("common.zig");
13
14pub const panic = common.panic;
15
16comptime {
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}
1025
1126pub fn __trunch(x: f16) callconv(.C) f16 {
1227 // TODO: more efficient implementation
lib/compiler_rt/truncXfYf2.zig deleted-152
......@@ -1,152 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const 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.
9pub const F16T = if (native_arch.isAARCH64()) f16 else u16;
10
11pub fn __truncsfhf2(a: f32) callconv(.C) F16T {
12 return @bitCast(F16T, truncXfYf2(f16, f32, a));
13}
14
15pub fn __truncdfhf2(a: f64) callconv(.C) F16T {
16 return @bitCast(F16T, truncXfYf2(f16, f64, a));
17}
18
19pub fn __trunctfhf2(a: f128) callconv(.C) F16T {
20 return @bitCast(F16T, truncXfYf2(f16, f128, a));
21}
22
23pub fn __trunctfsf2(a: f128) callconv(.C) f32 {
24 return truncXfYf2(f32, f128, a);
25}
26
27pub fn __trunctfdf2(a: f128) callconv(.C) f64 {
28 return truncXfYf2(f64, f128, a);
29}
30
31pub fn __truncdfsf2(a: f64) callconv(.C) f32 {
32 return truncXfYf2(f32, f64, a);
33}
34
35pub fn __aeabi_d2f(a: f64) callconv(.AAPCS) f32 {
36 @setRuntimeSafety(false);
37 return truncXfYf2(f32, f64, a);
38}
39
40pub fn __aeabi_d2h(a: f64) callconv(.AAPCS) u16 {
41 @setRuntimeSafety(false);
42 return @bitCast(F16T, truncXfYf2(f16, f64, a));
43}
44
45pub fn __aeabi_f2h(a: f32) callconv(.AAPCS) u16 {
46 @setRuntimeSafety(false);
47 return @bitCast(F16T, truncXfYf2(f16, f32, a));
48}
49
50inline 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
150test {
151 _ = @import("truncXfYf2_test.zig");
152}
lib/compiler_rt/truncXfYf2_test.zig deleted-296
......@@ -1,296 +0,0 @@
1const std = @import("std");
2const __truncsfhf2 = @import("truncXfYf2.zig").__truncsfhf2;
3
4fn 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
14test "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
67const __truncdfhf2 = @import("truncXfYf2.zig").__truncdfhf2;
68
69fn 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
85fn 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
95test "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
135const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;
136
137fn 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
154test "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
170const __trunctfdf2 = @import("truncXfYf2.zig").__trunctfdf2;
171
172fn 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
189test "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
205const __truncdfsf2 = @import("truncXfYf2.zig").__truncdfsf2;
206
207fn 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
226test "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
242const __trunctfhf2 = @import("truncXfYf2.zig").__trunctfhf2;
243
244fn 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
257test "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 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const native_arch = builtin.cpu.arch;
4const 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.
8pub const F16T = if (native_arch.isAARCH64()) f16 else u16;
9
10pub fn __truncxfhf2(a: f80) callconv(.C) F16T {
11 return @bitCast(F16T, trunc(f16, a));
12}
13
14pub fn __truncxfsf2(a: f80) callconv(.C) f32 {
15 return trunc(f32, a);
16}
17
18pub fn __truncxfdf2(a: f80) callconv(.C) f64 {
19 return trunc(f64, a);
20}
21
22inline 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
106pub 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
163fn test__trunctfxf2(a: f128, expected: f80) !void {
164 const x = __trunctfxf2(a);
165 try testing.expect(x == expected);
166}
167
168test {
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 @@
1const common = @import("./common.zig");
2const truncf = @import("./truncf.zig").truncf;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __truncdfhf2(a: f64) callconv(.C) common.F16T {
15 return @bitCast(common.F16T, truncf(f16, f64, a));
16}
17
18fn __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 @@
1const common = @import("./common.zig");
2const truncf = @import("./truncf.zig").truncf;
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __truncdfsf2(a: f64) callconv(.C) f32 {
15 return truncf(f32, f64, a);
16}
17
18fn __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 @@
1const std = @import("std");
2
3pub 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
103pub 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
185test {
186 _ = @import("truncf_test.zig");
187}
lib/compiler_rt/truncf_test.zig created+306
......@@ -0,0 +1,306 @@
1const std = @import("std");
2const testing = std.testing;
3
4const __truncsfhf2 = @import("truncsfhf2.zig").__truncsfhf2;
5const __truncdfhf2 = @import("truncdfhf2.zig").__truncdfhf2;
6const __truncdfsf2 = @import("truncdfsf2.zig").__truncdfsf2;
7const __trunctfhf2 = @import("trunctfhf2.zig").__trunctfhf2;
8const __trunctfsf2 = @import("trunctfsf2.zig").__trunctfsf2;
9const __trunctfdf2 = @import("trunctfdf2.zig").__trunctfdf2;
10const __trunctfxf2 = @import("trunctfxf2.zig").__trunctfxf2;
11
12fn 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
22test "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
75fn 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
91fn 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
101test "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
141fn 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
158test "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
174fn 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
191test "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
207fn 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
226test "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
242fn 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
255test "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
296test "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
303fn 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 @@
1const common = @import("./common.zig");
2const truncf = @import("./truncf.zig").truncf;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __truncsfhf2(a: f32) callconv(.C) common.F16T {
17 return @bitCast(common.F16T, truncf(f16, f32, a));
18}
19
20fn __gnu_f2h_ieee(a: f32) callconv(.C) common.F16T {
21 return @bitCast(common.F16T, truncf(f16, f32, a));
22}
23
24fn __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 @@
1const common = @import("./common.zig");
2const truncf = @import("./truncf.zig").truncf;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __trunctfdf2(a: f128) callconv(.C) f64 {
17 return truncf(f64, f128, a);
18}
19
20fn __trunckfdf2(a: f128) callconv(.C) f64 {
21 return truncf(f64, f128, a);
22}
23
24fn _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 @@
1const common = @import("./common.zig");
2const truncf = @import("./truncf.zig").truncf;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = common.linkage });
8}
9
10pub 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 @@
1const common = @import("./common.zig");
2const truncf = @import("./truncf.zig").truncf;
3
4pub const panic = common.panic;
5
6comptime {
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
16pub fn __trunctfsf2(a: f128) callconv(.C) f32 {
17 return truncf(f32, f128, a);
18}
19
20fn __trunckfsf2(a: f128) callconv(.C) f32 {
21 return truncf(f32, f128, a);
22}
23
24fn _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 @@
1const math = @import("std").math;
2const common = @import("./common.zig");
3const trunc_f80 = @import("./truncf.zig").trunc_f80;
4
5pub const panic = common.panic;
6
7comptime {
8 @export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = common.linkage });
9}
10
11pub 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 @@
1const common = @import("./common.zig");
2const trunc_f80 = @import("./truncf.zig").trunc_f80;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__truncxfdf2, .{ .name = "__truncxfdf2", .linkage = common.linkage });
8}
9
10fn __truncxfdf2(a: f80) callconv(.C) f64 {
11 return trunc_f80(f64, a);
12}
lib/compiler_rt/truncxfhf2.zig created+12
......@@ -0,0 +1,12 @@
1const common = @import("./common.zig");
2const trunc_f80 = @import("./truncf.zig").trunc_f80;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__truncxfhf2, .{ .name = "__truncxfhf2", .linkage = common.linkage });
8}
9
10fn __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 @@
1const common = @import("./common.zig");
2const trunc_f80 = @import("./truncf.zig").trunc_f80;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(__truncxfsf2, .{ .name = "__truncxfsf2", .linkage = common.linkage });
8}
9
10fn __truncxfsf2(a: f80) callconv(.C) f32 {
11 return trunc_f80(f32, a);
12}
lib/compiler_rt/udivmodti4.zig+27-6
......@@ -1,15 +1,36 @@
1const udivmod = @import("udivmod.zig").udivmod;
1const std = @import("std");
22const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
3const udivmod = @import("udivmod.zig").udivmod;
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
426
527pub fn __udivmodti4(a: u128, b: u128, maybe_rem: ?*u128) callconv(.C) u128 {
6 @setRuntimeSafety(builtin.is_test);
728 return udivmod(u128, a, b, maybe_rem);
829}
930
10const v128 = @import("std").meta.Vector(2, u64);
11pub fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) callconv(.C) v128 {
12 @setRuntimeSafety(builtin.is_test);
31const v128 = std.meta.Vector(2, u64);
32
33fn __udivmodti4_windows_x86_64(a: v128, b: v128, maybe_rem: ?*u128) callconv(.C) v128 {
1334 return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), maybe_rem));
1435}
1536
lib/compiler_rt/udivti3.zig+32-7
......@@ -1,13 +1,38 @@
1const udivmodti4 = @import("udivmodti4.zig");
1const std = @import("std");
22const builtin = @import("builtin");
3const udivmod = @import("udivmod.zig").udivmod;
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
329
430pub 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);
732}
833
9const v128 = @import("std").meta.Vector(2, u64);
10pub 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);
34const v128 = std.meta.Vector(2, u64);
35
36fn __udivti3_windows_x86_64(a: v128, b: v128) callconv(.C) v128 {
37 return @bitCast(v128, udivmod(u128, @bitCast(u128, a), @bitCast(u128, b), null));
1338}
lib/compiler_rt/umodti3.zig+34-10
......@@ -1,18 +1,42 @@
1const udivmodti4 = @import("udivmodti4.zig");
1const std = @import("std");
22const builtin = @import("builtin");
3const compiler_rt = @import("../compiler_rt.zig");
3const udivmod = @import("udivmod.zig").udivmod;
4const arch = builtin.cpu.arch;
5const common = @import("common.zig");
6
7pub const panic = common.panic;
8
9comptime {
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}
429
530pub fn __umodti3(a: u128, b: u128) callconv(.C) u128 {
6 @setRuntimeSafety(builtin.is_test);
731 var r: u128 = undefined;
8 _ = udivmodti4.__udivmodti4(a, b, &r);
32 _ = udivmod(u128, a, b, &r);
933 return r;
1034}
1135
12const v128 = @import("std").meta.Vector(2, u64);
13pub 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 }));
36const v128 = std.meta.Vector(2, u64);
37
38fn __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);
1842}
lib/compiler_rt/unorddf2.zig created+20
......@@ -0,0 +1,20 @@
1const common = @import("./common.zig");
2const comparef = @import("./comparef.zig");
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __unorddf2(a: f64, b: f64) callconv(.C) i32 {
15 return comparef.unordcmp(f64, a, b);
16}
17
18fn __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 @@
1const common = @import("./common.zig");
2const comparef = @import("./comparef.zig");
3
4pub const panic = common.panic;
5
6comptime {
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
14pub fn __unordsf2(a: f32, b: f32) callconv(.C) i32 {
15 return comparef.unordcmp(f32, a, b);
16}
17
18fn __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 @@
1const common = @import("./common.zig");
2const comparef = @import("./comparef.zig");
3
4pub const panic = common.panic;
5
6comptime {
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
17fn __unordtf2(a: f128, b: f128) callconv(.C) i32 {
18 return comparef.unordcmp(f128, a, b);
19}
20
21fn __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,
9292test_evented_io: bool,
9393debug_compiler_runtime_libs: bool,
9494debug_compile_errors: bool,
95job_queued_compiler_rt_lib: bool = false,
96job_queued_compiler_rt_obj: bool = false,
97alloc_failure_occurred: bool = false,
9598
9699c_source_files: []const CSourceFile,
97100clang_argv: []const []const u8,
......@@ -129,11 +132,11 @@ libssp_static_lib: ?CRTFile = null,
129132/// Populated when we build the libc static library. A Job to build this is placed in the queue
130133/// and resolved before calling linker.flush().
131134libc_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().
134compiler_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().
137compiler_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().
137140compiler_rt_obj: ?CRTFile = null,
138141
139142glibc_so_files: ?glibc.BuiltSharedObjects = null,
......@@ -175,7 +178,7 @@ pub const CRTFile = struct {
175178 lock: Cache.Lock,
176179 full_object_path: []const u8,
177180
178 fn deinit(self: *CRTFile, gpa: Allocator) void {
181 pub fn deinit(self: *CRTFile, gpa: Allocator) void {
179182 self.lock.release();
180183 gpa.free(self.full_object_path);
181184 self.* = undefined;
......@@ -223,8 +226,6 @@ const Job = union(enum) {
223226 libcxxabi: void,
224227 libtsan: void,
225228 libssp: void,
226 compiler_rt_lib: void,
227 compiler_rt_obj: void,
228229 /// needed when not linking libc and using LLVM for code generation because it generates
229230 /// calls to, for example, memcpy and memset.
230231 zig_libc: void,
......@@ -1924,13 +1925,13 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
19241925 if (comp.bin_file.options.include_compiler_rt and capable_of_building_compiler_rt) {
19251926 if (is_exe_or_dyn_lib) {
19261927 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;
19281929 } else if (options.output_mode != .Obj) {
19291930 log.debug("queuing a job to build compiler_rt_obj", .{});
19301931 // If build-obj with -fcompiler-rt is requested, that is handled specially
19311932 // elsewhere. In this case we are making a static library, so we ask
19321933 // 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;
19341935 }
19351936 }
19361937 if (needs_c_symbols) {
......@@ -1978,7 +1979,7 @@ pub fn destroy(self: *Compilation) void {
19781979 if (self.libcxxabi_static_lib) |*crt_file| {
19791980 crt_file.deinit(gpa);
19801981 }
1981 if (self.compiler_rt_static_lib) |*crt_file| {
1982 if (self.compiler_rt_lib) |*crt_file| {
19821983 crt_file.deinit(gpa);
19831984 }
19841985 if (self.compiler_rt_obj) |*crt_file| {
......@@ -2020,6 +2021,7 @@ pub fn destroy(self: *Compilation) void {
20202021}
20212022
20222023pub fn clearMiscFailures(comp: *Compilation) void {
2024 comp.alloc_failure_occurred = false;
20232025 for (comp.misc_failures.values()) |*value| {
20242026 value.deinit(comp.gpa);
20252027 }
......@@ -2532,8 +2534,10 @@ pub fn makeBinFileWritable(self: *Compilation) !void {
25322534 return self.bin_file.makeWritable();
25332535}
25342536
2537/// This function is temporally single-threaded.
25352538pub 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);
25372541
25382542 if (self.bin_file.options.module) |module| {
25392543 total += module.failed_exports.count();
......@@ -2590,6 +2594,7 @@ pub fn totalErrorCount(self: *Compilation) usize {
25902594 return total;
25912595}
25922596
2597/// This function is temporally single-threaded.
25932598pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
25942599 var arena = std.heap.ArenaAllocator.init(self.gpa);
25952600 errdefer arena.deinit();
......@@ -2622,6 +2627,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
26222627 for (self.misc_failures.values()) |*value| {
26232628 try AllErrors.addPlainWithChildren(&arena, &errors, value.msg, value.children);
26242629 }
2630 if (self.alloc_failure_occurred) {
2631 try AllErrors.addPlain(&arena, &errors, "memory allocation failure");
2632 }
26252633 if (self.bin_file.options.module) |module| {
26262634 {
26272635 var it = module.failed_files.iterator();
......@@ -2739,6 +2747,8 @@ pub fn performAllTheWork(
27392747 comp.work_queue_wait_group.reset();
27402748 defer comp.work_queue_wait_group.wait();
27412749
2750 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;
2751
27422752 {
27432753 const astgen_frame = tracy.namedFrame("astgen");
27442754 defer astgen_frame.end();
......@@ -2783,7 +2793,6 @@ pub fn performAllTheWork(
27832793 }
27842794 }
27852795
2786 const use_stage1 = build_options.is_stage1 and comp.bin_file.options.use_stage1;
27872796 if (!use_stage1) {
27882797 const outdated_and_deleted_decls_frame = tracy.namedFrame("outdated_and_deleted_decls");
27892798 defer outdated_and_deleted_decls_frame.end();
......@@ -2826,6 +2835,16 @@ pub fn performAllTheWork(
28262835 }
28272836 break;
28282837 }
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 }
28292848}
28302849
28312850fn processOneJob(comp: *Compilation, job: Job) !void {
......@@ -2996,7 +3015,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
29963015 module.semaPkg(pkg) catch |err| switch (err) {
29973016 error.CurrentWorkingDirectoryUnlinked,
29983017 error.Unexpected,
2999 => try comp.setMiscFailure(
3018 => comp.lockAndSetMiscFailure(
30003019 .analyze_pkg,
30013020 "unexpected problem analyzing package '{s}'",
30023021 .{pkg.root_src_path},
......@@ -3011,7 +3030,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30113030
30123031 glibc.buildCRTFile(comp, crt_file) catch |err| {
30133032 // 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}", .{
30153034 @errorName(err),
30163035 });
30173036 };
......@@ -3022,7 +3041,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30223041
30233042 glibc.buildSharedObjects(comp) catch |err| {
30243043 // TODO Surface more error details.
3025 try comp.setMiscFailure(
3044 comp.lockAndSetMiscFailure(
30263045 .glibc_shared_objects,
30273046 "unable to build glibc shared objects: {s}",
30283047 .{@errorName(err)},
......@@ -3035,7 +3054,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30353054
30363055 musl.buildCRTFile(comp, crt_file) catch |err| {
30373056 // TODO Surface more error details.
3038 try comp.setMiscFailure(
3057 comp.lockAndSetMiscFailure(
30393058 .musl_crt_file,
30403059 "unable to build musl CRT file: {s}",
30413060 .{@errorName(err)},
......@@ -3048,7 +3067,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30483067
30493068 mingw.buildCRTFile(comp, crt_file) catch |err| {
30503069 // TODO Surface more error details.
3051 try comp.setMiscFailure(
3070 comp.lockAndSetMiscFailure(
30523071 .mingw_crt_file,
30533072 "unable to build mingw-w64 CRT file: {s}",
30543073 .{@errorName(err)},
......@@ -3062,7 +3081,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30623081 const link_lib = comp.bin_file.options.system_libs.keys()[index];
30633082 mingw.buildImportLib(comp, link_lib) catch |err| {
30643083 // TODO Surface more error details.
3065 try comp.setMiscFailure(
3084 comp.lockAndSetMiscFailure(
30663085 .windows_import_lib,
30673086 "unable to generate DLL import .lib file: {s}",
30683087 .{@errorName(err)},
......@@ -3075,7 +3094,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30753094
30763095 libunwind.buildStaticLib(comp) catch |err| {
30773096 // TODO Surface more error details.
3078 try comp.setMiscFailure(
3097 comp.lockAndSetMiscFailure(
30793098 .libunwind,
30803099 "unable to build libunwind: {s}",
30813100 .{@errorName(err)},
......@@ -3088,7 +3107,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
30883107
30893108 libcxx.buildLibCXX(comp) catch |err| {
30903109 // TODO Surface more error details.
3091 try comp.setMiscFailure(
3110 comp.lockAndSetMiscFailure(
30923111 .libcxx,
30933112 "unable to build libcxx: {s}",
30943113 .{@errorName(err)},
......@@ -3101,7 +3120,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31013120
31023121 libcxx.buildLibCXXABI(comp) catch |err| {
31033122 // TODO Surface more error details.
3104 try comp.setMiscFailure(
3123 comp.lockAndSetMiscFailure(
31053124 .libcxxabi,
31063125 "unable to build libcxxabi: {s}",
31073126 .{@errorName(err)},
......@@ -3114,7 +3133,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31143133
31153134 libtsan.buildTsan(comp) catch |err| {
31163135 // TODO Surface more error details.
3117 try comp.setMiscFailure(
3136 comp.lockAndSetMiscFailure(
31183137 .libtsan,
31193138 "unable to build TSAN library: {s}",
31203139 .{@errorName(err)},
......@@ -3127,51 +3146,13 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31273146
31283147 wasi_libc.buildCRTFile(comp, crt_file) catch |err| {
31293148 // TODO Surface more error details.
3130 try comp.setMiscFailure(
3149 comp.lockAndSetMiscFailure(
31313150 .wasi_libc_crt_file,
31323151 "unable to build WASI libc CRT file: {s}",
31333152 .{@errorName(err)},
31343153 );
31353154 };
31363155 },
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 },
31753156 .libssp => {
31763157 const named_frame = tracy.namedFrame("libssp");
31773158 defer named_frame.end();
......@@ -3184,7 +3165,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
31843165 ) catch |err| switch (err) {
31853166 error.OutOfMemory => return error.OutOfMemory,
31863167 error.SubCompilationFailed => return, // error reported already
3187 else => try comp.setMiscFailure(
3168 else => comp.lockAndSetMiscFailure(
31883169 .libssp,
31893170 "unable to build libssp: {s}",
31903171 .{@errorName(err)},
......@@ -3203,7 +3184,7 @@ fn processOneJob(comp: *Compilation, job: Job) !void {
32033184 ) catch |err| switch (err) {
32043185 error.OutOfMemory => return error.OutOfMemory,
32053186 error.SubCompilationFailed => return, // error reported already
3206 else => try comp.setMiscFailure(
3187 else => comp.lockAndSetMiscFailure(
32073188 .zig_libc,
32083189 "unable to build zig's multitarget libc: {s}",
32093190 .{@errorName(err)},
......@@ -3307,11 +3288,7 @@ fn workerUpdateBuiltinZigFile(
33073288
33083289 comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{
33093290 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 });
33153292 };
33163293}
33173294
......@@ -3525,6 +3502,21 @@ fn workerUpdateCObject(
35253502 };
35263503}
35273504
3505fn 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
35283520fn reportRetryableCObjectError(
35293521 comp: *Compilation,
35303522 c_object: *CObject,
......@@ -4623,14 +4615,21 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
46234615 comp.bin_file.options.object_format != .c;
46244616}
46254617
4626fn setMiscFailure(
4618fn 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`.
4625pub fn setMiscFailure(
46274626 comp: *Compilation,
46284627 tag: MiscTask,
46294628 comptime format: []const u8,
46304629 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();
46344633 const gop = comp.misc_failures.getOrPutAssumeCapacity(tag);
46354634 if (gop.found_existing) {
46364635 gop.value_ptr.deinit(comp.gpa);
......@@ -4638,6 +4637,19 @@ fn setMiscFailure(
46384637 gop.value_ptr.* = .{ .msg = msg };
46394638}
46404639
4640/// See also `setMiscFailure`.
4641pub 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
46414653pub fn dump_argv(argv: []const []const u8) void {
46424654 for (argv[0 .. argv.len - 1]) |arg| {
46434655 std.debug.print("{s} ", .{arg});
src/ThreadPool.zig+49-32
......@@ -1,6 +1,7 @@
11const std = @import("std");
22const builtin = @import("builtin");
33const ThreadPool = @This();
4const WaitGroup = @import("WaitGroup.zig");
45
56mutex: std.Thread.Mutex = .{},
67cond: std.Thread.Condition = .{},
......@@ -19,8 +20,8 @@ const RunProto = switch (builtin.zig_backend) {
1920 else => *const fn (*Runnable) void,
2021};
2122
22pub fn init(self: *ThreadPool, allocator: std.mem.Allocator) !void {
23 self.* = .{
23pub fn init(pool: *ThreadPool, allocator: std.mem.Allocator) !void {
24 pool.* = .{
2425 .allocator = allocator,
2526 .threads = &[_]std.Thread{},
2627 };
......@@ -30,48 +31,48 @@ pub fn init(self: *ThreadPool, allocator: std.mem.Allocator) !void {
3031 }
3132
3233 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);
3536
3637 // kill and join any threads we spawned previously on error.
3738 var spawned: usize = 0;
38 errdefer self.join(spawned);
39 errdefer pool.join(spawned);
3940
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});
4243 spawned += 1;
4344 }
4445}
4546
46pub fn deinit(self: *ThreadPool) void {
47 self.join(self.threads.len); // kill and join all threads.
48 self.* = undefined;
47pub fn deinit(pool: *ThreadPool) void {
48 pool.join(pool.threads.len); // kill and join all threads.
49 pool.* = undefined;
4950}
5051
51fn join(self: *ThreadPool, spawned: usize) void {
52fn join(pool: *ThreadPool, spawned: usize) void {
5253 if (builtin.single_threaded) {
5354 return;
5455 }
5556
5657 {
57 self.mutex.lock();
58 defer self.mutex.unlock();
58 pool.mutex.lock();
59 defer pool.mutex.unlock();
5960
6061 // ensure future worker threads exit the dequeue loop
61 self.is_running = false;
62 pool.is_running = false;
6263 }
6364
6465 // wake up any sleeping threads (this can be done outside the mutex)
6566 // 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| {
6869 thread.join();
6970 }
7071
71 self.allocator.free(self.threads);
72 pool.allocator.free(pool.threads);
7273}
7374
74pub fn spawn(self: *ThreadPool, comptime func: anytype, args: anytype) !void {
75pub fn spawn(pool: *ThreadPool, comptime func: anytype, args: anytype) !void {
7576 if (builtin.single_threaded) {
7677 @call(.{}, func, args);
7778 return;
......@@ -98,41 +99,57 @@ pub fn spawn(self: *ThreadPool, comptime func: anytype, args: anytype) !void {
9899 };
99100
100101 {
101 self.mutex.lock();
102 defer self.mutex.unlock();
102 pool.mutex.lock();
103 defer pool.mutex.unlock();
103104
104 const closure = try self.allocator.create(Closure);
105 const closure = try pool.allocator.create(Closure);
105106 closure.* = .{
106107 .arguments = args,
107 .pool = self,
108 .pool = pool,
108109 };
109110
110 self.run_queue.prepend(&closure.run_node);
111 pool.run_queue.prepend(&closure.run_node);
111112 }
112113
113114 // Notify waiting threads outside the lock to try and keep the critical section small.
114 self.cond.signal();
115 pool.cond.signal();
115116}
116117
117fn worker(self: *ThreadPool) void {
118 self.mutex.lock();
119 defer self.mutex.unlock();
118fn worker(pool: *ThreadPool) void {
119 pool.mutex.lock();
120 defer pool.mutex.unlock();
120121
121122 while (true) {
122 while (self.run_queue.popFirst()) |run_node| {
123 while (pool.run_queue.popFirst()) |run_node| {
123124 // 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();
126127
127128 const runFn = run_node.data.runFn;
128129 runFn(&run_node.data);
129130 }
130131
131132 // 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);
134135 } else {
135136 break;
136137 }
137138 }
138139}
140
141pub 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 {
3737 self.state.store(0, .Monotonic);
3838 self.event.reset();
3939}
40
41pub 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 {
792792 }),
793793 }
794794 }
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
800797 const dirname = fs.path.dirname(full_out_path_z) orelse ".";
801798 break :blk try fs.path.join(arena, &.{ dirname, base.intermediary_basename.? });
802799 } else null;
src/link/Coff.zig+1-1
......@@ -1354,7 +1354,7 @@ fn linkWithLLD(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !
13541354 }
13551355 // MSVC compiler_rt is missing some stuff, so we build it unconditionally but
13561356 // 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| {
13581358 try argv.append(lib.full_object_path);
13591359 }
13601360 }
src/link/Elf.zig+1-1
......@@ -1272,7 +1272,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
12721272 const stack_size = self.base.options.stack_size_override orelse 16777216;
12731273 const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os;
12741274 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;
12761276 if (comp.compiler_rt_obj) |x| break :blk x.full_object_path;
12771277 break :blk null;
12781278 };
src/link/MachO.zig+24-26
......@@ -436,7 +436,7 @@ pub fn flush(self: *MachO, comp: *Compilation, prog_node: *std.Progress.Node) !v
436436 return error.TODOImplementWritingStaticLibFiles;
437437 }
438438 }
439 try self.flushModule(comp, prog_node);
439 return self.flushModule(comp, prog_node);
440440}
441441
442442pub 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
444444 defer tracy.end();
445445
446446 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();
449464
450465 var arena_allocator = std.heap.ArenaAllocator.init(self.base.allocator);
451466 defer arena_allocator.deinit();
......@@ -454,12 +469,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
454469 const directory = self.base.options.emit.?.directory; // Just an alias to make it shorter to type.
455470 const full_out_path = try directory.join(arena, &[_][]const u8{self.base.options.emit.?.sub_path});
456471
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
463472 // If there is no Zig code to compile, then we should skip flushing the output file because it
464473 // will not be part of the linker line anyway.
465474 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
482491
483492 const obj_basename = self.base.intermediary_basename orelse break :blk null;
484493
485 try self.flushObject(comp, prog_node);
486
487494 if (fs.path.dirname(full_out_path)) |dirname| {
488495 break :blk try fs.path.join(arena, &.{ dirname, obj_basename });
489496 } else {
......@@ -491,9 +498,11 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
491498 }
492499 } else null;
493500
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 }
497506
498507 const is_lib = self.base.options.output_mode == .Lib;
499508 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
738747 try positionals.append(p);
739748 }
740749
741 if (comp.compiler_rt_static_lib) |lib| {
750 if (comp.compiler_rt_lib) |lib| {
742751 try positionals.append(lib.full_object_path);
743752 }
744753
......@@ -1119,17 +1128,6 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
11191128 self.cold_start = false;
11201129}
11211130
1122pub 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
11331131fn resolveSearchDir(
11341132 arena: Allocator,
11351133 dir: []const u8,
src/link/Wasm.zig+1-1
......@@ -2255,7 +2255,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) !
22552255 const is_obj = self.base.options.output_mode == .Obj;
22562256
22572257 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
22592259 else
22602260 null;
22612261
src/musl.zig-1
......@@ -4,7 +4,6 @@ const mem = std.mem;
44const path = std.fs.path;
55const assert = std.debug.assert;
66
7const target_util = @import("target.zig");
87const Compilation = @import("Compilation.zig");
98const build_options = @import("build_options");
109