authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-15 23:09:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-17 16:38:59-07:00
logc99c085d70c9347ec9a15d9a4f73c19e628912b7
tree877b2d98b2611f8b4a1598f3c7b28e62f20ddd90
parent47c834e477657113bccaaad32e91148ff837f1a4

compiler-rt: break up functions even more

The purpose of this branch is to switch to using an object file for each independent function, in order to make linking simpler - instead of relying on `-ffunction-sections` and `--gc-sections`, which involves the linker doing the work of linking everything and then undoing work via garbage collection, this will allow the linker to only include the compilation units that are depended on in the first place. This commit makes progress towards that goal.

135 files changed, 4791 insertions(+), 4008 deletions(-)

CMakeLists.txt+92-9
......@@ -480,7 +480,14 @@ 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/addf3.zig"
484 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addsf3.zig"
485 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addtf3.zig"
486 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addxf3.zig"
487 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subdf3.zig"
488 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subsf3.zig"
489 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subtf3.zig"
490 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/subxf3.zig"
484491 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/addo.zig"
485492 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/arm.zig"
486493 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/atomics.zig"
......@@ -491,7 +498,18 @@ set(ZIG_STAGE2_SOURCES
491498 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/clear_cache.zig"
492499 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmp.zig"
493500 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/common.zig"
494 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/compareXf2.zig"
501 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/comparef.zig"
502 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmpsf2.zig"
503 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmpdf2.zig"
504 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmptf2.zig"
505 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cmpxf2.zig"
506 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/gesf2.zig"
507 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/gedf2.zig"
508 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/getf2.zig"
509 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/gexf2.zig"
510 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/unordsf2.zig"
511 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/unorddf2.zig"
512 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/unordtf2.zig"
495513 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/cos.zig"
496514 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/count0bits.zig"
497515 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/divdf3.zig"
......@@ -502,11 +520,79 @@ set(ZIG_STAGE2_SOURCES
502520 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/emutls.zig"
503521 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/exp.zig"
504522 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/exp2.zig"
505 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendXfYf2.zig"
506 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extend_f80.zig"
523 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendf.zig"
524 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extenddftf2.zig"
525 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extenddfxf2.zig"
526 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendhfsf2.zig"
527 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendhftf2.zig"
528 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendhfxf2.zig"
529 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendsfdf2.zig"
530 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendsftf2.zig"
531 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendsfxf2.zig"
532 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/extendxftf2.zig"
507533 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fabs.zig"
508 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixXfYi.zig"
509 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatXiYf.zig"
534 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/int_to_float.zig"
535 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsihf.zig"
536 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsisf.zig"
537 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsidf.zig"
538 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsitf.zig"
539 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatsixf.zig"
540 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdihf.zig"
541 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdisf.zig"
542 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdidf.zig"
543 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatditf.zig"
544 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatdixf.zig"
545 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattihf.zig"
546 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattisf.zig"
547 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattidf.zig"
548 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattitf.zig"
549 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floattixf.zig"
550 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundihf.zig"
551 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundisf.zig"
552 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundidf.zig"
553 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunditf.zig"
554 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatundixf.zig"
555 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsihf.zig"
556 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsisf.zig"
557 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsidf.zig"
558 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsitf.zig"
559 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatunsixf.zig"
560 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntihf.zig"
561 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntisf.zig"
562 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntidf.zig"
563 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntitf.zig"
564 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floatuntixf.zig"
565 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/float_to_int.zig"
566 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixhfsi.zig"
567 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixhfdi.zig"
568 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixhfti.zig"
569 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixsfsi.zig"
570 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixsfdi.zig"
571 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixsfti.zig"
572 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixdfsi.zig"
573 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixdfdi.zig"
574 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixdfti.zig"
575 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixtfsi.zig"
576 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixtfdi.zig"
577 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixtfti.zig"
578 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixxfsi.zig"
579 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixxfdi.zig"
580 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixxfti.zig"
581 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunshfsi.zig"
582 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunshfdi.zig"
583 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunshfti.zig"
584 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunssfsi.zig"
585 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunssfdi.zig"
586 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunssfti.zig"
587 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsdfsi.zig"
588 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsdfdi.zig"
589 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsdfti.zig"
590 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunstfsi.zig"
591 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunstfdi.zig"
592 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunstfti.zig"
593 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsxfsi.zig"
594 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsxfdi.zig"
595 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fixunsxfti.zig"
510596 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/floor.zig"
511597 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fma.zig"
512598 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/fmax.zig"
......@@ -517,7 +603,6 @@ set(ZIG_STAGE2_SOURCES
517603 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log10.zig"
518604 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log2.zig"
519605 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/modti3.zig"
520 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulXf3.zig"
521606 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/muldi3.zig"
522607 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulo.zig"
523608 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/multi3.zig"
......@@ -541,8 +626,6 @@ set(ZIG_STAGE2_SOURCES
541626 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/tan.zig"
542627 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trig.zig"
543628 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunc.zig"
544 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/truncXfYf2.zig"
545 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/trunc_f80.zig"
546629 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivmod.zig"
547630 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivmodti4.zig"
548631 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/udivti3.zig"
lib/compiler_rt.zig+127-20
......@@ -1,18 +1,59 @@
1const builtin = @import("builtin");
21pub const panic = @import("compiler_rt/common.zig").panic;
32
43comptime {
5 // TODO moving these around makes or breaks compilation of zig1.o for some reason
6 // Perhaps, until we switch to stage2, exports should be duplicated between this file
7 // and files included as a standalone units?
84 _ = @import("compiler_rt/atomics.zig");
9 _ = @import("compiler_rt/addXf3.zig");
10 _ = @import("compiler_rt/mulXf3.zig");
11 _ = @import("compiler_rt/compareXf2.zig");
12 _ = @import("compiler_rt/extendXfYf2.zig");
13 _ = @import("compiler_rt/extend_f80.zig");
14 _ = @import("compiler_rt/truncXfYf2.zig");
15 _ = @import("compiler_rt/trunc_f80.zig");
5
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
1657 _ = @import("compiler_rt/divtf3.zig");
1758 _ = @import("compiler_rt/divsf3.zig");
1859 _ = @import("compiler_rt/divdf3.zig");
......@@ -43,35 +84,101 @@ comptime {
4384 _ = @import("compiler_rt/udivti3.zig");
4485 _ = @import("compiler_rt/udivmodti4.zig");
4586 _ = @import("compiler_rt/umodti3.zig");
46 _ = @import("compiler_rt/floatXiYf.zig");
47 _ = @import("compiler_rt/fixXfYi.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
48152 _ = @import("compiler_rt/count0bits.zig");
49153 _ = @import("compiler_rt/parity.zig");
50154 _ = @import("compiler_rt/popcount.zig");
51155 _ = @import("compiler_rt/bswap.zig");
52156 _ = @import("compiler_rt/int.zig");
53157 _ = @import("compiler_rt/shift.zig");
158
54159 _ = @import("compiler_rt/negXi2.zig");
160
55161 _ = @import("compiler_rt/muldi3.zig");
162
56163 _ = @import("compiler_rt/absv.zig");
164 _ = @import("compiler_rt/absvsi2.zig");
165 _ = @import("compiler_rt/absvdi2.zig");
166 _ = @import("compiler_rt/absvti2.zig");
167
57168 _ = @import("compiler_rt/negv.zig");
58169 _ = @import("compiler_rt/addo.zig");
59170 _ = @import("compiler_rt/subo.zig");
60171 _ = @import("compiler_rt/mulo.zig");
61172 _ = @import("compiler_rt/cmp.zig");
173
62174 _ = @import("compiler_rt/negXf2.zig");
175
63176 _ = @import("compiler_rt/os_version_check.zig");
64177 _ = @import("compiler_rt/emutls.zig");
65178 _ = @import("compiler_rt/arm.zig");
66179 _ = @import("compiler_rt/aulldiv.zig");
67180 _ = @import("compiler_rt/aullrem.zig");
68 _ = @import("compiler_rt/sparc.zig");
69181 _ = @import("compiler_rt/clear_cache.zig");
70182
71 // missing: Floating point raised to integer power
72
73 // missing: Complex arithmetic
74 // (a + ib) * (c + id)
75 // (a + ib) / (c + id)
76
183 _ = @import("compiler_rt/sparc.zig");
77184}
lib/compiler_rt/absv.zig+3-27
......@@ -1,18 +1,6 @@
1// absv - absolute oVerflow
2// * @panic, if value can not be represented
3// - absvXi4_generic for unoptimized version
4const std = @import("std");
5const builtin = @import("builtin");
6const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
7pub const panic = @import("common.zig").panic;
8
9comptime {
10 @export(__absvsi2, .{ .name = "__absvsi2", .linkage = linkage });
11 @export(__absvdi2, .{ .name = "__absvdi2", .linkage = linkage });
12 @export(__absvti2, .{ .name = "__absvti2", .linkage = linkage });
13}
14
15inline 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 {
164 const UT = switch (ST) {
175 i32 => u32,
186 i64 => u64,
......@@ -31,18 +19,6 @@ inline fn absvXi(comptime ST: type, a: ST) ST {
3119 return x;
3220}
3321
34pub fn __absvsi2(a: i32) callconv(.C) i32 {
35 return absvXi(i32, a);
36}
37
38pub fn __absvdi2(a: i64) callconv(.C) i64 {
39 return absvXi(i64, a);
40}
41
42pub fn __absvti2(a: i128) callconv(.C) i128 {
43 return absvXi(i128, a);
44}
45
4622test {
4723 _ = @import("absvsi2_test.zig");
4824 _ = @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
10fn __absvdi2(a: i64) callconv(.C) i64 {
11 return absv(i64, a);
12}
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
10fn __absvsi2(a: i32) callconv(.C) i32 {
11 return absv(i32, a);
12}
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
10fn __absvti2(a: i128) callconv(.C) i128 {
11 return absv(i128, a);
12}
lib/compiler_rt/addXf3.zig deleted-271
......@@ -1,271 +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 builtin = @import("builtin");
7const math = std.math;
8const arch = builtin.cpu.arch;
9const is_test = builtin.is_test;
10const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
11
12const common = @import("common.zig");
13const normalize = common.normalize;
14pub const panic = common.panic;
15
16comptime {
17 @export(__addsf3, .{ .name = "__addsf3", .linkage = linkage });
18 @export(__adddf3, .{ .name = "__adddf3", .linkage = linkage });
19 @export(__addxf3, .{ .name = "__addxf3", .linkage = linkage });
20 @export(__addtf3, .{ .name = "__addtf3", .linkage = linkage });
21
22 @export(__subsf3, .{ .name = "__subsf3", .linkage = linkage });
23 @export(__subdf3, .{ .name = "__subdf3", .linkage = linkage });
24 @export(__subxf3, .{ .name = "__subxf3", .linkage = linkage });
25 @export(__subtf3, .{ .name = "__subtf3", .linkage = linkage });
26
27 if (!is_test) {
28 if (arch.isARM() or arch.isThumb()) {
29 @export(__aeabi_fadd, .{ .name = "__aeabi_fadd", .linkage = linkage });
30 @export(__aeabi_dadd, .{ .name = "__aeabi_dadd", .linkage = linkage });
31 @export(__aeabi_fsub, .{ .name = "__aeabi_fsub", .linkage = linkage });
32 @export(__aeabi_dsub, .{ .name = "__aeabi_dsub", .linkage = linkage });
33 }
34
35 if (arch.isPPC() or arch.isPPC64()) {
36 @export(__addkf3, .{ .name = "__addkf3", .linkage = linkage });
37 @export(__subkf3, .{ .name = "__subkf3", .linkage = linkage });
38 }
39 }
40}
41
42pub fn __addsf3(a: f32, b: f32) callconv(.C) f32 {
43 return addXf3(f32, a, b);
44}
45
46pub fn __adddf3(a: f64, b: f64) callconv(.C) f64 {
47 return addXf3(f64, a, b);
48}
49
50pub fn __addxf3(a: f80, b: f80) callconv(.C) f80 {
51 return addXf3(f80, a, b);
52}
53
54pub fn __subxf3(a: f80, b: f80) callconv(.C) f80 {
55 var b_rep = std.math.break_f80(b);
56 b_rep.exp ^= 0x8000;
57 return __addxf3(a, std.math.make_f80(b_rep));
58}
59
60pub fn __addtf3(a: f128, b: f128) callconv(.C) f128 {
61 return addXf3(f128, a, b);
62}
63
64pub fn __addkf3(a: f128, b: f128) callconv(.C) f128 {
65 return @call(.{ .modifier = .always_inline }, __addtf3, .{ a, b });
66}
67
68pub fn __subsf3(a: f32, b: f32) callconv(.C) f32 {
69 const neg_b = @bitCast(f32, @bitCast(u32, b) ^ (@as(u32, 1) << 31));
70 return addXf3(f32, a, neg_b);
71}
72
73pub fn __subdf3(a: f64, b: f64) callconv(.C) f64 {
74 const neg_b = @bitCast(f64, @bitCast(u64, b) ^ (@as(u64, 1) << 63));
75 return addXf3(f64, a, neg_b);
76}
77
78pub fn __subtf3(a: f128, b: f128) callconv(.C) f128 {
79 const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (@as(u128, 1) << 127));
80 return addXf3(f128, a, neg_b);
81}
82
83pub fn __subkf3(a: f128, b: f128) callconv(.C) f128 {
84 return @call(.{ .modifier = .always_inline }, __subtf3, .{ a, b });
85}
86
87pub fn __aeabi_fadd(a: f32, b: f32) callconv(.AAPCS) f32 {
88 @setRuntimeSafety(false);
89 return @call(.{ .modifier = .always_inline }, __addsf3, .{ a, b });
90}
91
92pub fn __aeabi_dadd(a: f64, b: f64) callconv(.AAPCS) f64 {
93 @setRuntimeSafety(false);
94 return @call(.{ .modifier = .always_inline }, __adddf3, .{ a, b });
95}
96
97pub fn __aeabi_fsub(a: f32, b: f32) callconv(.AAPCS) f32 {
98 @setRuntimeSafety(false);
99 return @call(.{ .modifier = .always_inline }, __subsf3, .{ a, b });
100}
101
102pub fn __aeabi_dsub(a: f64, b: f64) callconv(.AAPCS) f64 {
103 @setRuntimeSafety(false);
104 return @call(.{ .modifier = .always_inline }, __subdf3, .{ a, b });
105}
106
107// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
108pub fn addXf3(comptime T: type, a: T, b: T) T {
109 const bits = @typeInfo(T).Float.bits;
110 const Z = std.meta.Int(.unsigned, bits);
111 const S = std.meta.Int(.unsigned, bits - @clz(Z, @as(Z, bits) - 1));
112
113 const typeWidth = bits;
114 const significandBits = math.floatMantissaBits(T);
115 const fractionalBits = math.floatFractionalBits(T);
116 const exponentBits = math.floatExponentBits(T);
117
118 const signBit = (@as(Z, 1) << (significandBits + exponentBits));
119 const maxExponent = ((1 << exponentBits) - 1);
120
121 const integerBit = (@as(Z, 1) << fractionalBits);
122 const quietBit = integerBit >> 1;
123 const significandMask = (@as(Z, 1) << significandBits) - 1;
124
125 const absMask = signBit - 1;
126 const qnanRep = @bitCast(Z, math.nan(T)) | quietBit;
127
128 var aRep = @bitCast(Z, a);
129 var bRep = @bitCast(Z, b);
130 const aAbs = aRep & absMask;
131 const bAbs = bRep & absMask;
132
133 const infRep = @bitCast(Z, math.inf(T));
134
135 // Detect if a or b is zero, infinity, or NaN.
136 if (aAbs -% @as(Z, 1) >= infRep - @as(Z, 1) or
137 bAbs -% @as(Z, 1) >= infRep - @as(Z, 1))
138 {
139 // NaN + anything = qNaN
140 if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
141 // anything + NaN = qNaN
142 if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit);
143
144 if (aAbs == infRep) {
145 // +/-infinity + -/+infinity = qNaN
146 if ((@bitCast(Z, a) ^ @bitCast(Z, b)) == signBit) {
147 return @bitCast(T, qnanRep);
148 }
149 // +/-infinity + anything remaining = +/- infinity
150 else {
151 return a;
152 }
153 }
154
155 // anything remaining + +/-infinity = +/-infinity
156 if (bAbs == infRep) return b;
157
158 // zero + anything = anything
159 if (aAbs == 0) {
160 // but we need to get the sign right for zero + zero
161 if (bAbs == 0) {
162 return @bitCast(T, @bitCast(Z, a) & @bitCast(Z, b));
163 } else {
164 return b;
165 }
166 }
167
168 // anything + zero = anything
169 if (bAbs == 0) return a;
170 }
171
172 // Swap a and b if necessary so that a has the larger absolute value.
173 if (bAbs > aAbs) {
174 const temp = aRep;
175 aRep = bRep;
176 bRep = temp;
177 }
178
179 // Extract the exponent and significand from the (possibly swapped) a and b.
180 var aExponent = @intCast(i32, (aRep >> significandBits) & maxExponent);
181 var bExponent = @intCast(i32, (bRep >> significandBits) & maxExponent);
182 var aSignificand = aRep & significandMask;
183 var bSignificand = bRep & significandMask;
184
185 // Normalize any denormals, and adjust the exponent accordingly.
186 if (aExponent == 0) aExponent = normalize(T, &aSignificand);
187 if (bExponent == 0) bExponent = normalize(T, &bSignificand);
188
189 // The sign of the result is the sign of the larger operand, a. If they
190 // have opposite signs, we are performing a subtraction; otherwise addition.
191 const resultSign = aRep & signBit;
192 const subtraction = (aRep ^ bRep) & signBit != 0;
193
194 // Shift the significands to give us round, guard and sticky, and or in the
195 // implicit significand bit. (If we fell through from the denormal path it
196 // was already set by normalize( ), but setting it twice won't hurt
197 // anything.)
198 aSignificand = (aSignificand | integerBit) << 3;
199 bSignificand = (bSignificand | integerBit) << 3;
200
201 // Shift the significand of b by the difference in exponents, with a sticky
202 // bottom bit to get rounding correct.
203 const @"align" = @intCast(u32, aExponent - bExponent);
204 if (@"align" != 0) {
205 if (@"align" < typeWidth) {
206 const sticky = if (bSignificand << @intCast(S, typeWidth - @"align") != 0) @as(Z, 1) else 0;
207 bSignificand = (bSignificand >> @truncate(S, @"align")) | sticky;
208 } else {
209 bSignificand = 1; // sticky; b is known to be non-zero.
210 }
211 }
212 if (subtraction) {
213 aSignificand -= bSignificand;
214 // If a == -b, return +zero.
215 if (aSignificand == 0) return @bitCast(T, @as(Z, 0));
216
217 // If partial cancellation occured, we need to left-shift the result
218 // and adjust the exponent:
219 if (aSignificand < integerBit << 3) {
220 const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(std.meta.Int(.unsigned, bits), integerBit << 3));
221 aSignificand <<= @intCast(S, shift);
222 aExponent -= shift;
223 }
224 } else { // addition
225 aSignificand += bSignificand;
226
227 // If the addition carried up, we need to right-shift the result and
228 // adjust the exponent:
229 if (aSignificand & (integerBit << 4) != 0) {
230 const sticky = aSignificand & 1;
231 aSignificand = aSignificand >> 1 | sticky;
232 aExponent += 1;
233 }
234 }
235
236 // If we have overflowed the type, return +/- infinity:
237 if (aExponent >= maxExponent) return @bitCast(T, infRep | resultSign);
238
239 if (aExponent <= 0) {
240 // Result is denormal; the exponent and round/sticky bits are zero.
241 // All we need to do is shift the significand and apply the correct sign.
242 aSignificand >>= @intCast(S, 4 - aExponent);
243 return @bitCast(T, resultSign | aSignificand);
244 }
245
246 // Low three bits are round, guard, and sticky.
247 const roundGuardSticky = aSignificand & 0x7;
248
249 // Shift the significand into place, and mask off the integer bit, if it's implicit.
250 var result = (aSignificand >> 3) & significandMask;
251
252 // Insert the exponent and sign.
253 result |= @intCast(Z, aExponent) << significandBits;
254 result |= resultSign;
255
256 // Final rounding. The result may overflow to infinity, but that is the
257 // correct result in that case.
258 if (roundGuardSticky > 0x4) result += 1;
259 if (roundGuardSticky == 0x4) result += result & 1;
260
261 // Restore any explicit integer bit, if it was rounded off
262 if (significandBits != fractionalBits) {
263 if ((result >> significandBits) != 0) result |= integerBit;
264 }
265
266 return @bitCast(T, result);
267}
268
269test {
270 _ = @import("addXf3_test.zig");
271}
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+157
......@@ -0,0 +1,157 @@
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("addf3.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("addf3.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("addf3.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/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+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_ppc_abi) {
8 @export(__addkf3, .{ .name = "__addkf3", .linkage = common.linkage });
9 } else {
10 @export(__addtf3, .{ .name = "__addtf3", .linkage = common.linkage });
11 }
12}
13
14fn __addtf3(a: f128, b: f128) callconv(.C) f128 {
15 return addf3(f128, a, b);
16}
17
18fn __addkf3(a: f128, b: f128) callconv(.C) f128 {
19 return addf3(f128, a, b);
20}
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
10fn __addxf3(a: f80, b: f80) callconv(.C) f80 {
11 return addf3(f80, a, b);
12}
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."
34fn __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.
41fn __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.
48fn __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."
54fn __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."
34fn __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.
41fn __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.
48fn __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."
54fn __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+73
......@@ -0,0 +1,73 @@
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 {
15 @export(__eqtf2, .{ .name = "__eqtf2", .linkage = common.linkage });
16 @export(__netf2, .{ .name = "__netf2", .linkage = common.linkage });
17 @export(__letf2, .{ .name = "__letf2", .linkage = common.linkage });
18 @export(__cmptf2, .{ .name = "__cmptf2", .linkage = common.linkage });
19 @export(__lttf2, .{ .name = "__lttf2", .linkage = common.linkage });
20 }
21}
22
23/// "These functions calculate a <=> b. That is, if a is less than b, they return -1;
24/// if a is greater than b, they return 1; and if a and b are equal they return 0.
25/// If either argument is NaN they return 1..."
26///
27/// Note that this matches the definition of `__letf2`, `__eqtf2`, `__netf2`, `__cmptf2`,
28/// and `__lttf2`.
29fn __cmptf2(a: f128, b: f128) callconv(.C) i32 {
30 return @enumToInt(comparef.cmpf2(f128, comparef.LE, a, b));
31}
32
33/// "These functions return a value less than or equal to zero if neither argument is NaN,
34/// and a is less than or equal to b."
35fn __letf2(a: f128, b: f128) callconv(.C) i32 {
36 return __cmptf2(a, b);
37}
38
39/// "These functions return zero if neither argument is NaN, and a and b are equal."
40/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined
41/// to have the same return value.
42fn __eqtf2(a: f128, b: f128) callconv(.C) i32 {
43 return __cmptf2(a, b);
44}
45
46/// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal."
47/// Note that due to some kind of historical accident, __eqtf2 and __netf2 are defined
48/// to have the same return value.
49fn __netf2(a: f128, b: f128) callconv(.C) i32 {
50 return __cmptf2(a, b);
51}
52
53/// "These functions return a value less than zero if neither argument is NaN, and a
54/// is strictly less than b."
55fn __lttf2(a: f128, b: f128) callconv(.C) i32 {
56 return __cmptf2(a, b);
57}
58
59fn __eqkf2(a: f128, b: f128) callconv(.C) i32 {
60 return __cmptf2(a, b);
61}
62
63fn __nekf2(a: f128, b: f128) callconv(.C) i32 {
64 return __cmptf2(a, b);
65}
66
67fn __ltkf2(a: f128, b: f128) callconv(.C) i32 {
68 return __cmptf2(a, b);
69}
70
71fn __lekf2(a: f128, b: f128) callconv(.C) i32 {
72 return __cmptf2(a, b);
73}
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+17-10
......@@ -3,8 +3,14 @@ const builtin = @import("builtin");
33const math = std.math;
44const is_test = builtin.is_test;
55
6pub const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
7pub const want_aeabi = builtin.cpu.arch.isARM() or builtin.cpu.arch.isThumb();
8pub const want_ppc_abi = builtin.cpu.arch.isPPC() or builtin.cpu.arch.isPPC64();
9pub const want_msvc_abi = builtin.abi == .msvc;
10pub const want_gnu_abi = builtin.abi.isGnu();
11
612// Avoid dragging in the runtime safety mechanisms into this .o file,
7// unless we're trying to test this file.
13// unless we're trying to test compiler-rt.
814pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn {
915 _ = error_return_trace;
1016 @setCold(true);
......@@ -15,8 +21,13 @@ pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) nore
1521 }
1622}
1723
24/// AArch64 is the only ABI (at the moment) to support f16 arguments without the
25/// need for extending them to wider fp types.
26/// TODO remove this; do this type selection in the language rather than
27/// here in compiler-rt.
28pub const F16T = if (builtin.cpu.arch.isAARCH64()) f16 else u16;
29
1830pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
19 @setRuntimeSafety(is_test);
2031 switch (Z) {
2132 u16 => {
2233 // 16x16 --> 32 bit multiply
......@@ -130,15 +141,11 @@ pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
130141 }
131142}
132143
133// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
134144pub fn normalize(comptime T: type, significand: *std.meta.Int(.unsigned, @typeInfo(T).Float.bits)) i32 {
135 const bits = @typeInfo(T).Float.bits;
136 const Z = std.meta.Int(.unsigned, bits);
137 const S = std.meta.Int(.unsigned, bits - @clz(Z, @as(Z, bits) - 1));
138 const fractionalBits = math.floatFractionalBits(T);
139 const integerBit = @as(Z, 1) << fractionalBits;
145 const Z = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
146 const integerBit = @as(Z, 1) << std.math.floatFractionalBits(T);
140147
141 const shift = @clz(std.meta.Int(.unsigned, bits), significand.*) - @clz(Z, integerBit);
142 significand.* <<= @intCast(S, shift);
148 const shift = @clz(Z, significand.*) - @clz(Z, integerBit);
149 significand.* <<= @intCast(std.math.Log2Int(Z), shift);
143150 return @as(i32, 1) - shift;
144151}
lib/compiler_rt/compareXf2.zig deleted-440
......@@ -1,440 +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");
7const is_test = builtin.is_test;
8const arch = builtin.cpu.arch;
9const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
10pub const panic = @import("common.zig").panic;
11
12comptime {
13 @export(__lesf2, .{ .name = "__lesf2", .linkage = linkage });
14 @export(__ledf2, .{ .name = "__ledf2", .linkage = linkage });
15 @export(__letf2, .{ .name = "__letf2", .linkage = linkage });
16 @export(__lexf2, .{ .name = "__lexf2", .linkage = linkage });
17
18 @export(__gesf2, .{ .name = "__gesf2", .linkage = linkage });
19 @export(__gedf2, .{ .name = "__gedf2", .linkage = linkage });
20 @export(__getf2, .{ .name = "__getf2", .linkage = linkage });
21 @export(__gexf2, .{ .name = "__gexf2", .linkage = linkage });
22
23 @export(__eqsf2, .{ .name = "__eqsf2", .linkage = linkage });
24 @export(__eqdf2, .{ .name = "__eqdf2", .linkage = linkage });
25 @export(__eqxf2, .{ .name = "__eqxf2", .linkage = linkage });
26
27 @export(__ltsf2, .{ .name = "__ltsf2", .linkage = linkage });
28 @export(__ltdf2, .{ .name = "__ltdf2", .linkage = linkage });
29 @export(__ltxf2, .{ .name = "__ltxf2", .linkage = linkage });
30
31 @export(__nesf2, .{ .name = "__nesf2", .linkage = linkage });
32 @export(__nedf2, .{ .name = "__nedf2", .linkage = linkage });
33 @export(__nexf2, .{ .name = "__nexf2", .linkage = linkage });
34
35 @export(__gtsf2, .{ .name = "__gtsf2", .linkage = linkage });
36 @export(__gtdf2, .{ .name = "__gtdf2", .linkage = linkage });
37 @export(__gtxf2, .{ .name = "__gtxf2", .linkage = linkage });
38
39 @export(__unordsf2, .{ .name = "__unordsf2", .linkage = linkage });
40 @export(__unorddf2, .{ .name = "__unorddf2", .linkage = linkage });
41 @export(__unordtf2, .{ .name = "__unordtf2", .linkage = linkage });
42
43 if (!is_test) {
44 @export(__cmpsf2, .{ .name = "__cmpsf2", .linkage = linkage });
45 @export(__cmpdf2, .{ .name = "__cmpdf2", .linkage = linkage });
46 @export(__cmptf2, .{ .name = "__cmptf2", .linkage = linkage });
47 @export(__eqtf2, .{ .name = "__eqtf2", .linkage = linkage });
48 @export(__lttf2, .{ .name = "__lttf2", .linkage = linkage });
49 @export(__gttf2, .{ .name = "__gttf2", .linkage = linkage });
50 @export(__netf2, .{ .name = "__netf2", .linkage = linkage });
51
52 if (arch.isARM() or arch.isThumb()) {
53 @export(__aeabi_fcmpeq, .{ .name = "__aeabi_fcmpeq", .linkage = linkage });
54 @export(__aeabi_fcmplt, .{ .name = "__aeabi_fcmplt", .linkage = linkage });
55 @export(__aeabi_fcmple, .{ .name = "__aeabi_fcmple", .linkage = linkage });
56 @export(__aeabi_fcmpge, .{ .name = "__aeabi_fcmpge", .linkage = linkage });
57 @export(__aeabi_fcmpgt, .{ .name = "__aeabi_fcmpgt", .linkage = linkage });
58 @export(__aeabi_fcmpun, .{ .name = "__aeabi_fcmpun", .linkage = linkage });
59
60 @export(__aeabi_dcmpeq, .{ .name = "__aeabi_dcmpeq", .linkage = linkage });
61 @export(__aeabi_dcmplt, .{ .name = "__aeabi_dcmplt", .linkage = linkage });
62 @export(__aeabi_dcmple, .{ .name = "__aeabi_dcmple", .linkage = linkage });
63 @export(__aeabi_dcmpge, .{ .name = "__aeabi_dcmpge", .linkage = linkage });
64 @export(__aeabi_dcmpgt, .{ .name = "__aeabi_dcmpgt", .linkage = linkage });
65 @export(__aeabi_dcmpun, .{ .name = "__aeabi_dcmpun", .linkage = linkage });
66 }
67
68 if (arch.isPPC() or arch.isPPC64()) {
69 @export(__eqkf2, .{ .name = "__eqkf2", .linkage = linkage });
70 @export(__nekf2, .{ .name = "__nekf2", .linkage = linkage });
71 @export(__gekf2, .{ .name = "__gekf2", .linkage = linkage });
72 @export(__ltkf2, .{ .name = "__ltkf2", .linkage = linkage });
73 @export(__lekf2, .{ .name = "__lekf2", .linkage = linkage });
74 @export(__gtkf2, .{ .name = "__gtkf2", .linkage = linkage });
75 @export(__unordkf2, .{ .name = "__unordkf2", .linkage = linkage });
76 }
77 }
78}
79
80const LE = enum(i32) {
81 Less = -1,
82 Equal = 0,
83 Greater = 1,
84
85 const Unordered: LE = .Greater;
86};
87
88const GE = enum(i32) {
89 Less = -1,
90 Equal = 0,
91 Greater = 1,
92
93 const Unordered: GE = .Less;
94};
95
96pub inline fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {
97 @setRuntimeSafety(builtin.is_test);
98
99 const bits = @typeInfo(T).Float.bits;
100 const srep_t = std.meta.Int(.signed, bits);
101 const rep_t = std.meta.Int(.unsigned, 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 infT = comptime std.math.inf(T);
108 const infRep = @bitCast(rep_t, infT);
109
110 const aInt = @bitCast(srep_t, a);
111 const bInt = @bitCast(srep_t, b);
112 const aAbs = @bitCast(rep_t, aInt) & absMask;
113 const bAbs = @bitCast(rep_t, bInt) & absMask;
114
115 // If either a or b is NaN, they are unordered.
116 if (aAbs > infRep or bAbs > infRep) return RT.Unordered;
117
118 // If a and b are both zeros, they are equal.
119 if ((aAbs | bAbs) == 0) return .Equal;
120
121 // If at least one of a and b is positive, we get the same result comparing
122 // a and b as signed integers as we would with a floating-point compare.
123 if ((aInt & bInt) >= 0) {
124 if (aInt < bInt) {
125 return .Less;
126 } else if (aInt == bInt) {
127 return .Equal;
128 } else return .Greater;
129 } else {
130 // Otherwise, both are negative, so we need to flip the sense of the
131 // comparison to get the correct result. (This assumes a twos- or ones-
132 // complement integer representation; if integers are represented in a
133 // sign-magnitude representation, then this flip is incorrect).
134 if (aInt > bInt) {
135 return .Less;
136 } else if (aInt == bInt) {
137 return .Equal;
138 } else return .Greater;
139 }
140}
141
142pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 {
143 @setRuntimeSafety(builtin.is_test);
144
145 const rep_t = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
146
147 const significandBits = std.math.floatMantissaBits(T);
148 const exponentBits = std.math.floatExponentBits(T);
149 const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
150 const absMask = signBit - 1;
151 const infRep = @bitCast(rep_t, std.math.inf(T));
152
153 const aAbs: rep_t = @bitCast(rep_t, a) & absMask;
154 const bAbs: rep_t = @bitCast(rep_t, b) & absMask;
155
156 return @boolToInt(aAbs > infRep or bAbs > infRep);
157}
158
159// Comparison between f32
160
161pub fn __lesf2(a: f32, b: f32) callconv(.C) i32 {
162 @setRuntimeSafety(builtin.is_test);
163 const float = cmp(f32, LE, a, b);
164 return @bitCast(i32, float);
165}
166
167pub fn __gesf2(a: f32, b: f32) callconv(.C) i32 {
168 @setRuntimeSafety(builtin.is_test);
169 const float = cmp(f32, GE, a, b);
170 return @bitCast(i32, float);
171}
172
173pub fn __cmpsf2(a: f32, b: f32) callconv(.C) i32 {
174 return @call(.{ .modifier = .always_inline }, __lesf2, .{ a, b });
175}
176
177pub fn __eqsf2(a: f32, b: f32) callconv(.C) i32 {
178 return @call(.{ .modifier = .always_inline }, __lesf2, .{ a, b });
179}
180
181pub fn __ltsf2(a: f32, b: f32) callconv(.C) i32 {
182 return @call(.{ .modifier = .always_inline }, __lesf2, .{ a, b });
183}
184
185pub fn __nesf2(a: f32, b: f32) callconv(.C) i32 {
186 return @call(.{ .modifier = .always_inline }, __lesf2, .{ a, b });
187}
188
189pub fn __gtsf2(a: f32, b: f32) callconv(.C) i32 {
190 return @call(.{ .modifier = .always_inline }, __gesf2, .{ a, b });
191}
192
193// Comparison between f64
194
195pub fn __ledf2(a: f64, b: f64) callconv(.C) i32 {
196 @setRuntimeSafety(builtin.is_test);
197 const float = cmp(f64, LE, a, b);
198 return @bitCast(i32, float);
199}
200
201pub fn __gedf2(a: f64, b: f64) callconv(.C) i32 {
202 @setRuntimeSafety(builtin.is_test);
203 const float = cmp(f64, GE, a, b);
204 return @bitCast(i32, float);
205}
206
207pub fn __cmpdf2(a: f64, b: f64) callconv(.C) i32 {
208 return @call(.{ .modifier = .always_inline }, __ledf2, .{ a, b });
209}
210
211pub fn __eqdf2(a: f64, b: f64) callconv(.C) i32 {
212 return @call(.{ .modifier = .always_inline }, __ledf2, .{ a, b });
213}
214
215pub fn __ltdf2(a: f64, b: f64) callconv(.C) i32 {
216 return @call(.{ .modifier = .always_inline }, __ledf2, .{ a, b });
217}
218
219pub fn __nedf2(a: f64, b: f64) callconv(.C) i32 {
220 return @call(.{ .modifier = .always_inline }, __ledf2, .{ a, b });
221}
222
223pub fn __gtdf2(a: f64, b: f64) callconv(.C) i32 {
224 return @call(.{ .modifier = .always_inline }, __gedf2, .{ a, b });
225}
226
227// Comparison between f80
228
229pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT {
230 const a_rep = std.math.break_f80(a);
231 const b_rep = std.math.break_f80(b);
232 const sig_bits = std.math.floatMantissaBits(f80);
233 const int_bit = 0x8000000000000000;
234 const sign_bit = 0x8000;
235 const special_exp = 0x7FFF;
236
237 // If either a or b is NaN, they are unordered.
238 if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or
239 (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0))
240 return RT.Unordered;
241
242 // If a and b are both zeros, they are equal.
243 if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0)
244 return .Equal;
245
246 if (@boolToInt(a_rep.exp == b_rep.exp) & @boolToInt(a_rep.fraction == b_rep.fraction) != 0) {
247 return .Equal;
248 } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) {
249 // signs are different
250 if (@bitCast(i16, a_rep.exp) < @bitCast(i16, b_rep.exp)) {
251 return .Less;
252 } else {
253 return .Greater;
254 }
255 } else {
256 const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits);
257 const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits);
258 if (a_fraction < b_fraction) {
259 return .Less;
260 } else {
261 return .Greater;
262 }
263 }
264}
265
266pub fn __lexf2(a: f80, b: f80) callconv(.C) i32 {
267 @setRuntimeSafety(builtin.is_test);
268 const float = cmp_f80(LE, a, b);
269 return @bitCast(i32, float);
270}
271
272pub fn __gexf2(a: f80, b: f80) callconv(.C) i32 {
273 @setRuntimeSafety(builtin.is_test);
274 const float = cmp_f80(GE, a, b);
275 return @bitCast(i32, float);
276}
277
278pub fn __eqxf2(a: f80, b: f80) callconv(.C) i32 {
279 return @call(.{ .modifier = .always_inline }, __lexf2, .{ a, b });
280}
281
282pub fn __ltxf2(a: f80, b: f80) callconv(.C) i32 {
283 return @call(.{ .modifier = .always_inline }, __lexf2, .{ a, b });
284}
285
286pub fn __nexf2(a: f80, b: f80) callconv(.C) i32 {
287 return @call(.{ .modifier = .always_inline }, __lexf2, .{ a, b });
288}
289
290pub fn __gtxf2(a: f80, b: f80) callconv(.C) i32 {
291 return @call(.{ .modifier = .always_inline }, __gexf2, .{ a, b });
292}
293
294// Comparison between f128
295
296pub fn __letf2(a: f128, b: f128) callconv(.C) i32 {
297 @setRuntimeSafety(builtin.is_test);
298 const float = cmp(f128, LE, a, b);
299 return @bitCast(i32, float);
300}
301
302pub fn __getf2(a: f128, b: f128) callconv(.C) i32 {
303 @setRuntimeSafety(builtin.is_test);
304 const float = cmp(f128, GE, a, b);
305 return @bitCast(i32, float);
306}
307
308pub fn __cmptf2(a: f128, b: f128) callconv(.C) i32 {
309 return @call(.{ .modifier = .always_inline }, __letf2, .{ a, b });
310}
311
312pub fn __eqtf2(a: f128, b: f128) callconv(.C) i32 {
313 return @call(.{ .modifier = .always_inline }, __letf2, .{ a, b });
314}
315
316pub fn __lttf2(a: f128, b: f128) callconv(.C) i32 {
317 return @call(.{ .modifier = .always_inline }, __letf2, .{ a, b });
318}
319
320pub fn __netf2(a: f128, b: f128) callconv(.C) i32 {
321 return @call(.{ .modifier = .always_inline }, __letf2, .{ a, b });
322}
323
324pub fn __gttf2(a: f128, b: f128) callconv(.C) i32 {
325 return @call(.{ .modifier = .always_inline }, __getf2, .{ a, b });
326}
327
328pub fn __eqkf2(a: f128, b: f128) callconv(.C) i32 {
329 return @call(.{ .modifier = .always_inline }, __letf2, .{ a, b });
330}
331
332pub fn __nekf2(a: f128, b: f128) callconv(.C) i32 {
333 return @call(.{ .modifier = .always_inline }, __letf2, .{ a, b });
334}
335
336pub fn __gekf2(a: f128, b: f128) callconv(.C) i32 {
337 return @call(.{ .modifier = .always_inline }, __getf2, .{ a, b });
338}
339
340pub fn __ltkf2(a: f128, b: f128) callconv(.C) i32 {
341 return @call(.{ .modifier = .always_inline }, __letf2, .{ a, b });
342}
343
344pub fn __lekf2(a: f128, b: f128) callconv(.C) i32 {
345 return @call(.{ .modifier = .always_inline }, __letf2, .{ a, b });
346}
347
348pub fn __gtkf2(a: f128, b: f128) callconv(.C) i32 {
349 return @call(.{ .modifier = .always_inline }, __getf2, .{ a, b });
350}
351
352// Unordered comparison between f32/f64/f128
353
354pub fn __unordsf2(a: f32, b: f32) callconv(.C) i32 {
355 @setRuntimeSafety(builtin.is_test);
356 return unordcmp(f32, a, b);
357}
358
359pub fn __unorddf2(a: f64, b: f64) callconv(.C) i32 {
360 @setRuntimeSafety(builtin.is_test);
361 return unordcmp(f64, a, b);
362}
363
364pub fn __unordtf2(a: f128, b: f128) callconv(.C) i32 {
365 @setRuntimeSafety(builtin.is_test);
366 return unordcmp(f128, a, b);
367}
368
369pub fn __unordkf2(a: f128, b: f128) callconv(.C) i32 {
370 return @call(.{ .modifier = .always_inline }, __unordtf2, .{ a, b });
371}
372
373// ARM EABI intrinsics
374
375pub fn __aeabi_fcmpeq(a: f32, b: f32) callconv(.AAPCS) i32 {
376 @setRuntimeSafety(false);
377 return @boolToInt(@call(.{ .modifier = .always_inline }, __eqsf2, .{ a, b }) == 0);
378}
379
380pub fn __aeabi_fcmplt(a: f32, b: f32) callconv(.AAPCS) i32 {
381 @setRuntimeSafety(false);
382 return @boolToInt(@call(.{ .modifier = .always_inline }, __ltsf2, .{ a, b }) < 0);
383}
384
385pub fn __aeabi_fcmple(a: f32, b: f32) callconv(.AAPCS) i32 {
386 @setRuntimeSafety(false);
387 return @boolToInt(@call(.{ .modifier = .always_inline }, __lesf2, .{ a, b }) <= 0);
388}
389
390pub fn __aeabi_fcmpge(a: f32, b: f32) callconv(.AAPCS) i32 {
391 @setRuntimeSafety(false);
392 return @boolToInt(@call(.{ .modifier = .always_inline }, __gesf2, .{ a, b }) >= 0);
393}
394
395pub fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.AAPCS) i32 {
396 @setRuntimeSafety(false);
397 return @boolToInt(@call(.{ .modifier = .always_inline }, __gtsf2, .{ a, b }) > 0);
398}
399
400pub fn __aeabi_fcmpun(a: f32, b: f32) callconv(.AAPCS) i32 {
401 @setRuntimeSafety(false);
402 return @call(.{ .modifier = .always_inline }, __unordsf2, .{ a, b });
403}
404
405pub fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.AAPCS) i32 {
406 @setRuntimeSafety(false);
407 return @boolToInt(@call(.{ .modifier = .always_inline }, __eqdf2, .{ a, b }) == 0);
408}
409
410pub fn __aeabi_dcmplt(a: f64, b: f64) callconv(.AAPCS) i32 {
411 @setRuntimeSafety(false);
412 return @boolToInt(@call(.{ .modifier = .always_inline }, __ltdf2, .{ a, b }) < 0);
413}
414
415pub fn __aeabi_dcmple(a: f64, b: f64) callconv(.AAPCS) i32 {
416 @setRuntimeSafety(false);
417 return @boolToInt(@call(.{ .modifier = .always_inline }, __ledf2, .{ a, b }) <= 0);
418}
419
420pub fn __aeabi_dcmpge(a: f64, b: f64) callconv(.AAPCS) i32 {
421 @setRuntimeSafety(false);
422 return @boolToInt(@call(.{ .modifier = .always_inline }, __gedf2, .{ a, b }) >= 0);
423}
424
425pub fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.AAPCS) i32 {
426 @setRuntimeSafety(false);
427 return @boolToInt(@call(.{ .modifier = .always_inline }, __gtdf2, .{ a, b }) > 0);
428}
429
430pub fn __aeabi_dcmpun(a: f64, b: f64) callconv(.AAPCS) i32 {
431 @setRuntimeSafety(false);
432 return @call(.{ .modifier = .always_inline }, __unorddf2, .{ a, b });
433}
434
435test "comparesf2" {
436 _ = @import("comparesf2_test.zig");
437}
438test "comparedf2" {
439 _ = @import("comparedf2_test.zig");
440}
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/extendXfYf2.zig deleted-148
......@@ -1,148 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const arch = builtin.cpu.arch;
5const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
6pub const panic = @import("common.zig").panic;
7
8comptime {
9 @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });
10 @export(__extendsftf2, .{ .name = "__extendsftf2", .linkage = linkage });
11 @export(__extendhfsf2, .{ .name = "__extendhfsf2", .linkage = linkage });
12 @export(__extendhftf2, .{ .name = "__extendhftf2", .linkage = linkage });
13 @export(__extendsfdf2, .{ .name = "__extendsfdf2", .linkage = linkage });
14
15 if (!is_test) {
16 @export(__gnu_h2f_ieee, .{ .name = "__gnu_h2f_ieee", .linkage = linkage });
17
18 if (arch.isARM() or arch.isThumb()) {
19 @export(__aeabi_f2d, .{ .name = "__aeabi_f2d", .linkage = linkage });
20 @export(__aeabi_h2f, .{ .name = "__aeabi_h2f", .linkage = linkage });
21 }
22
23 if (arch.isPPC() or arch.isPPC64()) {
24 @export(__extendsfkf2, .{ .name = "__extendsfkf2", .linkage = linkage });
25 @export(__extenddfkf2, .{ .name = "__extenddfkf2", .linkage = linkage });
26 }
27 }
28}
29
30pub fn __extendsfdf2(a: f32) callconv(.C) f64 {
31 return extendXfYf2(f64, f32, @bitCast(u32, a));
32}
33
34pub fn __extenddftf2(a: f64) callconv(.C) f128 {
35 return extendXfYf2(f128, f64, @bitCast(u64, a));
36}
37
38pub fn __extenddfkf2(a: f64) callconv(.C) f128 {
39 return @call(.{ .modifier = .always_inline }, __extenddftf2, .{a});
40}
41
42pub fn __extendsftf2(a: f32) callconv(.C) f128 {
43 return extendXfYf2(f128, f32, @bitCast(u32, a));
44}
45
46pub fn __extendsfkf2(a: f32) callconv(.C) f128 {
47 return @call(.{ .modifier = .always_inline }, __extendsftf2, .{a});
48}
49
50// AArch64 is the only ABI (at the moment) to support f16 arguments without the
51// need for extending them to wider fp types.
52pub const F16T = if (arch.isAARCH64()) f16 else u16;
53
54pub fn __extendhfsf2(a: F16T) callconv(.C) f32 {
55 return extendXfYf2(f32, f16, @bitCast(u16, a));
56}
57
58pub fn __gnu_h2f_ieee(a: F16T) callconv(.C) f32 {
59 return @call(.{ .modifier = .always_inline }, __extendhfsf2, .{a});
60}
61
62pub fn __extendhftf2(a: F16T) callconv(.C) f128 {
63 return extendXfYf2(f128, f16, @bitCast(u16, a));
64}
65
66pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 {
67 @setRuntimeSafety(false);
68 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, arg });
69}
70
71pub fn __aeabi_f2d(arg: f32) callconv(.AAPCS) f64 {
72 @setRuntimeSafety(false);
73 return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f64, f32, @bitCast(u32, arg) });
74}
75
76inline fn extendXfYf2(comptime dst_t: type, comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) dst_t {
77 @setRuntimeSafety(builtin.is_test);
78
79 const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits);
80 const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits);
81 const srcSigBits = std.math.floatMantissaBits(src_t);
82 const dstSigBits = std.math.floatMantissaBits(dst_t);
83 const DstShift = std.math.Log2Int(dst_rep_t);
84
85 // Various constants whose values follow from the type parameters.
86 // Any reasonable optimizer will fold and propagate all of these.
87 const srcBits = @bitSizeOf(src_t);
88 const srcExpBits = srcBits - srcSigBits - 1;
89 const srcInfExp = (1 << srcExpBits) - 1;
90 const srcExpBias = srcInfExp >> 1;
91
92 const srcMinNormal = 1 << srcSigBits;
93 const srcInfinity = srcInfExp << srcSigBits;
94 const srcSignMask = 1 << (srcSigBits + srcExpBits);
95 const srcAbsMask = srcSignMask - 1;
96 const srcQNaN = 1 << (srcSigBits - 1);
97 const srcNaNCode = srcQNaN - 1;
98
99 const dstBits = @bitSizeOf(dst_t);
100 const dstExpBits = dstBits - dstSigBits - 1;
101 const dstInfExp = (1 << dstExpBits) - 1;
102 const dstExpBias = dstInfExp >> 1;
103
104 const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits;
105
106 // Break a into a sign and representation of the absolute value
107 const aRep: src_rep_t = @bitCast(src_rep_t, a);
108 const aAbs: src_rep_t = aRep & srcAbsMask;
109 const sign: src_rep_t = aRep & srcSignMask;
110 var absResult: dst_rep_t = undefined;
111
112 if (aAbs -% srcMinNormal < srcInfinity - srcMinNormal) {
113 // a is a normal number.
114 // Extend to the destination type by shifting the significand and
115 // exponent into the proper position and rebiasing the exponent.
116 absResult = @as(dst_rep_t, aAbs) << (dstSigBits - srcSigBits);
117 absResult += (dstExpBias - srcExpBias) << dstSigBits;
118 } else if (aAbs >= srcInfinity) {
119 // a is NaN or infinity.
120 // Conjure the result by beginning with infinity, then setting the qNaN
121 // bit (if needed) and right-aligning the rest of the trailing NaN
122 // payload field.
123 absResult = dstInfExp << dstSigBits;
124 absResult |= @as(dst_rep_t, aAbs & srcQNaN) << (dstSigBits - srcSigBits);
125 absResult |= @as(dst_rep_t, aAbs & srcNaNCode) << (dstSigBits - srcSigBits);
126 } else if (aAbs != 0) {
127 // a is denormal.
128 // renormalize the significand and clear the leading bit, then insert
129 // the correct adjusted exponent in the destination type.
130 const scale: u32 = @clz(src_rep_t, aAbs) -
131 @clz(src_rep_t, @as(src_rep_t, srcMinNormal));
132 absResult = @as(dst_rep_t, aAbs) << @intCast(DstShift, dstSigBits - srcSigBits + scale);
133 absResult ^= dstMinNormal;
134 const resultExponent: u32 = dstExpBias - srcExpBias - scale + 1;
135 absResult |= @intCast(dst_rep_t, resultExponent) << dstSigBits;
136 } else {
137 // a is zero.
138 absResult = 0;
139 }
140
141 // Apply the signbit to (dst_t)abs(a).
142 const result: dst_rep_t align(@alignOf(dst_t)) = absResult | @as(dst_rep_t, sign) << (dstBits - srcBits);
143 return @bitCast(dst_t, result);
144}
145
146test {
147 _ = @import("extendXfYf2_test.zig");
148}
lib/compiler_rt/extend_f80.zig deleted-140
......@@ -1,140 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const is_test = builtin.is_test;
4const arch = builtin.cpu.arch;
5const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
6pub const panic = @import("common.zig").panic;
7
8comptime {
9 @export(__extendhfxf2, .{ .name = "__extendhfxf2", .linkage = linkage });
10 @export(__extendsfxf2, .{ .name = "__extendsfxf2", .linkage = linkage });
11 @export(__extenddfxf2, .{ .name = "__extenddfxf2", .linkage = linkage });
12 @export(__extendxftf2, .{ .name = "__extendxftf2", .linkage = linkage });
13}
14
15// AArch64 is the only ABI (at the moment) to support f16 arguments without the
16// need for extending them to wider fp types.
17const F16T = if (arch.isAARCH64()) f16 else u16;
18
19fn __extendhfxf2(a: F16T) callconv(.C) f80 {
20 return extendF80(f16, @bitCast(u16, a));
21}
22
23fn __extendsfxf2(a: f32) callconv(.C) f80 {
24 return extendF80(f32, @bitCast(u32, a));
25}
26
27fn __extenddfxf2(a: f64) callconv(.C) f80 {
28 return extendF80(f64, @bitCast(u64, a));
29}
30
31inline fn extendF80(comptime src_t: type, a: std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits)) f80 {
32 @setRuntimeSafety(builtin.is_test);
33
34 const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits);
35 const src_sig_bits = std.math.floatMantissaBits(src_t);
36 const dst_int_bit = 0x8000000000000000;
37 const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
38
39 const dst_exp_bias = 16383;
40
41 const src_bits = @bitSizeOf(src_t);
42 const src_exp_bits = src_bits - src_sig_bits - 1;
43 const src_inf_exp = (1 << src_exp_bits) - 1;
44 const src_exp_bias = src_inf_exp >> 1;
45
46 const src_min_normal = 1 << src_sig_bits;
47 const src_inf = src_inf_exp << src_sig_bits;
48 const src_sign_mask = 1 << (src_sig_bits + src_exp_bits);
49 const src_abs_mask = src_sign_mask - 1;
50 const src_qnan = 1 << (src_sig_bits - 1);
51 const src_nan_code = src_qnan - 1;
52
53 var dst: std.math.F80 = undefined;
54
55 // Break a into a sign and representation of the absolute value
56 const a_abs = a & src_abs_mask;
57 const sign: u16 = if (a & src_sign_mask != 0) 0x8000 else 0;
58
59 if (a_abs -% src_min_normal < src_inf - src_min_normal) {
60 // a is a normal number.
61 // Extend to the destination type by shifting the significand and
62 // exponent into the proper position and rebiasing the exponent.
63 dst.exp = @intCast(u16, a_abs >> src_sig_bits);
64 dst.exp += dst_exp_bias - src_exp_bias;
65 dst.fraction = @as(u64, a_abs) << (dst_sig_bits - src_sig_bits);
66 dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers
67 } else if (a_abs >= src_inf) {
68 // a is NaN or infinity.
69 // Conjure the result by beginning with infinity, then setting the qNaN
70 // bit (if needed) and right-aligning the rest of the trailing NaN
71 // payload field.
72 dst.exp = 0x7fff;
73 dst.fraction = dst_int_bit;
74 dst.fraction |= @as(u64, a_abs & src_qnan) << (dst_sig_bits - src_sig_bits);
75 dst.fraction |= @as(u64, a_abs & src_nan_code) << (dst_sig_bits - src_sig_bits);
76 } else if (a_abs != 0) {
77 // a is denormal.
78 // renormalize the significand and clear the leading bit, then insert
79 // the correct adjusted exponent in the destination type.
80 const scale: u16 = @clz(src_rep_t, a_abs) -
81 @clz(src_rep_t, @as(src_rep_t, src_min_normal));
82
83 dst.fraction = @as(u64, a_abs) << @intCast(u6, dst_sig_bits - src_sig_bits + scale);
84 dst.fraction |= dst_int_bit; // bit 64 is always set for normal numbers
85 dst.exp = @truncate(u16, a_abs >> @intCast(u4, src_sig_bits - scale));
86 dst.exp ^= 1;
87 dst.exp |= dst_exp_bias - src_exp_bias - scale + 1;
88 } else {
89 // a is zero.
90 dst.exp = 0;
91 dst.fraction = 0;
92 }
93
94 dst.exp |= sign;
95 return std.math.make_f80(dst);
96}
97
98fn __extendxftf2(a: f80) callconv(.C) f128 {
99 @setRuntimeSafety(builtin.is_test);
100
101 const src_int_bit: u64 = 0x8000000000000000;
102 const src_sig_mask = ~src_int_bit;
103 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
104 const dst_sig_bits = std.math.floatMantissaBits(f128);
105
106 const dst_bits = @bitSizeOf(f128);
107
108 const dst_min_normal = @as(u128, 1) << dst_sig_bits;
109
110 // Break a into a sign and representation of the absolute value
111 var a_rep = std.math.break_f80(a);
112 const sign = a_rep.exp & 0x8000;
113 a_rep.exp &= 0x7FFF;
114 var abs_result: u128 = undefined;
115
116 if (a_rep.exp == 0 and a_rep.fraction == 0) {
117 // zero
118 abs_result = 0;
119 } else if (a_rep.exp == 0x7FFF) {
120 // a is nan or infinite
121 abs_result = @as(u128, a_rep.fraction) << (dst_sig_bits - src_sig_bits);
122 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
123 } else if (a_rep.fraction & src_int_bit != 0) {
124 // a is a normal value
125 abs_result = @as(u128, a_rep.fraction & src_sig_mask) << (dst_sig_bits - src_sig_bits);
126 abs_result |= @as(u128, a_rep.exp) << dst_sig_bits;
127 } else {
128 // a is denormal
129 // renormalize the significand and clear the leading bit and integer part,
130 // then insert the correct adjusted exponent in the destination type.
131 const scale: u32 = @clz(u64, a_rep.fraction);
132 abs_result = @as(u128, a_rep.fraction) << @intCast(u7, dst_sig_bits - src_sig_bits + scale + 1);
133 abs_result ^= dst_min_normal;
134 abs_result |= @as(u128, scale + 1) << dst_sig_bits;
135 }
136
137 // Apply the signbit to (dst_t)abs(a).
138 const result: u128 align(@alignOf(f128)) = abs_result | @as(u128, sign) << (dst_bits - 16);
139 return @bitCast(f128, result);
140}
lib/compiler_rt/extenddftf2.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_ppc_abi) {
8 @export(__extenddfkf2, .{ .name = "__extenddfkf2", .linkage = common.linkage });
9 } else {
10 @export(__extenddftf2, .{ .name = "__extenddftf2", .linkage = common.linkage });
11 }
12}
13
14fn __extenddftf2(a: f64) callconv(.C) f128 {
15 return extendf(f128, f64, @bitCast(u64, a));
16}
17
18fn __extenddfkf2(a: f64) callconv(.C) f128 {
19 return extendf(f128, f64, @bitCast(u64, a));
20}
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("extendXfYf2_test.zig");
142}
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.want_gnu_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
16fn __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
10fn __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+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_ppc_abi) {
8 @export(__extendsfkf2, .{ .name = "__extendsfkf2", .linkage = common.linkage });
9 } else {
10 @export(__extendsftf2, .{ .name = "__extendsftf2", .linkage = common.linkage });
11 }
12}
13
14fn __extendsftf2(a: f32) callconv(.C) f128 {
15 return extendf(f128, f32, @bitCast(u32, a));
16}
17
18fn __extendsfkf2(a: f32) callconv(.C) f128 {
19 return extendf(f128, f32, @bitCast(u32, a));
20}
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/fixXfYi.zig deleted-312
......@@ -1,312 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const math = std.math;
4const Log2Int = math.Log2Int;
5const arch = builtin.cpu.arch;
6const is_test = builtin.is_test;
7const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
8pub const panic = @import("common.zig").panic;
9
10comptime {
11 // Float -> Integral Conversion
12
13 // Conversion from f32
14 @export(__fixsfsi, .{ .name = "__fixsfsi", .linkage = linkage });
15 @export(__fixunssfsi, .{ .name = "__fixunssfsi", .linkage = linkage });
16
17 @export(__fixsfdi, .{ .name = "__fixsfdi", .linkage = linkage });
18 @export(__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = linkage });
19
20 @export(__fixsfti, .{ .name = "__fixsfti", .linkage = linkage });
21 @export(__fixunssfti, .{ .name = "__fixunssfti", .linkage = linkage });
22
23 // Conversion from f64
24 @export(__fixdfsi, .{ .name = "__fixdfsi", .linkage = linkage });
25 @export(__fixunsdfsi, .{ .name = "__fixunsdfsi", .linkage = linkage });
26
27 @export(__fixdfdi, .{ .name = "__fixdfdi", .linkage = linkage });
28 @export(__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = linkage });
29
30 @export(__fixdfti, .{ .name = "__fixdfti", .linkage = linkage });
31 @export(__fixunsdfti, .{ .name = "__fixunsdfti", .linkage = linkage });
32
33 // Conversion from f80
34 @export(__fixxfsi, .{ .name = "__fixxfsi", .linkage = linkage });
35 @export(__fixunsxfsi, .{ .name = "__fixunsxfsi", .linkage = linkage });
36
37 @export(__fixxfdi, .{ .name = "__fixxfdi", .linkage = linkage });
38 @export(__fixunsxfdi, .{ .name = "__fixunsxfdi", .linkage = linkage });
39
40 @export(__fixxfti, .{ .name = "__fixxfti", .linkage = linkage });
41 @export(__fixunsxfti, .{ .name = "__fixunsxfti", .linkage = linkage });
42
43 // Conversion from f128
44 @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = linkage });
45 @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = linkage });
46
47 @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = linkage });
48 @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = linkage });
49
50 @export(__fixtfti, .{ .name = "__fixtfti", .linkage = linkage });
51 @export(__fixunstfti, .{ .name = "__fixunstfti", .linkage = linkage });
52
53 if (!is_test) {
54 if (arch.isARM() or arch.isThumb()) {
55 @export(__aeabi_f2ulz, .{ .name = "__aeabi_f2ulz", .linkage = linkage });
56 @export(__aeabi_d2ulz, .{ .name = "__aeabi_d2ulz", .linkage = linkage });
57
58 @export(__aeabi_f2lz, .{ .name = "__aeabi_f2lz", .linkage = linkage });
59 @export(__aeabi_d2lz, .{ .name = "__aeabi_d2lz", .linkage = linkage });
60
61 @export(__aeabi_d2uiz, .{ .name = "__aeabi_d2uiz", .linkage = linkage });
62
63 @export(__aeabi_f2uiz, .{ .name = "__aeabi_f2uiz", .linkage = linkage });
64
65 @export(__aeabi_f2iz, .{ .name = "__aeabi_f2iz", .linkage = linkage });
66 @export(__aeabi_d2iz, .{ .name = "__aeabi_d2iz", .linkage = linkage });
67 }
68
69 if (arch.isPPC() or arch.isPPC64()) {
70 @export(__fixkfdi, .{ .name = "__fixkfdi", .linkage = linkage });
71 @export(__fixkfsi, .{ .name = "__fixkfsi", .linkage = linkage });
72 @export(__fixunskfsi, .{ .name = "__fixunskfsi", .linkage = linkage });
73 @export(__fixunskfdi, .{ .name = "__fixunskfdi", .linkage = linkage });
74 }
75 }
76}
77
78pub inline fn fixXfYi(comptime I: type, a: anytype) I {
79 @setRuntimeSafety(is_test);
80
81 const F = @TypeOf(a);
82 const float_bits = @typeInfo(F).Float.bits;
83 const int_bits = @typeInfo(I).Int.bits;
84 const rep_t = std.meta.Int(.unsigned, float_bits);
85 const sig_bits = math.floatMantissaBits(F);
86 const exp_bits = math.floatExponentBits(F);
87 const fractional_bits = math.floatFractionalBits(F);
88
89 const implicit_bit = if (F != f80) (@as(rep_t, 1) << sig_bits) else 0;
90 const max_exp = (1 << (exp_bits - 1));
91 const exp_bias = max_exp - 1;
92 const sig_mask = (@as(rep_t, 1) << sig_bits) - 1;
93
94 // Break a into sign, exponent, significand
95 const a_rep: rep_t = @bitCast(rep_t, a);
96 const negative = (a_rep >> (float_bits - 1)) != 0;
97 const exponent = @intCast(i32, (a_rep << 1) >> (sig_bits + 1)) - exp_bias;
98 const significand: rep_t = (a_rep & sig_mask) | implicit_bit;
99
100 // If the exponent is negative, the result rounds to zero.
101 if (exponent < 0) return 0;
102
103 // If the value is too large for the integer type, saturate.
104 switch (@typeInfo(I).Int.signedness) {
105 .unsigned => {
106 if (negative) return 0;
107 if (@intCast(c_uint, exponent) >= @minimum(int_bits, max_exp)) return math.maxInt(I);
108 },
109 .signed => if (@intCast(c_uint, exponent) >= @minimum(int_bits - 1, max_exp)) {
110 return if (negative) math.minInt(I) else math.maxInt(I);
111 },
112 }
113
114 // If 0 <= exponent < sig_bits, right shift to get the result.
115 // Otherwise, shift left.
116 var result: I = undefined;
117 if (exponent < fractional_bits) {
118 result = @intCast(I, significand >> @intCast(Log2Int(rep_t), fractional_bits - exponent));
119 } else {
120 result = @intCast(I, significand) << @intCast(Log2Int(I), exponent - fractional_bits);
121 }
122
123 if ((@typeInfo(I).Int.signedness == .signed) and negative)
124 return ~result +% 1;
125 return result;
126}
127
128// Conversion from f16
129
130pub fn __fixhfsi(a: f16) callconv(.C) i32 {
131 return fixXfYi(i32, a);
132}
133
134pub fn __fixunshfsi(a: f16) callconv(.C) u32 {
135 return fixXfYi(u32, a);
136}
137
138pub fn __fixhfdi(a: f16) callconv(.C) i64 {
139 return fixXfYi(i64, a);
140}
141
142pub fn __fixunshfdi(a: f16) callconv(.C) u64 {
143 return fixXfYi(u64, a);
144}
145
146pub fn __fixhfti(a: f16) callconv(.C) i128 {
147 return fixXfYi(i128, a);
148}
149
150pub fn __fixunshfti(a: f16) callconv(.C) u128 {
151 return fixXfYi(u128, a);
152}
153
154// Conversion from f32
155
156pub fn __fixsfsi(a: f32) callconv(.C) i32 {
157 return fixXfYi(i32, a);
158}
159
160pub fn __fixunssfsi(a: f32) callconv(.C) u32 {
161 return fixXfYi(u32, a);
162}
163
164pub fn __fixsfdi(a: f32) callconv(.C) i64 {
165 return fixXfYi(i64, a);
166}
167
168pub fn __fixunssfdi(a: f32) callconv(.C) u64 {
169 return fixXfYi(u64, a);
170}
171
172pub fn __fixsfti(a: f32) callconv(.C) i128 {
173 return fixXfYi(i128, a);
174}
175
176pub fn __fixunssfti(a: f32) callconv(.C) u128 {
177 return fixXfYi(u128, a);
178}
179
180// Conversion from f64
181
182pub fn __fixdfsi(a: f64) callconv(.C) i32 {
183 return fixXfYi(i32, a);
184}
185
186pub fn __fixunsdfsi(a: f64) callconv(.C) u32 {
187 return fixXfYi(u32, a);
188}
189
190pub fn __fixdfdi(a: f64) callconv(.C) i64 {
191 return fixXfYi(i64, a);
192}
193
194pub fn __fixunsdfdi(a: f64) callconv(.C) u64 {
195 return fixXfYi(u64, a);
196}
197
198pub fn __fixdfti(a: f64) callconv(.C) i128 {
199 return fixXfYi(i128, a);
200}
201
202pub fn __fixunsdfti(a: f64) callconv(.C) u128 {
203 return fixXfYi(u128, a);
204}
205
206// Conversion from f80
207
208pub fn __fixxfsi(a: f80) callconv(.C) i32 {
209 return fixXfYi(i32, a);
210}
211
212pub fn __fixunsxfsi(a: f80) callconv(.C) u32 {
213 return fixXfYi(u32, a);
214}
215
216pub fn __fixxfdi(a: f80) callconv(.C) i64 {
217 return fixXfYi(i64, a);
218}
219
220pub fn __fixunsxfdi(a: f80) callconv(.C) u64 {
221 return fixXfYi(u64, a);
222}
223
224pub fn __fixxfti(a: f80) callconv(.C) i128 {
225 return fixXfYi(i128, a);
226}
227
228pub fn __fixunsxfti(a: f80) callconv(.C) u128 {
229 return fixXfYi(u128, a);
230}
231
232// Conversion from f128
233
234pub fn __fixtfsi(a: f128) callconv(.C) i32 {
235 return fixXfYi(i32, a);
236}
237
238pub fn __fixkfsi(a: f128) callconv(.C) i32 {
239 return __fixtfsi(a);
240}
241
242pub fn __fixunstfsi(a: f128) callconv(.C) u32 {
243 return fixXfYi(u32, a);
244}
245
246pub fn __fixunskfsi(a: f128) callconv(.C) u32 {
247 return @call(.{ .modifier = .always_inline }, __fixunstfsi, .{a});
248}
249
250pub fn __fixtfdi(a: f128) callconv(.C) i64 {
251 return fixXfYi(i64, a);
252}
253
254pub fn __fixkfdi(a: f128) callconv(.C) i64 {
255 return @call(.{ .modifier = .always_inline }, __fixtfdi, .{a});
256}
257
258pub fn __fixunstfdi(a: f128) callconv(.C) u64 {
259 return fixXfYi(u64, a);
260}
261
262pub fn __fixunskfdi(a: f128) callconv(.C) u64 {
263 return @call(.{ .modifier = .always_inline }, __fixunstfdi, .{a});
264}
265
266pub fn __fixtfti(a: f128) callconv(.C) i128 {
267 return fixXfYi(i128, a);
268}
269
270pub fn __fixunstfti(a: f128) callconv(.C) u128 {
271 return fixXfYi(u128, a);
272}
273
274// Conversion from f32
275
276pub fn __aeabi_f2iz(a: f32) callconv(.AAPCS) i32 {
277 return fixXfYi(i32, a);
278}
279
280pub fn __aeabi_f2uiz(a: f32) callconv(.AAPCS) u32 {
281 return fixXfYi(u32, a);
282}
283
284pub fn __aeabi_f2lz(a: f32) callconv(.AAPCS) i64 {
285 return fixXfYi(i64, a);
286}
287
288pub fn __aeabi_f2ulz(a: f32) callconv(.AAPCS) u64 {
289 return fixXfYi(u64, a);
290}
291
292// Conversion from f64
293
294pub fn __aeabi_d2iz(a: f64) callconv(.AAPCS) i32 {
295 return fixXfYi(i32, a);
296}
297
298pub fn __aeabi_d2uiz(a: f64) callconv(.AAPCS) u32 {
299 return fixXfYi(u32, a);
300}
301
302pub fn __aeabi_d2lz(a: f64) callconv(.AAPCS) i64 {
303 return fixXfYi(i64, a);
304}
305
306pub fn __aeabi_d2ulz(a: f64) callconv(.AAPCS) u64 {
307 return fixXfYi(u64, a);
308}
309
310test {
311 _ = @import("fixXfYi_test.zig");
312}
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
14fn __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
14fn __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
10fn __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
14fn __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
14fn __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
10fn __fixsfti(a: f32) callconv(.C) i128 {
11 return floatToInt(i128, a);
12}
lib/compiler_rt/fixtfdi.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_ppc_abi) {
8 @export(__fixkfdi, .{ .name = "__fixkfdi", .linkage = common.linkage });
9 } else {
10 @export(__fixtfdi, .{ .name = "__fixtfdi", .linkage = common.linkage });
11 }
12}
13
14fn __fixtfdi(a: f128) callconv(.C) i64 {
15 return floatToInt(i64, a);
16}
17
18fn __fixkfdi(a: f128) callconv(.C) i64 {
19 return floatToInt(i64, a);
20}
lib/compiler_rt/fixtfsi.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_ppc_abi) {
8 @export(__fixkfsi, .{ .name = "__fixkfsi", .linkage = common.linkage });
9 } else {
10 @export(__fixtfsi, .{ .name = "__fixtfsi", .linkage = common.linkage });
11 }
12}
13
14fn __fixtfsi(a: f128) callconv(.C) i32 {
15 return floatToInt(i32, a);
16}
17
18fn __fixkfsi(a: f128) callconv(.C) i32 {
19 return floatToInt(i32, a);
20}
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
10fn __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
14fn __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
14fn __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
10fn __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
10fn __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
14fn __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
14fn __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
10fn __fixunssfti(a: f32) callconv(.C) u128 {
11 return floatToInt(u128, a);
12}
lib/compiler_rt/fixunstfdi.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_ppc_abi) {
8 @export(__fixunskfdi, .{ .name = "__fixunskfdi", .linkage = common.linkage });
9 } else {
10 @export(__fixunstfdi, .{ .name = "__fixunstfdi", .linkage = common.linkage });
11 }
12}
13
14fn __fixunstfdi(a: f128) callconv(.C) u64 {
15 return floatToInt(u64, a);
16}
17
18fn __fixunskfdi(a: f128) callconv(.C) u64 {
19 return floatToInt(u64, a);
20}
lib/compiler_rt/fixunstfsi.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_ppc_abi) {
8 @export(__fixunskfsi, .{ .name = "__fixunskfsi", .linkage = common.linkage });
9 } else {
10 @export(__fixunstfsi, .{ .name = "__fixunstfsi", .linkage = common.linkage });
11 }
12}
13
14fn __fixunstfsi(a: f128) callconv(.C) u32 {
15 return floatToInt(u32, a);
16}
17
18fn __fixunskfsi(a: f128) callconv(.C) u32 {
19 return floatToInt(u32, a);
20}
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
10fn __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
10fn __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-311
......@@ -1,311 +0,0 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const math = std.math;
4const expect = std.testing.expect;
5const arch = builtin.cpu.arch;
6const is_test = builtin.is_test;
7const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
8pub const panic = @import("common.zig").panic;
9
10comptime {
11 // Integral -> Float Conversion
12
13 // Conversion to f32
14 @export(__floatsisf, .{ .name = "__floatsisf", .linkage = linkage });
15 @export(__floatunsisf, .{ .name = "__floatunsisf", .linkage = linkage });
16
17 @export(__floatundisf, .{ .name = "__floatundisf", .linkage = linkage });
18 @export(__floatdisf, .{ .name = "__floatdisf", .linkage = linkage });
19
20 @export(__floattisf, .{ .name = "__floattisf", .linkage = linkage });
21 @export(__floatuntisf, .{ .name = "__floatuntisf", .linkage = linkage });
22
23 // Conversion to f64
24 @export(__floatsidf, .{ .name = "__floatsidf", .linkage = linkage });
25 @export(__floatunsidf, .{ .name = "__floatunsidf", .linkage = linkage });
26
27 @export(__floatdidf, .{ .name = "__floatdidf", .linkage = linkage });
28 @export(__floatundidf, .{ .name = "__floatundidf", .linkage = linkage });
29
30 @export(__floattidf, .{ .name = "__floattidf", .linkage = linkage });
31 @export(__floatuntidf, .{ .name = "__floatuntidf", .linkage = linkage });
32
33 // Conversion to f80
34 @export(__floatsixf, .{ .name = "__floatsixf", .linkage = linkage });
35 @export(__floatunsixf, .{ .name = "__floatunsixf", .linkage = linkage });
36
37 @export(__floatdixf, .{ .name = "__floatdixf", .linkage = linkage });
38 @export(__floatundixf, .{ .name = "__floatundixf", .linkage = linkage });
39
40 @export(__floattixf, .{ .name = "__floattixf", .linkage = linkage });
41 @export(__floatuntixf, .{ .name = "__floatuntixf", .linkage = linkage });
42
43 // Conversion to f128
44 @export(__floatsitf, .{ .name = "__floatsitf", .linkage = linkage });
45 @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = linkage });
46
47 @export(__floatditf, .{ .name = "__floatditf", .linkage = linkage });
48 @export(__floatunditf, .{ .name = "__floatunditf", .linkage = linkage });
49
50 @export(__floattitf, .{ .name = "__floattitf", .linkage = linkage });
51 @export(__floatuntitf, .{ .name = "__floatuntitf", .linkage = linkage });
52
53 if (!is_test) {
54 if (arch.isARM() or arch.isThumb()) {
55 @export(__aeabi_i2d, .{ .name = "__aeabi_i2d", .linkage = linkage });
56 @export(__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = linkage });
57 @export(__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = linkage });
58 @export(__aeabi_ui2d, .{ .name = "__aeabi_ui2d", .linkage = linkage });
59 @export(__aeabi_ul2d, .{ .name = "__aeabi_ul2d", .linkage = linkage });
60 @export(__aeabi_ui2f, .{ .name = "__aeabi_ui2f", .linkage = linkage });
61 @export(__aeabi_ul2f, .{ .name = "__aeabi_ul2f", .linkage = linkage });
62
63 @export(__aeabi_i2f, .{ .name = "__aeabi_i2f", .linkage = linkage });
64 }
65
66 if (arch.isPPC() or arch.isPPC64()) {
67 @export(__floatsikf, .{ .name = "__floatsikf", .linkage = linkage });
68 @export(__floatdikf, .{ .name = "__floatdikf", .linkage = linkage });
69 @export(__floatundikf, .{ .name = "__floatundikf", .linkage = linkage });
70 @export(__floatunsikf, .{ .name = "__floatunsikf", .linkage = linkage });
71 @export(__floatuntikf, .{ .name = "__floatuntikf", .linkage = linkage });
72 }
73 }
74}
75
76pub fn floatXiYf(comptime T: type, x: anytype) T {
77 @setRuntimeSafety(is_test);
78
79 if (x == 0) return 0;
80
81 // Various constants whose values follow from the type parameters.
82 // Any reasonable optimizer will fold and propagate all of these.
83 const Z = std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(x)));
84 const uT = std.meta.Int(.unsigned, @bitSizeOf(T));
85 const inf = math.inf(T);
86 const float_bits = @bitSizeOf(T);
87 const int_bits = @bitSizeOf(@TypeOf(x));
88 const exp_bits = math.floatExponentBits(T);
89 const fractional_bits = math.floatFractionalBits(T);
90 const exp_bias = math.maxInt(std.meta.Int(.unsigned, exp_bits - 1));
91 const implicit_bit = if (T != f80) @as(uT, 1) << fractional_bits else 0;
92 const max_exp = exp_bias;
93
94 // Sign
95 var abs_val = math.absCast(x);
96 const sign_bit = if (x < 0) @as(uT, 1) << (float_bits - 1) else 0;
97 var result: uT = sign_bit;
98
99 // Compute significand
100 var exp = int_bits - @clz(Z, abs_val) - 1;
101 if (int_bits <= fractional_bits or exp <= fractional_bits) {
102 const shift_amt = fractional_bits - @intCast(math.Log2Int(uT), exp);
103
104 // Shift up result to line up with the significand - no rounding required
105 result = (@intCast(uT, abs_val) << shift_amt);
106 result ^= implicit_bit; // Remove implicit integer bit
107 } else {
108 var shift_amt = @intCast(math.Log2Int(Z), exp - fractional_bits);
109 const exact_tie: bool = @ctz(Z, abs_val) == shift_amt - 1;
110
111 // Shift down result and remove implicit integer bit
112 result = @intCast(uT, (abs_val >> (shift_amt - 1))) ^ (implicit_bit << 1);
113
114 // Round result, including round-to-even for exact ties
115 result = ((result + 1) >> 1) & ~@as(uT, @boolToInt(exact_tie));
116 }
117
118 // Compute exponent
119 if ((int_bits > max_exp) and (exp > max_exp)) // If exponent too large, overflow to infinity
120 return @bitCast(T, sign_bit | @bitCast(uT, inf));
121
122 result += (@as(uT, exp) + exp_bias) << math.floatMantissaBits(T);
123
124 // If the result included a carry, we need to restore the explicit integer bit
125 if (T == f80) result |= 1 << fractional_bits;
126
127 return @bitCast(T, sign_bit | result);
128}
129
130// Conversion to f16
131pub fn __floatsihf(a: i32) callconv(.C) f16 {
132 return floatXiYf(f16, a);
133}
134
135pub fn __floatunsihf(a: u32) callconv(.C) f16 {
136 return floatXiYf(f16, a);
137}
138
139pub fn __floatdihf(a: i64) callconv(.C) f16 {
140 return floatXiYf(f16, a);
141}
142
143pub fn __floatundihf(a: u64) callconv(.C) f16 {
144 return floatXiYf(f16, a);
145}
146
147pub fn __floattihf(a: i128) callconv(.C) f16 {
148 return floatXiYf(f16, a);
149}
150
151pub fn __floatuntihf(a: u128) callconv(.C) f16 {
152 return floatXiYf(f16, a);
153}
154
155// Conversion to f32
156pub fn __floatsisf(a: i32) callconv(.C) f32 {
157 return floatXiYf(f32, a);
158}
159
160pub fn __floatunsisf(a: u32) callconv(.C) f32 {
161 return floatXiYf(f32, a);
162}
163
164pub fn __floatdisf(a: i64) callconv(.C) f32 {
165 return floatXiYf(f32, a);
166}
167
168pub fn __floatundisf(a: u64) callconv(.C) f32 {
169 return floatXiYf(f32, a);
170}
171
172pub fn __floattisf(a: i128) callconv(.C) f32 {
173 return floatXiYf(f32, a);
174}
175
176pub fn __floatuntisf(a: u128) callconv(.C) f32 {
177 return floatXiYf(f32, a);
178}
179
180// Conversion to f64
181pub fn __floatsidf(a: i32) callconv(.C) f64 {
182 return floatXiYf(f64, a);
183}
184
185pub fn __floatunsidf(a: u32) callconv(.C) f64 {
186 return floatXiYf(f64, a);
187}
188
189pub fn __floatdidf(a: i64) callconv(.C) f64 {
190 return floatXiYf(f64, a);
191}
192
193pub fn __floatundidf(a: u64) callconv(.C) f64 {
194 return floatXiYf(f64, a);
195}
196
197pub fn __floattidf(a: i128) callconv(.C) f64 {
198 return floatXiYf(f64, a);
199}
200
201pub fn __floatuntidf(a: u128) callconv(.C) f64 {
202 return floatXiYf(f64, a);
203}
204
205// Conversion to f80
206pub fn __floatsixf(a: i32) callconv(.C) f80 {
207 return floatXiYf(f80, a);
208}
209
210pub fn __floatunsixf(a: u32) callconv(.C) f80 {
211 return floatXiYf(f80, a);
212}
213
214pub fn __floatdixf(a: i64) callconv(.C) f80 {
215 return floatXiYf(f80, a);
216}
217
218pub fn __floatundixf(a: u64) callconv(.C) f80 {
219 return floatXiYf(f80, a);
220}
221
222pub fn __floattixf(a: i128) callconv(.C) f80 {
223 return floatXiYf(f80, a);
224}
225
226pub fn __floatuntixf(a: u128) callconv(.C) f80 {
227 return floatXiYf(f80, a);
228}
229
230// Conversion to f128
231pub fn __floatsitf(a: i32) callconv(.C) f128 {
232 return floatXiYf(f128, a);
233}
234
235pub fn __floatsikf(a: i32) callconv(.C) f128 {
236 return @call(.{ .modifier = .always_inline }, __floatsitf, .{a});
237}
238
239pub fn __floatunsitf(a: u32) callconv(.C) f128 {
240 return floatXiYf(f128, a);
241}
242
243pub fn __floatunsikf(a: u32) callconv(.C) f128 {
244 return @call(.{ .modifier = .always_inline }, __floatunsitf, .{a});
245}
246
247pub fn __floatditf(a: i64) callconv(.C) f128 {
248 return floatXiYf(f128, a);
249}
250
251pub fn __floatdikf(a: i64) callconv(.C) f128 {
252 return @call(.{ .modifier = .always_inline }, __floatditf, .{a});
253}
254
255pub fn __floatunditf(a: u64) callconv(.C) f128 {
256 return floatXiYf(f128, a);
257}
258
259pub fn __floatundikf(a: u64) callconv(.C) f128 {
260 return @call(.{ .modifier = .always_inline }, __floatunditf, .{a});
261}
262
263pub fn __floattitf(a: i128) callconv(.C) f128 {
264 return floatXiYf(f128, a);
265}
266
267pub fn __floatuntitf(a: u128) callconv(.C) f128 {
268 return floatXiYf(f128, a);
269}
270
271pub fn __floatuntikf(a: u128) callconv(.C) f128 {
272 return @call(.{ .modifier = .always_inline }, __floatuntitf, .{a});
273}
274
275// Conversion to f32
276pub fn __aeabi_ui2f(arg: u32) callconv(.AAPCS) f32 {
277 return floatXiYf(f32, arg);
278}
279
280pub fn __aeabi_i2f(arg: i32) callconv(.AAPCS) f32 {
281 return floatXiYf(f32, arg);
282}
283
284pub fn __aeabi_ul2f(arg: u64) callconv(.AAPCS) f32 {
285 return floatXiYf(f32, arg);
286}
287
288pub fn __aeabi_l2f(arg: i64) callconv(.AAPCS) f32 {
289 return floatXiYf(f32, arg);
290}
291
292// Conversion to f64
293pub fn __aeabi_ui2d(arg: u32) callconv(.AAPCS) f64 {
294 return floatXiYf(f64, arg);
295}
296
297pub fn __aeabi_i2d(arg: i32) callconv(.AAPCS) f64 {
298 return floatXiYf(f64, arg);
299}
300
301pub fn __aeabi_ul2d(arg: u64) callconv(.AAPCS) f64 {
302 return floatXiYf(f64, arg);
303}
304
305pub fn __aeabi_l2d(arg: i64) callconv(.AAPCS) f64 {
306 return floatXiYf(f64, arg);
307}
308
309test {
310 _ = @import("floatXiYf_test.zig");
311}
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+948
......@@ -0,0 +1,948 @@
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/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
14fn __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
14fn __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+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(__floatdikf, .{ .name = "__floatdikf", .linkage = common.linkage });
9 } else {
10 @export(__floatditf, .{ .name = "__floatditf", .linkage = common.linkage });
11 }
12}
13
14fn __floatditf(a: i64) callconv(.C) f128 {
15 return intToFloat(f128, a);
16}
17
18fn __floatdikf(a: i64) callconv(.C) f128 {
19 return intToFloat(f128, a);
20}
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
14fn __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
14fn __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+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(__floatsikf, .{ .name = "__floatsikf", .linkage = common.linkage });
9 } else {
10 @export(__floatsitf, .{ .name = "__floatsitf", .linkage = common.linkage });
11 }
12}
13
14fn __floatsitf(a: i32) callconv(.C) f128 {
15 return intToFloat(f128, a);
16}
17
18fn __floatsikf(a: i32) callconv(.C) f128 {
19 return intToFloat(f128, a);
20}
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
10fn __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
10fn __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
10fn __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
14fn __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
14fn __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+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(__floatundikf, .{ .name = "__floatundikf", .linkage = common.linkage });
9 } else {
10 @export(__floatunditf, .{ .name = "__floatunditf", .linkage = common.linkage });
11 }
12}
13
14fn __floatunditf(a: u64) callconv(.C) f128 {
15 return intToFloat(f128, a);
16}
17
18fn __floatundikf(a: u64) callconv(.C) f128 {
19 return intToFloat(f128, a);
20}
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
14fn __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
10fn __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
14fn __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+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(__floatunsikf, .{ .name = "__floatunsikf", .linkage = common.linkage });
9 } else {
10 @export(__floatunsitf, .{ .name = "__floatunsitf", .linkage = common.linkage });
11 }
12}
13
14fn __floatunsitf(a: u32) callconv(.C) f128 {
15 return intToFloat(f128, a);
16}
17
18fn __floatunsikf(a: u32) callconv(.C) f128 {
19 return intToFloat(f128, a);
20}
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
10fn __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
10fn __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
14fn __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/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."
20fn __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."
26fn __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 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."
20fn __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."
26fn __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 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+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_ppc_abi) {
10 @export(__gekf2, .{ .name = "__gekf2", .linkage = common.linkage });
11 @export(__gtkf2, .{ .name = "__gtkf2", .linkage = common.linkage });
12 } else {
13 @export(__getf2, .{ .name = "__getf2", .linkage = common.linkage });
14 @export(__gttf2, .{ .name = "__gttf2", .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."
20fn __getf2(a: f128, b: f128) callconv(.C) i32 {
21 return @enumToInt(comparef.cmpf2(f128, 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."
26fn __gttf2(a: f128, b: f128) callconv(.C) i32 {
27 return __getf2(a, b);
28}
29
30fn __gekf2(a: f128, b: f128) callconv(.C) i32 {
31 return __getf2(a, b);
32}
33
34fn __gtkf2(a: f128, b: f128) callconv(.C) i32 {
35 return __getf2(a, b);
36}
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_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("floatXiYf_test.zig");
58}
lib/compiler_rt/mulXf3.zig deleted-368
......@@ -1,368 +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 arch = builtin.cpu.arch;
9const is_test = builtin.is_test;
10const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
11pub const panic = @import("common.zig").panic;
12
13comptime {
14 @export(__mulsf3, .{ .name = "__mulsf3", .linkage = linkage });
15 @export(__muldf3, .{ .name = "__muldf3", .linkage = linkage });
16 @export(__mulxf3, .{ .name = "__mulxf3", .linkage = linkage });
17 @export(__multf3, .{ .name = "__multf3", .linkage = linkage });
18
19 if (!is_test) {
20 if (arch.isARM() or arch.isThumb()) {
21 @export(__aeabi_fmul, .{ .name = "__aeabi_fmul", .linkage = linkage });
22 @export(__aeabi_dmul, .{ .name = "__aeabi_dmul", .linkage = linkage });
23 }
24
25 if (arch.isPPC() or arch.isPPC64()) {
26 @export(__mulkf3, .{ .name = "__mulkf3", .linkage = linkage });
27 }
28 }
29}
30
31pub fn __mulkf3(a: f128, b: f128) callconv(.C) f128 {
32 return @call(.{ .modifier = .always_inline }, __multf3, .{ a, b });
33}
34pub fn __multf3(a: f128, b: f128) callconv(.C) f128 {
35 return mulXf3(f128, a, b);
36}
37pub fn __mulxf3(a: f80, b: f80) callconv(.C) f80 {
38 return mulXf3(f80, a, b);
39}
40pub fn __muldf3(a: f64, b: f64) callconv(.C) f64 {
41 return mulXf3(f64, a, b);
42}
43pub fn __mulsf3(a: f32, b: f32) callconv(.C) f32 {
44 return mulXf3(f32, a, b);
45}
46
47pub fn __aeabi_fmul(a: f32, b: f32) callconv(.C) f32 {
48 @setRuntimeSafety(false);
49 return @call(.{ .modifier = .always_inline }, __mulsf3, .{ a, b });
50}
51
52pub fn __aeabi_dmul(a: f64, b: f64) callconv(.C) f64 {
53 @setRuntimeSafety(false);
54 return @call(.{ .modifier = .always_inline }, __muldf3, .{ a, b });
55}
56
57pub fn mulXf3(comptime T: type, a: T, b: T) T {
58 @setRuntimeSafety(builtin.is_test);
59 const typeWidth = @typeInfo(T).Float.bits;
60 const significandBits = math.floatMantissaBits(T);
61 const fractionalBits = math.floatFractionalBits(T);
62 const exponentBits = math.floatExponentBits(T);
63
64 const Z = std.meta.Int(.unsigned, typeWidth);
65
66 // ZSignificand is large enough to contain the significand, including an explicit integer bit
67 const ZSignificand = PowerOfTwoSignificandZ(T);
68 const ZSignificandBits = @typeInfo(ZSignificand).Int.bits;
69
70 const roundBit = (1 << (ZSignificandBits - 1));
71 const signBit = (@as(Z, 1) << (significandBits + exponentBits));
72 const maxExponent = ((1 << exponentBits) - 1);
73 const exponentBias = (maxExponent >> 1);
74
75 const integerBit = (@as(ZSignificand, 1) << fractionalBits);
76 const quietBit = integerBit >> 1;
77 const significandMask = (@as(Z, 1) << significandBits) - 1;
78
79 const absMask = signBit - 1;
80 const qnanRep = @bitCast(Z, math.nan(T)) | quietBit;
81 const infRep = @bitCast(Z, math.inf(T));
82 const minNormalRep = @bitCast(Z, math.floatMin(T));
83
84 const aExponent = @truncate(u32, (@bitCast(Z, a) >> significandBits) & maxExponent);
85 const bExponent = @truncate(u32, (@bitCast(Z, b) >> significandBits) & maxExponent);
86 const productSign: Z = (@bitCast(Z, a) ^ @bitCast(Z, b)) & signBit;
87
88 var aSignificand: ZSignificand = @intCast(ZSignificand, @bitCast(Z, a) & significandMask);
89 var bSignificand: ZSignificand = @intCast(ZSignificand, @bitCast(Z, b) & significandMask);
90 var scale: i32 = 0;
91
92 // Detect if a or b is zero, denormal, infinity, or NaN.
93 if (aExponent -% 1 >= maxExponent - 1 or bExponent -% 1 >= maxExponent - 1) {
94 const aAbs: Z = @bitCast(Z, a) & absMask;
95 const bAbs: Z = @bitCast(Z, b) & absMask;
96
97 // NaN * anything = qNaN
98 if (aAbs > infRep) return @bitCast(T, @bitCast(Z, a) | quietBit);
99 // anything * NaN = qNaN
100 if (bAbs > infRep) return @bitCast(T, @bitCast(Z, b) | quietBit);
101
102 if (aAbs == infRep) {
103 // infinity * non-zero = +/- infinity
104 if (bAbs != 0) {
105 return @bitCast(T, aAbs | productSign);
106 } else {
107 // infinity * zero = NaN
108 return @bitCast(T, qnanRep);
109 }
110 }
111
112 if (bAbs == infRep) {
113 //? non-zero * infinity = +/- infinity
114 if (aAbs != 0) {
115 return @bitCast(T, bAbs | productSign);
116 } else {
117 // zero * infinity = NaN
118 return @bitCast(T, qnanRep);
119 }
120 }
121
122 // zero * anything = +/- zero
123 if (aAbs == 0) return @bitCast(T, productSign);
124 // anything * zero = +/- zero
125 if (bAbs == 0) return @bitCast(T, productSign);
126
127 // one or both of a or b is denormal, the other (if applicable) is a
128 // normal number. Renormalize one or both of a and b, and set scale to
129 // include the necessary exponent adjustment.
130 if (aAbs < minNormalRep) scale += normalize(T, &aSignificand);
131 if (bAbs < minNormalRep) scale += normalize(T, &bSignificand);
132 }
133
134 // Or in the implicit significand bit. (If we fell through from the
135 // denormal path it was already set by normalize( ), but setting it twice
136 // won't hurt anything.)
137 aSignificand |= integerBit;
138 bSignificand |= integerBit;
139
140 // Get the significand of a*b. Before multiplying the significands, shift
141 // one of them left to left-align it in the field. Thus, the product will
142 // have (exponentBits + 2) integral digits, all but two of which must be
143 // zero. Normalizing this result is just a conditional left-shift by one
144 // and bumping the exponent accordingly.
145 var productHi: ZSignificand = undefined;
146 var productLo: ZSignificand = undefined;
147 const left_align_shift = ZSignificandBits - fractionalBits - 1;
148 wideMultiply(ZSignificand, aSignificand, bSignificand << left_align_shift, &productHi, &productLo);
149
150 var productExponent: i32 = @intCast(i32, aExponent + bExponent) - exponentBias + scale;
151
152 // Normalize the significand, adjust exponent if needed.
153 if ((productHi & integerBit) != 0) {
154 productExponent +%= 1;
155 } else {
156 productHi = (productHi << 1) | (productLo >> (ZSignificandBits - 1));
157 productLo = productLo << 1;
158 }
159
160 // If we have overflowed the type, return +/- infinity.
161 if (productExponent >= maxExponent) return @bitCast(T, infRep | productSign);
162
163 var result: Z = undefined;
164 if (productExponent <= 0) {
165 // Result is denormal before rounding
166 //
167 // If the result is so small that it just underflows to zero, return
168 // a zero of the appropriate sign. Mathematically there is no need to
169 // handle this case separately, but we make it a special case to
170 // simplify the shift logic.
171 const shift: u32 = @truncate(u32, @as(Z, 1) -% @bitCast(u32, productExponent));
172 if (shift >= ZSignificandBits) return @bitCast(T, productSign);
173
174 // Otherwise, shift the significand of the result so that the round
175 // bit is the high bit of productLo.
176 const sticky = wideShrWithTruncation(ZSignificand, &productHi, &productLo, shift);
177 productLo |= @boolToInt(sticky);
178 result = productHi;
179
180 // We include the integer bit so that rounding will carry to the exponent,
181 // but it will be removed later if the result is still denormal
182 if (significandBits != fractionalBits) result |= integerBit;
183 } else {
184 // Result is normal before rounding; insert the exponent.
185 result = productHi & significandMask;
186 result |= @intCast(Z, productExponent) << significandBits;
187 }
188
189 // Final rounding. The final result may overflow to infinity, or underflow
190 // to zero, but those are the correct results in those cases. We use the
191 // default IEEE-754 round-to-nearest, ties-to-even rounding mode.
192 if (productLo > roundBit) result +%= 1;
193 if (productLo == roundBit) result +%= result & 1;
194
195 // Restore any explicit integer bit, if it was rounded off
196 if (significandBits != fractionalBits) {
197 if ((result >> significandBits) != 0) {
198 result |= integerBit;
199 } else {
200 result &= ~integerBit;
201 }
202 }
203
204 // Insert the sign of the result:
205 result |= productSign;
206
207 return @bitCast(T, result);
208}
209
210fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
211 @setRuntimeSafety(builtin.is_test);
212 switch (Z) {
213 u16 => {
214 // 16x16 --> 32 bit multiply
215 const product = @as(u32, a) * @as(u32, b);
216 hi.* = @intCast(u16, product >> 16);
217 lo.* = @truncate(u16, product);
218 },
219 u32 => {
220 // 32x32 --> 64 bit multiply
221 const product = @as(u64, a) * @as(u64, b);
222 hi.* = @intCast(u32, product >> 32);
223 lo.* = @truncate(u32, product);
224 },
225 u64 => {
226 const S = struct {
227 fn loWord(x: u64) u64 {
228 return @truncate(u32, x);
229 }
230 fn hiWord(x: u64) u64 {
231 return @intCast(u32, x >> 32);
232 }
233 };
234 // 64x64 -> 128 wide multiply for platforms that don't have such an operation;
235 // many 64-bit platforms have this operation, but they tend to have hardware
236 // floating-point, so we don't bother with a special case for them here.
237 // Each of the component 32x32 -> 64 products
238 const plolo: u64 = S.loWord(a) * S.loWord(b);
239 const plohi: u64 = S.loWord(a) * S.hiWord(b);
240 const philo: u64 = S.hiWord(a) * S.loWord(b);
241 const phihi: u64 = S.hiWord(a) * S.hiWord(b);
242 // Sum terms that contribute to lo in a way that allows us to get the carry
243 const r0: u64 = S.loWord(plolo);
244 const r1: u64 = S.hiWord(plolo) +% S.loWord(plohi) +% S.loWord(philo);
245 lo.* = r0 +% (r1 << 32);
246 // Sum terms contributing to hi with the carry from lo
247 hi.* = S.hiWord(plohi) +% S.hiWord(philo) +% S.hiWord(r1) +% phihi;
248 },
249 u128 => {
250 const Word_LoMask = @as(u64, 0x00000000ffffffff);
251 const Word_HiMask = @as(u64, 0xffffffff00000000);
252 const Word_FullMask = @as(u64, 0xffffffffffffffff);
253 const S = struct {
254 fn Word_1(x: u128) u64 {
255 return @truncate(u32, x >> 96);
256 }
257 fn Word_2(x: u128) u64 {
258 return @truncate(u32, x >> 64);
259 }
260 fn Word_3(x: u128) u64 {
261 return @truncate(u32, x >> 32);
262 }
263 fn Word_4(x: u128) u64 {
264 return @truncate(u32, x);
265 }
266 };
267 // 128x128 -> 256 wide multiply for platforms that don't have such an operation;
268 // many 64-bit platforms have this operation, but they tend to have hardware
269 // floating-point, so we don't bother with a special case for them here.
270
271 const product11: u64 = S.Word_1(a) * S.Word_1(b);
272 const product12: u64 = S.Word_1(a) * S.Word_2(b);
273 const product13: u64 = S.Word_1(a) * S.Word_3(b);
274 const product14: u64 = S.Word_1(a) * S.Word_4(b);
275 const product21: u64 = S.Word_2(a) * S.Word_1(b);
276 const product22: u64 = S.Word_2(a) * S.Word_2(b);
277 const product23: u64 = S.Word_2(a) * S.Word_3(b);
278 const product24: u64 = S.Word_2(a) * S.Word_4(b);
279 const product31: u64 = S.Word_3(a) * S.Word_1(b);
280 const product32: u64 = S.Word_3(a) * S.Word_2(b);
281 const product33: u64 = S.Word_3(a) * S.Word_3(b);
282 const product34: u64 = S.Word_3(a) * S.Word_4(b);
283 const product41: u64 = S.Word_4(a) * S.Word_1(b);
284 const product42: u64 = S.Word_4(a) * S.Word_2(b);
285 const product43: u64 = S.Word_4(a) * S.Word_3(b);
286 const product44: u64 = S.Word_4(a) * S.Word_4(b);
287
288 const sum0: u128 = @as(u128, product44);
289 const sum1: u128 = @as(u128, product34) +%
290 @as(u128, product43);
291 const sum2: u128 = @as(u128, product24) +%
292 @as(u128, product33) +%
293 @as(u128, product42);
294 const sum3: u128 = @as(u128, product14) +%
295 @as(u128, product23) +%
296 @as(u128, product32) +%
297 @as(u128, product41);
298 const sum4: u128 = @as(u128, product13) +%
299 @as(u128, product22) +%
300 @as(u128, product31);
301 const sum5: u128 = @as(u128, product12) +%
302 @as(u128, product21);
303 const sum6: u128 = @as(u128, product11);
304
305 const r0: u128 = (sum0 & Word_FullMask) +%
306 ((sum1 & Word_LoMask) << 32);
307 const r1: u128 = (sum0 >> 64) +%
308 ((sum1 >> 32) & Word_FullMask) +%
309 (sum2 & Word_FullMask) +%
310 ((sum3 << 32) & Word_HiMask);
311
312 lo.* = r0 +% (r1 << 64);
313 hi.* = (r1 >> 64) +%
314 (sum1 >> 96) +%
315 (sum2 >> 64) +%
316 (sum3 >> 32) +%
317 sum4 +%
318 (sum5 << 32) +%
319 (sum6 << 64);
320 },
321 else => @compileError("unsupported"),
322 }
323}
324
325/// Returns a power-of-two integer type that is large enough to contain
326/// the significand of T, including an explicit integer bit
327fn PowerOfTwoSignificandZ(comptime T: type) type {
328 const bits = math.ceilPowerOfTwoAssert(u16, math.floatFractionalBits(T) + 1);
329 return std.meta.Int(.unsigned, bits);
330}
331
332fn normalize(comptime T: type, significand: *PowerOfTwoSignificandZ(T)) i32 {
333 @setRuntimeSafety(builtin.is_test);
334 const Z = PowerOfTwoSignificandZ(T);
335 const integerBit = @as(Z, 1) << math.floatFractionalBits(T);
336
337 const shift = @clz(Z, significand.*) - @clz(Z, integerBit);
338 significand.* <<= @intCast(math.Log2Int(Z), shift);
339 return @as(i32, 1) - shift;
340}
341
342// Returns `true` if the right shift is inexact (i.e. any bit shifted out is non-zero)
343//
344// This is analogous to an shr version of `@shlWithOverflow`
345fn wideShrWithTruncation(comptime Z: type, hi: *Z, lo: *Z, count: u32) bool {
346 @setRuntimeSafety(builtin.is_test);
347 const typeWidth = @typeInfo(Z).Int.bits;
348 const S = math.Log2Int(Z);
349 var inexact = false;
350 if (count < typeWidth) {
351 inexact = (lo.* << @intCast(S, typeWidth -% count)) != 0;
352 lo.* = (hi.* << @intCast(S, typeWidth -% count)) | (lo.* >> @intCast(S, count));
353 hi.* = hi.* >> @intCast(S, count);
354 } else if (count < 2 * typeWidth) {
355 inexact = (hi.* << @intCast(S, 2 * typeWidth -% count) | lo.*) != 0;
356 lo.* = hi.* >> @intCast(S, count -% typeWidth);
357 hi.* = 0;
358 } else {
359 inexact = (hi.* | lo.*) != 0;
360 lo.* = 0;
361 hi.* = 0;
362 }
363 return inexact;
364}
365
366test {
367 _ = @import("mulXf3_test.zig");
368}
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
14fn __muldf3(a: f64, b: f64) callconv(.C) f64 {
15 return mulf3(f64, a, b);
16}
17
18fn __aeabi_dmul(a: f64, b: f64) callconv(.C) f64 {
19 return mulf3(f64, a, b);
20}
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("mulf3.zig").__multf3;
11const __mulxf3 = @import("mulf3.zig").__mulxf3;
12const __muldf3 = @import("mulf3.zig").__muldf3;
13const __mulsf3 = @import("mulf3.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/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
14fn __mulsf3(a: f32, b: f32) callconv(.C) f32 {
15 return mulf3(f32, a, b);
16}
17
18fn __aeabi_fmul(a: f32, b: f32) callconv(.C) f32 {
19 return mulf3(f32, a, b);
20}
lib/compiler_rt/multf3.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_ppc_abi) {
8 @export(__mulkf3, .{ .name = "__mulkf3", .linkage = common.linkage });
9 } else {
10 @export(__multf3, .{ .name = "__multf3", .linkage = common.linkage });
11 }
12}
13
14fn __multf3(a: f128, b: f128) callconv(.C) f128 {
15 return mulf3(f128, a, b);
16}
17
18fn __mulkf3(a: f128, b: f128) callconv(.C) f128 {
19 return mulf3(f128, a, b);
20}
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/sparc.zig+3-3
......@@ -50,7 +50,7 @@ const FCMP = enum(i32) {
5050// Basic arithmetic
5151
5252pub fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.C) void {
53 c.* = @import("addXf3.zig").__addtf3(a.*, b.*);
53 c.* = @import("addf3.zig").__addtf3(a.*, b.*);
5454}
5555
5656pub fn _Qp_div(c: *f128, a: *f128, b: *f128) callconv(.C) void {
......@@ -58,11 +58,11 @@ pub fn _Qp_div(c: *f128, a: *f128, b: *f128) callconv(.C) void {
5858}
5959
6060pub fn _Qp_mul(c: *f128, a: *f128, b: *f128) callconv(.C) void {
61 c.* = @import("mulXf3.zig").__multf3(a.*, b.*);
61 c.* = @import("mulf3.zig").__multf3(a.*, b.*);
6262}
6363
6464pub fn _Qp_sub(c: *f128, a: *f128, b: *f128) callconv(.C) void {
65 c.* = @import("addXf3.zig").__subtf3(a.*, b.*);
65 c.* = @import("addf3.zig").__subtf3(a.*, b.*);
6666}
6767
6868// Comparison
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/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+21
......@@ -0,0 +1,21 @@
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 {
9 @export(__subtf3, .{ .name = "__subtf3", .linkage = common.linkage });
10 }
11}
12
13fn __subtf3(a: f128, b: f128) callconv(.C) f128 {
14 const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (@as(u128, 1) << 127));
15 return a + neg_b;
16}
17
18fn __subkf3(a: f128, b: f128) callconv(.C) f128 {
19 const neg_b = @bitCast(f128, @bitCast(u128, b) ^ (@as(u128, 1) << 127));
20 return a + neg_b;
21}
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/truncXfYf2.zig deleted-192
......@@ -1,192 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const arch = builtin.cpu.arch;
4const is_test = builtin.is_test;
5const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
6pub const panic = @import("common.zig").panic;
7
8comptime {
9 @export(__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage });
10 @export(__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage });
11 @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage });
12 @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage });
13
14 @export(__truncdfsf2, .{ .name = "__truncdfsf2", .linkage = linkage });
15 @export(__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage });
16
17 if (!is_test) {
18 @export(__gnu_f2h_ieee, .{ .name = "__gnu_f2h_ieee", .linkage = linkage });
19
20 if (arch.isARM() or arch.isThumb()) {
21 @export(__aeabi_d2h, .{ .name = "__aeabi_d2h", .linkage = linkage });
22 @export(__aeabi_f2h, .{ .name = "__aeabi_f2h", .linkage = linkage });
23 @export(__aeabi_d2f, .{ .name = "__aeabi_d2f", .linkage = linkage });
24 }
25
26 if (arch.isPPC() or arch.isPPC64()) {
27 @export(__trunckfsf2, .{ .name = "__trunckfsf2", .linkage = linkage });
28 @export(__trunckfdf2, .{ .name = "__trunckfdf2", .linkage = linkage });
29 }
30 }
31}
32
33// AArch64 is the only ABI (at the moment) to support f16 arguments without the
34// need for extending them to wider fp types.
35// TODO remove this; do this type selection in the language rather than
36// here in compiler-rt.
37const F16T = if (arch.isAARCH64()) f16 else u16;
38
39pub fn __truncsfhf2(a: f32) callconv(.C) F16T {
40 return @bitCast(F16T, truncXfYf2(f16, f32, a));
41}
42
43pub fn __gnu_f2h_ieee(a: f32) callconv(.C) F16T {
44 return @call(.{ .modifier = .always_inline }, __truncsfhf2, .{a});
45}
46
47pub fn __truncdfhf2(a: f64) callconv(.C) F16T {
48 return @bitCast(F16T, truncXfYf2(f16, f64, a));
49}
50
51pub fn __trunctfhf2(a: f128) callconv(.C) F16T {
52 return @bitCast(F16T, truncXfYf2(f16, f128, a));
53}
54
55pub fn __trunctfsf2(a: f128) callconv(.C) f32 {
56 return truncXfYf2(f32, f128, a);
57}
58
59pub fn __trunckfsf2(a: f128) callconv(.C) f32 {
60 return truncXfYf2(f32, f128, a);
61}
62
63pub fn __trunctfdf2(a: f128) callconv(.C) f64 {
64 return truncXfYf2(f64, f128, a);
65}
66
67pub fn __trunckfdf2(a: f128) callconv(.C) f64 {
68 return truncXfYf2(f64, f128, a);
69}
70
71pub fn __truncdfsf2(a: f64) callconv(.C) f32 {
72 return truncXfYf2(f32, f64, a);
73}
74
75pub fn __aeabi_d2f(a: f64) callconv(.AAPCS) f32 {
76 @setRuntimeSafety(false);
77 return truncXfYf2(f32, f64, a);
78}
79
80pub fn __aeabi_d2h(a: f64) callconv(.AAPCS) u16 {
81 @setRuntimeSafety(false);
82 return @bitCast(F16T, truncXfYf2(f16, f64, a));
83}
84
85pub fn __aeabi_f2h(a: f32) callconv(.AAPCS) u16 {
86 @setRuntimeSafety(false);
87 return @bitCast(F16T, truncXfYf2(f16, f32, a));
88}
89
90inline fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
91 const src_rep_t = std.meta.Int(.unsigned, @typeInfo(src_t).Float.bits);
92 const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits);
93 const srcSigBits = std.math.floatMantissaBits(src_t);
94 const dstSigBits = std.math.floatMantissaBits(dst_t);
95 const SrcShift = std.math.Log2Int(src_rep_t);
96
97 // Various constants whose values follow from the type parameters.
98 // Any reasonable optimizer will fold and propagate all of these.
99 const srcBits = @typeInfo(src_t).Float.bits;
100 const srcExpBits = srcBits - srcSigBits - 1;
101 const srcInfExp = (1 << srcExpBits) - 1;
102 const srcExpBias = srcInfExp >> 1;
103
104 const srcMinNormal = 1 << srcSigBits;
105 const srcSignificandMask = srcMinNormal - 1;
106 const srcInfinity = srcInfExp << srcSigBits;
107 const srcSignMask = 1 << (srcSigBits + srcExpBits);
108 const srcAbsMask = srcSignMask - 1;
109 const roundMask = (1 << (srcSigBits - dstSigBits)) - 1;
110 const halfway = 1 << (srcSigBits - dstSigBits - 1);
111 const srcQNaN = 1 << (srcSigBits - 1);
112 const srcNaNCode = srcQNaN - 1;
113
114 const dstBits = @typeInfo(dst_t).Float.bits;
115 const dstExpBits = dstBits - dstSigBits - 1;
116 const dstInfExp = (1 << dstExpBits) - 1;
117 const dstExpBias = dstInfExp >> 1;
118
119 const underflowExponent = srcExpBias + 1 - dstExpBias;
120 const overflowExponent = srcExpBias + dstInfExp - dstExpBias;
121 const underflow = underflowExponent << srcSigBits;
122 const overflow = overflowExponent << srcSigBits;
123
124 const dstQNaN = 1 << (dstSigBits - 1);
125 const dstNaNCode = dstQNaN - 1;
126
127 // Break a into a sign and representation of the absolute value
128 const aRep: src_rep_t = @bitCast(src_rep_t, a);
129 const aAbs: src_rep_t = aRep & srcAbsMask;
130 const sign: src_rep_t = aRep & srcSignMask;
131 var absResult: dst_rep_t = undefined;
132
133 if (aAbs -% underflow < aAbs -% overflow) {
134 // The exponent of a is within the range of normal numbers in the
135 // destination format. We can convert by simply right-shifting with
136 // rounding and adjusting the exponent.
137 absResult = @truncate(dst_rep_t, aAbs >> (srcSigBits - dstSigBits));
138 absResult -%= @as(dst_rep_t, srcExpBias - dstExpBias) << dstSigBits;
139
140 const roundBits: src_rep_t = aAbs & roundMask;
141 if (roundBits > halfway) {
142 // Round to nearest
143 absResult += 1;
144 } else if (roundBits == halfway) {
145 // Ties to even
146 absResult += absResult & 1;
147 }
148 } else if (aAbs > srcInfinity) {
149 // a is NaN.
150 // Conjure the result by beginning with infinity, setting the qNaN
151 // bit and inserting the (truncated) trailing NaN field.
152 absResult = @intCast(dst_rep_t, dstInfExp) << dstSigBits;
153 absResult |= dstQNaN;
154 absResult |= @intCast(dst_rep_t, ((aAbs & srcNaNCode) >> (srcSigBits - dstSigBits)) & dstNaNCode);
155 } else if (aAbs >= overflow) {
156 // a overflows to infinity.
157 absResult = @intCast(dst_rep_t, dstInfExp) << dstSigBits;
158 } else {
159 // a underflows on conversion to the destination type or is an exact
160 // zero. The result may be a denormal or zero. Extract the exponent
161 // to get the shift amount for the denormalization.
162 const aExp = @intCast(u32, aAbs >> srcSigBits);
163 const shift = @intCast(u32, srcExpBias - dstExpBias - aExp + 1);
164
165 const significand: src_rep_t = (aRep & srcSignificandMask) | srcMinNormal;
166
167 // Right shift by the denormalization amount with sticky.
168 if (shift > srcSigBits) {
169 absResult = 0;
170 } else {
171 const sticky: src_rep_t = @boolToInt(significand << @intCast(SrcShift, srcBits - shift) != 0);
172 const denormalizedSignificand: src_rep_t = significand >> @intCast(SrcShift, shift) | sticky;
173 absResult = @intCast(dst_rep_t, denormalizedSignificand >> (srcSigBits - dstSigBits));
174 const roundBits: src_rep_t = denormalizedSignificand & roundMask;
175 if (roundBits > halfway) {
176 // Round to nearest
177 absResult += 1;
178 } else if (roundBits == halfway) {
179 // Ties to even
180 absResult += absResult & 1;
181 }
182 }
183 }
184
185 const result: dst_rep_t align(@alignOf(dst_t)) = absResult |
186 @truncate(dst_rep_t, sign >> @intCast(SrcShift, srcBits - dstBits));
187 return @bitCast(dst_t, result);
188}
189
190test {
191 _ = @import("truncXfYf2_test.zig");
192}
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-183
......@@ -1,183 +0,0 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const arch = builtin.cpu.arch;
4const testing = std.testing;
5const is_test = builtin.is_test;
6const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
7pub const panic = @import("common.zig").panic;
8
9comptime {
10 @export(__truncxfhf2, .{ .name = "__truncxfhf2", .linkage = linkage });
11 @export(__truncxfsf2, .{ .name = "__truncxfsf2", .linkage = linkage });
12 @export(__truncxfdf2, .{ .name = "__truncxfdf2", .linkage = linkage });
13 @export(__trunctfxf2, .{ .name = "__trunctfxf2", .linkage = linkage });
14}
15
16// AArch64 is the only ABI (at the moment) to support f16 arguments without the
17// need for extending them to wider fp types.
18const F16T = if (arch.isAARCH64()) f16 else u16;
19
20pub fn __truncxfhf2(a: f80) callconv(.C) F16T {
21 return @bitCast(F16T, trunc(f16, a));
22}
23
24pub fn __truncxfsf2(a: f80) callconv(.C) f32 {
25 return trunc(f32, a);
26}
27
28pub fn __truncxfdf2(a: f80) callconv(.C) f64 {
29 return trunc(f64, a);
30}
31
32inline fn trunc(comptime dst_t: type, a: f80) dst_t {
33 @setRuntimeSafety(builtin.is_test);
34
35 const dst_rep_t = std.meta.Int(.unsigned, @typeInfo(dst_t).Float.bits);
36 const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
37 const dst_sig_bits = std.math.floatMantissaBits(dst_t);
38
39 const src_exp_bias = 16383;
40
41 const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1;
42 const halfway = 1 << (src_sig_bits - dst_sig_bits - 1);
43
44 const dst_bits = @typeInfo(dst_t).Float.bits;
45 const dst_exp_bits = dst_bits - dst_sig_bits - 1;
46 const dst_inf_exp = (1 << dst_exp_bits) - 1;
47 const dst_exp_bias = dst_inf_exp >> 1;
48
49 const underflow = src_exp_bias + 1 - dst_exp_bias;
50 const overflow = src_exp_bias + dst_inf_exp - dst_exp_bias;
51
52 const dst_qnan = 1 << (dst_sig_bits - 1);
53 const dst_nan_mask = dst_qnan - 1;
54
55 // Break a into a sign and representation of the absolute value
56 var a_rep = std.math.break_f80(a);
57 const sign = a_rep.exp & 0x8000;
58 a_rep.exp &= 0x7FFF;
59 a_rep.fraction &= 0x7FFFFFFFFFFFFFFF;
60 var abs_result: dst_rep_t = undefined;
61
62 if (a_rep.exp -% underflow < a_rep.exp -% overflow) {
63 // The exponent of a is within the range of normal numbers in the
64 // destination format. We can convert by simply right-shifting with
65 // rounding and adjusting the exponent.
66 abs_result = @as(dst_rep_t, a_rep.exp) << dst_sig_bits;
67 abs_result |= @truncate(dst_rep_t, a_rep.fraction >> (src_sig_bits - dst_sig_bits));
68 abs_result -%= @as(dst_rep_t, src_exp_bias - dst_exp_bias) << dst_sig_bits;
69
70 const round_bits = a_rep.fraction & round_mask;
71 if (round_bits > halfway) {
72 // Round to nearest
73 abs_result += 1;
74 } else if (round_bits == halfway) {
75 // Ties to even
76 abs_result += abs_result & 1;
77 }
78 } else if (a_rep.exp == 0x7FFF and a_rep.fraction != 0) {
79 // a is NaN.
80 // Conjure the result by beginning with infinity, setting the qNaN
81 // bit and inserting the (truncated) trailing NaN field.
82 abs_result = @intCast(dst_rep_t, dst_inf_exp) << dst_sig_bits;
83 abs_result |= dst_qnan;
84 abs_result |= @intCast(dst_rep_t, (a_rep.fraction >> (src_sig_bits - dst_sig_bits)) & dst_nan_mask);
85 } else if (a_rep.exp >= overflow) {
86 // a overflows to infinity.
87 abs_result = @intCast(dst_rep_t, dst_inf_exp) << dst_sig_bits;
88 } else {
89 // a underflows on conversion to the destination type or is an exact
90 // zero. The result may be a denormal or zero. Extract the exponent
91 // to get the shift amount for the denormalization.
92 const shift = src_exp_bias - dst_exp_bias - a_rep.exp;
93
94 // Right shift by the denormalization amount with sticky.
95 if (shift > src_sig_bits) {
96 abs_result = 0;
97 } else {
98 const sticky = @boolToInt(a_rep.fraction << @intCast(u6, shift) != 0);
99 const denormalized_significand = a_rep.fraction >> @intCast(u6, shift) | sticky;
100 abs_result = @intCast(dst_rep_t, denormalized_significand >> (src_sig_bits - dst_sig_bits));
101 const round_bits = denormalized_significand & round_mask;
102 if (round_bits > halfway) {
103 // Round to nearest
104 abs_result += 1;
105 } else if (round_bits == halfway) {
106 // Ties to even
107 abs_result += abs_result & 1;
108 }
109 }
110 }
111
112 const result align(@alignOf(dst_t)) = abs_result | @as(dst_rep_t, sign) << dst_bits - 16;
113 return @bitCast(dst_t, result);
114}
115
116pub fn __trunctfxf2(a: f128) callconv(.C) f80 {
117 const src_sig_bits = std.math.floatMantissaBits(f128);
118 const dst_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit
119
120 // Various constants whose values follow from the type parameters.
121 // Any reasonable optimizer will fold and propagate all of these.
122 const src_bits = @typeInfo(f128).Float.bits;
123 const src_exp_bits = src_bits - src_sig_bits - 1;
124 const src_inf_exp = 0x7FFF;
125
126 const src_inf = src_inf_exp << src_sig_bits;
127 const src_sign_mask = 1 << (src_sig_bits + src_exp_bits);
128 const src_abs_mask = src_sign_mask - 1;
129 const round_mask = (1 << (src_sig_bits - dst_sig_bits)) - 1;
130 const halfway = 1 << (src_sig_bits - dst_sig_bits - 1);
131
132 // Break a into a sign and representation of the absolute value
133 const a_rep = @bitCast(u128, a);
134 const a_abs = a_rep & src_abs_mask;
135 const sign: u16 = if (a_rep & src_sign_mask != 0) 0x8000 else 0;
136 const integer_bit = 1 << 63;
137
138 var res: std.math.F80 = undefined;
139
140 if (a_abs > src_inf) {
141 // a is NaN.
142 // Conjure the result by beginning with infinity, setting the qNaN
143 // bit and inserting the (truncated) trailing NaN field.
144 res.exp = 0x7fff;
145 res.fraction = 0x8000000000000000;
146 res.fraction |= @truncate(u64, a_abs >> (src_sig_bits - dst_sig_bits));
147 } else {
148 // The exponent of a is within the range of normal numbers in the
149 // destination format. We can convert by simply right-shifting with
150 // rounding, adding the explicit integer bit, and adjusting the exponent
151 res.fraction = @truncate(u64, a_abs >> (src_sig_bits - dst_sig_bits)) | integer_bit;
152 res.exp = @truncate(u16, a_abs >> src_sig_bits);
153
154 const round_bits = a_abs & round_mask;
155 if (round_bits > halfway) {
156 // Round to nearest
157 const carry = @boolToInt(@addWithOverflow(u64, res.fraction, 1, &res.fraction));
158 res.exp += carry;
159 res.fraction |= @as(u64, carry) << 63; // Restore integer bit after carry
160 } else if (round_bits == halfway) {
161 // Ties to even
162 const carry = @boolToInt(@addWithOverflow(u64, res.fraction, res.fraction & 1, &res.fraction));
163 res.exp += carry;
164 res.fraction |= @as(u64, carry) << 63; // Restore integer bit after carry
165 }
166 if (res.exp == 0) res.fraction &= ~@as(u64, integer_bit); // Remove integer bit for de-normals
167 }
168
169 res.exp |= sign;
170 return std.math.make_f80(res);
171}
172
173fn test__trunctfxf2(a: f128, expected: f80) !void {
174 const x = __trunctfxf2(a);
175 try testing.expect(x == expected);
176}
177
178test {
179 try test__trunctfxf2(1.5, 1.5);
180 try test__trunctfxf2(2.5, 2.5);
181 try test__trunctfxf2(-2.5, -2.5);
182 try test__trunctfxf2(0.0, 0.0);
183}
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
14fn __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
14fn __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+310
......@@ -0,0 +1,310 @@
1const std = @import("std");
2const testing = std.testing;
3const __truncsfhf2 = @import("truncXfYf2.zig").__truncsfhf2;
4const __trunctfxf2 = @import("trunctfxf2.zig").__trunctfxf2;
5
6fn test__truncsfhf2(a: u32, expected: u16) !void {
7 const actual = @bitCast(u16, __truncsfhf2(@bitCast(f32, a)));
8
9 if (actual == expected) {
10 return;
11 }
12
13 return error.TestFailure;
14}
15
16test "truncsfhf2" {
17 try test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN
18 try test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN
19
20 try test__truncsfhf2(0, 0); // 0
21 try test__truncsfhf2(0x80000000, 0x8000); // -0
22
23 try test__truncsfhf2(0x7f800000, 0x7c00); // inf
24 try test__truncsfhf2(0xff800000, 0xfc00); // -inf
25
26 try test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf
27 try test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf
28
29 try test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf
30 try test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf
31
32 try test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14
33 try test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14
34
35 try test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504
36 try test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504
37
38 try test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504
39 try test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504
40
41 try test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504
42 try test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504
43
44 try test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10
45 try test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10
46
47 try test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3
48 try test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3
49
50 try test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535
51 try test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535
52
53 try test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12
54
55 try test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1
56 try test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14
57
58 try test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24
59 try test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24
60
61 try test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24
62 try test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24
63
64 try test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20
65 try test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24
66 try test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero
67}
68
69const __truncdfhf2 = @import("truncXfYf2.zig").__truncdfhf2;
70
71fn test__truncdfhf2(a: f64, expected: u16) void {
72 const rep = @bitCast(u16, __truncdfhf2(a));
73
74 if (rep == expected) {
75 return;
76 }
77 // test other possible NaN representation(signal NaN)
78 else if (expected == 0x7e00) {
79 if ((rep & 0x7c00) == 0x7c00 and (rep & 0x3ff) > 0) {
80 return;
81 }
82 }
83
84 @panic("__truncdfhf2 test failure");
85}
86
87fn test__truncdfhf2_raw(a: u64, expected: u16) void {
88 const actual = @bitCast(u16, __truncdfhf2(@bitCast(f64, a)));
89
90 if (actual == expected) {
91 return;
92 }
93
94 @panic("__truncdfhf2 test failure");
95}
96
97test "truncdfhf2" {
98 test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN
99 test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN
100
101 test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf
102 test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf
103
104 test__truncdfhf2(0.0, 0x0); // zero
105 test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero
106
107 test__truncdfhf2(3.1415926535, 0x4248);
108 test__truncdfhf2(-3.1415926535, 0xc248);
109
110 test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00);
111 test__truncdfhf2(0x1.987124876876324p+12, 0x6e62);
112 test__truncdfhf2(0x1.0p+0, 0x3c00);
113 test__truncdfhf2(0x1.0p-14, 0x0400);
114
115 // denormal
116 test__truncdfhf2(0x1.0p-20, 0x0010);
117 test__truncdfhf2(0x1.0p-24, 0x0001);
118 test__truncdfhf2(-0x1.0p-24, 0x8001);
119 test__truncdfhf2(0x1.5p-25, 0x0001);
120
121 // and back to zero
122 test__truncdfhf2(0x1.0p-25, 0x0000);
123 test__truncdfhf2(-0x1.0p-25, 0x8000);
124
125 // max (precise)
126 test__truncdfhf2(65504.0, 0x7bff);
127
128 // max (rounded)
129 test__truncdfhf2(65519.0, 0x7bff);
130
131 // max (to +inf)
132 test__truncdfhf2(65520.0, 0x7c00);
133 test__truncdfhf2(-65520.0, 0xfc00);
134 test__truncdfhf2(65536.0, 0x7c00);
135}
136
137const __trunctfsf2 = @import("truncXfYf2.zig").__trunctfsf2;
138
139fn test__trunctfsf2(a: f128, expected: u32) void {
140 const x = __trunctfsf2(a);
141
142 const rep = @bitCast(u32, x);
143 if (rep == expected) {
144 return;
145 }
146 // test other possible NaN representation(signal NaN)
147 else if (expected == 0x7fc00000) {
148 if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) {
149 return;
150 }
151 }
152
153 @panic("__trunctfsf2 test failure");
154}
155
156test "trunctfsf2" {
157 // qnan
158 test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff800000000000 << 64)), 0x7fc00000);
159 // nan
160 test__trunctfsf2(@bitCast(f128, @as(u128, (0x7fff000000000000 | (0x810000000000 & 0xffffffffffff)) << 64)), 0x7fc08000);
161 // inf
162 test__trunctfsf2(@bitCast(f128, @as(u128, 0x7fff000000000000 << 64)), 0x7f800000);
163 // zero
164 test__trunctfsf2(0.0, 0x0);
165
166 test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156);
167 test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2);
168 test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000);
169 test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0);
170}
171
172const __trunctfdf2 = @import("truncXfYf2.zig").__trunctfdf2;
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
207const __truncdfsf2 = @import("truncXfYf2.zig").__truncdfsf2;
208
209fn test__truncdfsf2(a: f64, expected: u32) void {
210 const x = __truncdfsf2(a);
211
212 const rep = @bitCast(u32, x);
213 if (rep == expected) {
214 return;
215 }
216 // test other possible NaN representation(signal NaN)
217 else if (expected == 0x7fc00000) {
218 if ((rep & 0x7f800000) == 0x7f800000 and (rep & 0x7fffff) > 0) {
219 return;
220 }
221 }
222
223 std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
224
225 @panic("__trunctfsf2 test failure");
226}
227
228test "truncdfsf2" {
229 // nan & qnan
230 test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff8000000000000)), 0x7fc00000);
231 test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff0000000000001)), 0x7fc00000);
232 // inf
233 test__truncdfsf2(@bitCast(f64, @as(u64, 0x7ff0000000000000)), 0x7f800000);
234 test__truncdfsf2(@bitCast(f64, @as(u64, 0xfff0000000000000)), 0xff800000);
235
236 test__truncdfsf2(0.0, 0x0);
237 test__truncdfsf2(1.0, 0x3f800000);
238 test__truncdfsf2(-1.0, 0xbf800000);
239
240 // huge number becomes inf
241 test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);
242}
243
244const __trunctfhf2 = @import("truncXfYf2.zig").__trunctfhf2;
245
246fn test__trunctfhf2(a: f128, expected: u16) void {
247 const x = __trunctfhf2(a);
248
249 const rep = @bitCast(u16, x);
250 if (rep == expected) {
251 return;
252 }
253
254 std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
255
256 @panic("__trunctfhf2 test failure");
257}
258
259test "trunctfhf2" {
260 // qNaN
261 test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);
262 // NaN
263 test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);
264 // inf
265 test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);
266 test__trunctfhf2(-@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0xfc00);
267 // zero
268 test__trunctfhf2(0.0, 0x0);
269 test__trunctfhf2(-0.0, 0x8000);
270
271 test__trunctfhf2(3.1415926535, 0x4248);
272 test__trunctfhf2(-3.1415926535, 0xc248);
273 test__trunctfhf2(0x1.987124876876324p+100, 0x7c00);
274 test__trunctfhf2(0x1.987124876876324p+12, 0x6e62);
275 test__trunctfhf2(0x1.0p+0, 0x3c00);
276 test__trunctfhf2(0x1.0p-14, 0x0400);
277 // denormal
278 test__trunctfhf2(0x1.0p-20, 0x0010);
279 test__trunctfhf2(0x1.0p-24, 0x0001);
280 test__trunctfhf2(-0x1.0p-24, 0x8001);
281 test__trunctfhf2(0x1.5p-25, 0x0001);
282 // and back to zero
283 test__trunctfhf2(0x1.0p-25, 0x0000);
284 test__trunctfhf2(-0x1.0p-25, 0x8000);
285 // max (precise)
286 test__trunctfhf2(65504.0, 0x7bff);
287 // max (rounded)
288 test__trunctfhf2(65519.0, 0x7bff);
289 // max (to +inf)
290 test__trunctfhf2(65520.0, 0x7c00);
291 test__trunctfhf2(65536.0, 0x7c00);
292 test__trunctfhf2(-65520.0, 0xfc00);
293
294 test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);
295 test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);
296 test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);
297 test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);
298}
299
300test "trunctfxf2" {
301 try test__trunctfxf2(1.5, 1.5);
302 try test__trunctfxf2(2.5, 2.5);
303 try test__trunctfxf2(-2.5, -2.5);
304 try test__trunctfxf2(0.0, 0.0);
305}
306
307fn test__trunctfxf2(a: f128, expected: f80) !void {
308 const x = __trunctfxf2(a);
309 try testing.expect(x == expected);
310}
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.want_gnu_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
16fn __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+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_ppc_abi) {
8 @export(__trunckfdf2, .{ .name = "__trunckfdf2", .linkage = common.linkage });
9 } else {
10 @export(__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = common.linkage });
11 }
12}
13
14fn __trunctfdf2(a: f128) callconv(.C) f64 {
15 return truncf(f64, f128, a);
16}
17
18fn __trunckfdf2(a: f128) callconv(.C) f64 {
19 return truncf(f64, f128, a);
20}
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
10fn __trunctfhf2(a: f128) callconv(.C) common.F16T {
11 return @bitCast(common.F16T, truncf(f16, f128, a));
12}
lib/compiler_rt/trunctfsf2.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_ppc_abi) {
8 @export(__trunckfsf2, .{ .name = "__trunckfsf2", .linkage = common.linkage });
9 } else {
10 @export(__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = common.linkage });
11 }
12}
13
14fn __trunctfsf2(a: f128) callconv(.C) f32 {
15 return truncf(f32, f128, a);
16}
17
18fn __trunckfsf2(a: f128) callconv(.C) f32 {
19 return truncf(f32, f128, a);
20}
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
11fn __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/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
14fn __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
14fn __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+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_ppc_abi) {
8 @export(__unordkf2, .{ .name = "__unordkf2", .linkage = common.linkage });
9 } else {
10 @export(__unordtf2, .{ .name = "__unordtf2", .linkage = common.linkage });
11 }
12}
13
14fn __unordtf2(a: f128, b: f128) callconv(.C) i32 {
15 return comparef.unordcmp(f128, a, b);
16}
17
18fn __unordkf2(a: f128, b: f128) callconv(.C) i32 {
19 return comparef.unordcmp(f128, a, b);
20}
src/compiler_rt.zig+2-2
......@@ -200,8 +200,8 @@ const sources = &[_][]const u8{
200200 "compiler_rt/umodti3.zig",
201201 "compiler_rt/truncXfYf2.zig",
202202 "compiler_rt/trunc_f80.zig",
203 "compiler_rt/addXf3.zig",
204 "compiler_rt/mulXf3.zig",
203 "compiler_rt/addf3.zig",
204 "compiler_rt/mulf3.zig",
205205 "compiler_rt/divsf3.zig",
206206 "compiler_rt/divdf3.zig",
207207 "compiler_rt/divxf3.zig",