| author | |
| committer | |
| log | 5d89955543d30b851777ff119160e480d04a6f0e |
| tree | 2bb1bcaa2c4676a4e627fd743cc1145ea4555318 |
| parent | ecf56d85efa227acf1bd9cab9ad2d5af05f7efe5 |
* goals
- zig as linker for object files generated by other compilers
- zig-specific runtime features for eventual standardisation
* changes
- missing routines are marked with `missing`
- structure inspired by libgcc docs, but improved order and wording
- rename misspelled functions
- reorder and rephrase compiler_rt.zig to reflect documentation
- potential decimal float or fixed-point arithmetic support:
* 'Decimal float library routines' ca. 120 functions
* 'Fixed-point fractional library routines' ca. 300 functions
thanks to @Vexu for multiple reviews and @scheibo for review5 files changed, 305 insertions(+), 58 deletions(-)
lib/std/special/compiler_rt.zig+40-45| ... | ... | @@ -41,8 +41,8 @@ comptime { |
| 41 | 41 | |
| 42 | 42 | const __extendhfxf2 = @import("compiler_rt/extend_f80.zig").__extendhfxf2; |
| 43 | 43 | @export(__extendhfxf2, .{ .name = "__extendhfxf2", .linkage = linkage }); |
| 44 | const __extendffxf2 = @import("compiler_rt/extend_f80.zig").__extendffxf2; | |
| 45 | @export(__extendffxf2, .{ .name = "__extendffxf2", .linkage = linkage }); | |
| 44 | const __extendsfxf2 = @import("compiler_rt/extend_f80.zig").__extendsfxf2; | |
| 45 | @export(__extendsfxf2, .{ .name = "__extendsfxf2", .linkage = linkage }); | |
| 46 | 46 | const __extenddfxf2 = @import("compiler_rt/extend_f80.zig").__extenddfxf2; |
| 47 | 47 | @export(__extenddfxf2, .{ .name = "__extenddfxf2", .linkage = linkage }); |
| 48 | 48 | const __extendxftf2 = @import("compiler_rt/extend_f80.zig").__extendxftf2; |
| ... | ... | @@ -105,26 +105,6 @@ comptime { |
| 105 | 105 | @export(__extendhfsf2, .{ .name = "__gnu_h2f_ieee", .linkage = linkage }); |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | // Integral arithmetic which returns if overflow | |
| 109 | const __addosi4 = @import("compiler_rt/addo.zig").__addosi4; | |
| 110 | @export(__addosi4, .{ .name = "__addosi4", .linkage = linkage }); | |
| 111 | const __addodi4 = @import("compiler_rt/addo.zig").__addodi4; | |
| 112 | @export(__addodi4, .{ .name = "__addodi4", .linkage = linkage }); | |
| 113 | const __addoti4 = @import("compiler_rt/addo.zig").__addoti4; | |
| 114 | @export(__addoti4, .{ .name = "__addoti4", .linkage = linkage }); | |
| 115 | const __subosi4 = @import("compiler_rt/subo.zig").__subosi4; | |
| 116 | @export(__subosi4, .{ .name = "__subosi4", .linkage = linkage }); | |
| 117 | const __subodi4 = @import("compiler_rt/subo.zig").__subodi4; | |
| 118 | @export(__subodi4, .{ .name = "__subodi4", .linkage = linkage }); | |
| 119 | const __suboti4 = @import("compiler_rt/subo.zig").__suboti4; | |
| 120 | @export(__suboti4, .{ .name = "__suboti4", .linkage = linkage }); | |
| 121 | const __mulosi4 = @import("compiler_rt/mulo.zig").__mulosi4; | |
| 122 | @export(__mulosi4, .{ .name = "__mulosi4", .linkage = linkage }); | |
| 123 | const __mulodi4 = @import("compiler_rt/mulo.zig").__mulodi4; | |
| 124 | @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); | |
| 125 | const __muloti4 = @import("compiler_rt/mulo.zig").__muloti4; | |
| 126 | @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage }); | |
| 127 | ||
| 128 | 108 | if (builtin.os.tag == .windows) { |
| 129 | 109 | // Default stack-probe functions emitted by LLVM |
| 130 | 110 | if (is_mingw) { |
| ... | ... | @@ -214,8 +194,8 @@ comptime { |
| 214 | 194 | |
| 215 | 195 | const __truncxfhf2 = @import("compiler_rt/trunc_f80.zig").__truncxfhf2; |
| 216 | 196 | @export(__truncxfhf2, .{ .name = "__truncxfhf2", .linkage = linkage }); |
| 217 | const __truncxfff2 = @import("compiler_rt/trunc_f80.zig").__truncxfff2; | |
| 218 | @export(__truncxfff2, .{ .name = "__truncxfff2", .linkage = linkage }); | |
| 197 | const __truncxfsf2 = @import("compiler_rt/trunc_f80.zig").__truncxfsf2; | |
| 198 | @export(__truncxfsf2, .{ .name = "__truncxfsf2", .linkage = linkage }); | |
| 219 | 199 | const __truncxfdf2 = @import("compiler_rt/trunc_f80.zig").__truncxfdf2; |
| 220 | 200 | @export(__truncxfdf2, .{ .name = "__truncxfdf2", .linkage = linkage }); |
| 221 | 201 | const __trunctfxf2 = @import("compiler_rt/trunc_f80.zig").__trunctfxf2; |
| ... | ... | @@ -274,20 +254,7 @@ comptime { |
| 274 | 254 | const __divtf3 = @import("compiler_rt/divtf3.zig").__divtf3; |
| 275 | 255 | @export(__divtf3, .{ .name = "__divtf3", .linkage = linkage }); |
| 276 | 256 | |
| 277 | // Integral bit manipulation | |
| 278 | const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3; | |
| 279 | @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage }); | |
| 280 | const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3; | |
| 281 | @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage }); | |
| 282 | const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3; | |
| 283 | @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage }); | |
| 284 | const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3; | |
| 285 | @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage }); | |
| 286 | const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3; | |
| 287 | @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage }); | |
| 288 | const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3; | |
| 289 | @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage }); | |
| 290 | ||
| 257 | // Integer Bit operations | |
| 291 | 258 | const __clzsi2 = @import("compiler_rt/count0bits.zig").__clzsi2; |
| 292 | 259 | @export(__clzsi2, .{ .name = "__clzsi2", .linkage = linkage }); |
| 293 | 260 | const __clzdi2 = @import("compiler_rt/count0bits.zig").__clzdi2; |
| ... | ... | @@ -306,21 +273,18 @@ comptime { |
| 306 | 273 | @export(__ffsdi2, .{ .name = "__ffsdi2", .linkage = linkage }); |
| 307 | 274 | const __ffsti2 = @import("compiler_rt/count0bits.zig").__ffsti2; |
| 308 | 275 | @export(__ffsti2, .{ .name = "__ffsti2", .linkage = linkage }); |
| 309 | ||
| 310 | 276 | const __paritysi2 = @import("compiler_rt/parity.zig").__paritysi2; |
| 311 | 277 | @export(__paritysi2, .{ .name = "__paritysi2", .linkage = linkage }); |
| 312 | 278 | const __paritydi2 = @import("compiler_rt/parity.zig").__paritydi2; |
| 313 | 279 | @export(__paritydi2, .{ .name = "__paritydi2", .linkage = linkage }); |
| 314 | 280 | const __parityti2 = @import("compiler_rt/parity.zig").__parityti2; |
| 315 | 281 | @export(__parityti2, .{ .name = "__parityti2", .linkage = linkage }); |
| 316 | ||
| 317 | 282 | const __popcountsi2 = @import("compiler_rt/popcount.zig").__popcountsi2; |
| 318 | 283 | @export(__popcountsi2, .{ .name = "__popcountsi2", .linkage = linkage }); |
| 319 | 284 | const __popcountdi2 = @import("compiler_rt/popcount.zig").__popcountdi2; |
| 320 | 285 | @export(__popcountdi2, .{ .name = "__popcountdi2", .linkage = linkage }); |
| 321 | 286 | const __popcountti2 = @import("compiler_rt/popcount.zig").__popcountti2; |
| 322 | 287 | @export(__popcountti2, .{ .name = "__popcountti2", .linkage = linkage }); |
| 323 | ||
| 324 | 288 | const __bswapsi2 = @import("compiler_rt/bswap.zig").__bswapsi2; |
| 325 | 289 | @export(__bswapsi2, .{ .name = "__bswapsi2", .linkage = linkage }); |
| 326 | 290 | const __bswapdi2 = @import("compiler_rt/bswap.zig").__bswapdi2; |
| ... | ... | @@ -429,13 +393,26 @@ comptime { |
| 429 | 393 | @export(__isPlatformVersionAtLeast, .{ .name = "__isPlatformVersionAtLeast", .linkage = linkage }); |
| 430 | 394 | } |
| 431 | 395 | |
| 432 | // Integral arithmetic | |
| 396 | // Integer Arithmetic | |
| 397 | const __ashldi3 = @import("compiler_rt/shift.zig").__ashldi3; | |
| 398 | @export(__ashldi3, .{ .name = "__ashldi3", .linkage = linkage }); | |
| 399 | const __ashlti3 = @import("compiler_rt/shift.zig").__ashlti3; | |
| 400 | @export(__ashlti3, .{ .name = "__ashlti3", .linkage = linkage }); | |
| 401 | const __ashrdi3 = @import("compiler_rt/shift.zig").__ashrdi3; | |
| 402 | @export(__ashrdi3, .{ .name = "__ashrdi3", .linkage = linkage }); | |
| 403 | const __ashrti3 = @import("compiler_rt/shift.zig").__ashrti3; | |
| 404 | @export(__ashrti3, .{ .name = "__ashrti3", .linkage = linkage }); | |
| 405 | const __lshrdi3 = @import("compiler_rt/shift.zig").__lshrdi3; | |
| 406 | @export(__lshrdi3, .{ .name = "__lshrdi3", .linkage = linkage }); | |
| 407 | const __lshrti3 = @import("compiler_rt/shift.zig").__lshrti3; | |
| 408 | @export(__lshrti3, .{ .name = "__lshrti3", .linkage = linkage }); | |
| 433 | 409 | const __negsi2 = @import("compiler_rt/negXi2.zig").__negsi2; |
| 434 | 410 | @export(__negsi2, .{ .name = "__negsi2", .linkage = linkage }); |
| 435 | 411 | const __negdi2 = @import("compiler_rt/negXi2.zig").__negdi2; |
| 436 | 412 | @export(__negdi2, .{ .name = "__negdi2", .linkage = linkage }); |
| 437 | 413 | const __negti2 = @import("compiler_rt/negXi2.zig").__negti2; |
| 438 | 414 | @export(__negti2, .{ .name = "__negti2", .linkage = linkage }); |
| 415 | ||
| 439 | 416 | const __mulsi3 = @import("compiler_rt/int.zig").__mulsi3; |
| 440 | 417 | @export(__mulsi3, .{ .name = "__mulsi3", .linkage = linkage }); |
| 441 | 418 | const __muldi3 = @import("compiler_rt/muldi3.zig").__muldi3; |
| ... | ... | @@ -463,7 +440,7 @@ comptime { |
| 463 | 440 | const __udivmodsi4 = @import("compiler_rt/int.zig").__udivmodsi4; |
| 464 | 441 | @export(__udivmodsi4, .{ .name = "__udivmodsi4", .linkage = linkage }); |
| 465 | 442 | |
| 466 | // Integral arithmetic with trapping overflow | |
| 443 | // Integer Arithmetic with trapping overflow | |
| 467 | 444 | const __absvsi2 = @import("compiler_rt/absv.zig").__absvsi2; |
| 468 | 445 | @export(__absvsi2, .{ .name = "__absvsi2", .linkage = linkage }); |
| 469 | 446 | const __absvdi2 = @import("compiler_rt/absv.zig").__absvdi2; |
| ... | ... | @@ -477,9 +454,27 @@ comptime { |
| 477 | 454 | const __negvti2 = @import("compiler_rt/negv.zig").__negvti2; |
| 478 | 455 | @export(__negvti2, .{ .name = "__negvti2", .linkage = linkage }); |
| 479 | 456 | |
| 480 | // missing: Integral arithmetic which returns if overflow | |
| 457 | // Integer arithmetic which returns if overflow | |
| 458 | const __addosi4 = @import("compiler_rt/addo.zig").__addosi4; | |
| 459 | @export(__addosi4, .{ .name = "__addosi4", .linkage = linkage }); | |
| 460 | const __addodi4 = @import("compiler_rt/addo.zig").__addodi4; | |
| 461 | @export(__addodi4, .{ .name = "__addodi4", .linkage = linkage }); | |
| 462 | const __addoti4 = @import("compiler_rt/addo.zig").__addoti4; | |
| 463 | @export(__addoti4, .{ .name = "__addoti4", .linkage = linkage }); | |
| 464 | const __subosi4 = @import("compiler_rt/subo.zig").__subosi4; | |
| 465 | @export(__subosi4, .{ .name = "__subosi4", .linkage = linkage }); | |
| 466 | const __subodi4 = @import("compiler_rt/subo.zig").__subodi4; | |
| 467 | @export(__subodi4, .{ .name = "__subodi4", .linkage = linkage }); | |
| 468 | const __suboti4 = @import("compiler_rt/subo.zig").__suboti4; | |
| 469 | @export(__suboti4, .{ .name = "__suboti4", .linkage = linkage }); | |
| 470 | const __mulosi4 = @import("compiler_rt/mulo.zig").__mulosi4; | |
| 471 | @export(__mulosi4, .{ .name = "__mulosi4", .linkage = linkage }); | |
| 472 | const __mulodi4 = @import("compiler_rt/mulo.zig").__mulodi4; | |
| 473 | @export(__mulodi4, .{ .name = "__mulodi4", .linkage = linkage }); | |
| 474 | const __muloti4 = @import("compiler_rt/mulo.zig").__muloti4; | |
| 475 | @export(__muloti4, .{ .name = "__muloti4", .linkage = linkage }); | |
| 481 | 476 | |
| 482 | // Integral comparison | |
| 477 | // Integer Comparison | |
| 483 | 478 | // (a < b) => 0 |
| 484 | 479 | // (a == b) => 1 |
| 485 | 480 | // (a > b) => 2 |
lib/std/special/compiler_rt/README.md+261-9| ... | ... | @@ -1,15 +1,267 @@ |
| 1 | This compiler-rt library is ported from [LLVM](http://compiler-rt.llvm.org/). | |
| 1 | If hardware lacks basic or specialized functionality, compiler-rt adds such functionality | |
| 2 | for basic arithmetic(s). | |
| 3 | One such example is 64-bit integer multiplication on 32-bit x86. | |
| 2 | 4 | |
| 3 | It's needed because LLVM emits library calls to compiler-rt when hardware lacks | |
| 4 | functionality, for example, 64-bit integer multiplication on 32-bit x86. | |
| 5 | Goals: | |
| 6 | 1. zig as linker for object files produced by other compilers | |
| 7 | => `function compatibility` to compiler-rt and libgcc for same-named functions | |
| 8 | * compatibility conflict between compiler-rt and libgcc: prefer compiler-rt | |
| 9 | 2. `symbol-level compatibility` low-priority compared to emitted calls by llvm | |
| 10 | * symbol-level compatibility: libgcc even lower priority | |
| 11 | 3. add zig-specific language runtime features, see #7265 | |
| 12 | * example: arbitrary bit width integer arithmetic | |
| 13 | * lower to call those functions for e.g. multiplying two i12345 numbers together | |
| 14 | * proper naming + documention for standardizing (allow languages to follow our exmaple) | |
| 15 | ||
| 16 | Current status (tracking libgcc documentation): | |
| 17 | - Integer library routines => almost implemented | |
| 18 | - Soft float library routines => only f80 routines missing | |
| 19 | - Decimal float library routines => unimplemented (~120 functions) | |
| 20 | - Fixed-point fractional library routines => unimplemented (~300 functions) | |
| 21 | - Exception handling routines => unclear, if supported (~32+x undocumented functions) | |
| 22 | - Miscellaneous routines => unclear, if supported (cache control and stack function) | |
| 23 | - No zig-specific language runtime features in compiler-rt yet | |
| 5 | 24 | |
| 6 | 25 | This library is automatically built as-needed for the compilation target and |
| 7 | 26 | then statically linked and therefore is a transparent dependency for the |
| 8 | 27 | programmer. |
| 28 | For details see `../compiler_rt.zig`. | |
| 29 | ||
| 30 | The routines in this folder are listed below. | |
| 31 | Routines are annotated as `type source routine // description`, with `routine` | |
| 32 | being the name used in aforementioned `compiler_rt.zig`. | |
| 33 | `dev` means deviating from compiler_rt, `port` ported, `source` is the | |
| 34 | information source for the implementation, `none` means unimplemented. | |
| 35 | Some examples for the naming convention are: | |
| 36 | - dev source name_routine, name_routine2 various implementations for performance, simplicity etc | |
| 37 | - port llvm compiler-rt library routines from [LLVM](http://compiler-rt.llvm.org/) | |
| 38 | * LLVM emits library calls to compiler-rt, if the hardware lacks functionality | |
| 39 | - port musl libc routines from [musl](https://musl.libc.org/) | |
| 40 | If the library or information source is uncommon, use the entry `other` for `source`. | |
| 41 | Please do not break the search by inserting entries in another format than `impl space source`. | |
| 42 | ||
| 43 | Bugs should be solved by trying to duplicate the bug upstream, if possible. | |
| 44 | * If the bug exists upstream, get it fixed upstream and port the fix downstream to Zig. | |
| 45 | * If the bug only exists in Zig, use the corresponding C code and debug | |
| 46 | both implementations side by side to figure out what is wrong. | |
| 47 | ||
| 48 | ## Integer library routines | |
| 49 | ||
| 50 | #### Integer Bit operations | |
| 51 | - dev HackersDelight __clzsi2 // count leading zeros | |
| 52 | - dev HackersDelight __clzdi2 // count leading zeros | |
| 53 | - dev HackersDelight __clzti2 // count leading zeros | |
| 54 | - dev HackersDelight __ctzsi2 // count trailing zeros | |
| 55 | - dev HackersDelight __ctzdi2 // count trailing zeros | |
| 56 | - dev HackersDelight __ctzti2 // count trailing zeros | |
| 57 | - dev __ctzsi2 __ffssi2 // find least significant 1 bit | |
| 58 | - dev __ctzsi2 __ffsdi2 // find least significant 1 bit | |
| 59 | - dev __ctzsi2 __ffsti2 // find least significant 1 bit | |
| 60 | - dev BitTwiddlingHacks __paritysi2 // bit parity | |
| 61 | - dev BitTwiddlingHacks __paritydi2 // bit parity | |
| 62 | - dev BitTwiddlingHacks __parityti2 // bit parity | |
| 63 | - dev TAOCP __popcountsi2 // bit population | |
| 64 | - dev TAOCP __popcountdi2 // bit population | |
| 65 | - dev TAOCP __popcountti2 // bit population | |
| 66 | - dev other __bswapsi2 // a byteswapped | |
| 67 | - dev other __bswapdi2 // a byteswapped | |
| 68 | - dev other __bswapti2 // a byteswapped | |
| 69 | ||
| 70 | #### Integer Comparison | |
| 71 | - port llvm __cmpsi2 // (a<b)=>output=0, (a==b)=>output=1, (a>b)=>output=2 | |
| 72 | - port llvm __cmpdi2 | |
| 73 | - port llvm __cmpti2 | |
| 74 | - port llvm __ucmpsi2 // (a<b)=>output=0, (a==b)=>output=1, (a>b)=>output=2 | |
| 75 | - port llvm __ucmpdi2 | |
| 76 | - port llvm __ucmpti2 | |
| 77 | ||
| 78 | #### Integer Arithmetic | |
| 79 | - none none __ashlsi3 // a << b unused in llvm, missing (e.g. used by rl78) | |
| 80 | - port llvm __ashldi3 // a << b | |
| 81 | - port llvm __ashlti3 // a << b | |
| 82 | - none none __ashrsi3 // a >> b arithmetic (sign fill) missing (e.g. used by rl78) | |
| 83 | - port llvm __ashrdi3 // a >> b arithmetic (sign fill) | |
| 84 | - port llvm __ashrti3 // a >> b arithmetic (sign fill) | |
| 85 | - none none __lshrsi3 // a >> b logical (zero fill) missing (e.g. used by rl78) | |
| 86 | - port llvm __lshrdi3 // a >> b logical (zero fill) | |
| 87 | - port llvm __lshrti3 // a >> b logical (zero fill) | |
| 88 | - port llvm __negdi2 // -a symbol-level compatibility: libgcc | |
| 89 | - port llvm __negti2 // -a unnecessary: unused in backends | |
| 90 | - port llvm __mulsi3 // a * b signed | |
| 91 | - port llvm __muldi3 // a * b signed | |
| 92 | - port llvm __multi3 // a * b signed | |
| 93 | - port llvm __divsi3 // a / b signed | |
| 94 | - port llvm __divdi3 // a / b signed | |
| 95 | - port llvm __divti3 // a / b signed | |
| 96 | - port llvm __udivsi3 // a / b unsigned | |
| 97 | - port llvm __udivdi3 // a / b unsigned | |
| 98 | - port llvm __udivti3 // a / b unsigned | |
| 99 | - port llvm __modsi3 // a % b signed | |
| 100 | - port llvm __moddi3 // a % b signed | |
| 101 | - port llvm __modti3 // a % b signed | |
| 102 | - port llvm __umodsi3 // a % b unsigned | |
| 103 | - port llvm __umoddi3 // a % b unsigned | |
| 104 | - port llvm __umodti3 // a % b unsigned | |
| 105 | - port llvm __udivmoddi4 // a / b, rem.* = a % b unsigned | |
| 106 | - port llvm __udivmodti4 // a / b, rem.* = a % b unsigned | |
| 107 | - port llvm __udivmodsi4 // a / b, rem.* = a % b unsigned | |
| 108 | - port llvm __divmodsi4 // a / b, rem.* = a % b signed, ARM | |
| 109 | ||
| 110 | #### Integer Arithmetic with trapping overflow | |
| 111 | - dev BitTwiddlingHacks __absvsi2 // abs(a) | |
| 112 | - dev BitTwiddlingHacks __absvdi2 // abs(a) | |
| 113 | - dev BitTwiddlingHacks __absvti2 // abs(a) | |
| 114 | - port llvm __negvsi2 // -a symbol-level compatibility: libgcc | |
| 115 | - port llvm __negvdi2 // -a unnecessary: unused in backends | |
| 116 | - port llvm __negvti2 // -a | |
| 117 | - TODO upstreaming __addvsi3..__mulvti3 after testing panics works | |
| 118 | - dev HackersDelight __addvsi3 // a + b | |
| 119 | - dev HackersDelight __addvdi3 // a + b | |
| 120 | - dev HackersDelight __addvti3 // a + b | |
| 121 | - dev HackersDelight __subvsi3 // a - b | |
| 122 | - dev HackersDelight __subvdi3 // a - b | |
| 123 | - dev HackersDelight __subvti3 // a - b | |
| 124 | - dev HackersDelight __mulvsi3 // a * b | |
| 125 | - dev HackersDelight __mulvdi3 // a * b | |
| 126 | - dev HackersDelight __mulvti3 // a * b | |
| 127 | ||
| 128 | #### Integer Arithmetic which returns if overflow (would be faster without pointer) | |
| 129 | - dev HackersDelight __addosi4 // a + b, overflow=>ov.*=1 else 0 | |
| 130 | - dev HackersDelight __addodi4 // (completeness + performance, llvm does not use them) | |
| 131 | - dev HackersDelight __addoti4 // | |
| 132 | - dev HackersDelight __subosi4 // a - b, overflow=>ov.*=1 else 0 | |
| 133 | - dev HackersDelight __subodi4 // (completeness + performance, llvm does not use them) | |
| 134 | - dev HackersDelight __suboti4 // | |
| 135 | - dev HackersDelight __mulosi4 // a * b, overflow=>ov.*=1 else 0 | |
| 136 | - dev HackersDelight __mulodi4 // (required by llvm) | |
| 137 | - dev HackersDelight __muloti4 // | |
| 138 | ||
| 139 | ## Float library routines | |
| 140 | ||
| 141 | #### Float Conversion | |
| 142 | - todo todo __extendsfdf2 // extend a f32 => f64 | |
| 143 | - todo todo __extendsftf2 // extend a f32 => f128 | |
| 144 | - dev llvm __extendsfxf2 // extend a f32 => f80 | |
| 145 | - todo todo __extenddftf2 // extend a f64 => f128 | |
| 146 | - dev llvm __extenddfxf2 // extend a f64 => f80 | |
| 147 | - todo todo __truncdfsf2 // truncate a to narrower mode of return type, rounding towards zero | |
| 148 | - todo todo __trunctfdf2 // | |
| 149 | - todo todo __trunctfsf2 // | |
| 150 | - dev llvm __truncxfsf2 // | |
| 151 | - dev llvm __truncxfdf2 // | |
| 152 | - todo todo __fixsfsi // convert a to i32, rounding towards zero | |
| 153 | - todo todo __fixdfsi // | |
| 154 | - todo todo __fixtfsi // | |
| 155 | - none none __fixxfsi // missing | |
| 156 | - todo todo __fixsfdi // convert a to i64, rounding towards zero | |
| 157 | - todo todo __fixdfdi // | |
| 158 | - todo todo __fixtfdi // | |
| 159 | - none none __fixxfdi // missing | |
| 160 | - todo todo __fixsfti // convert a to i128, rounding towards zero | |
| 161 | - todo todo __fixdfti // | |
| 162 | - todo todo __fixtfdi // | |
| 163 | - none none __fixxfti // missing | |
| 164 | ||
| 165 | - __fixunssfsi // convert to u32, rounding towards zero. negative values become 0. | |
| 166 | - __fixunsdfsi // | |
| 167 | - __fixunstfsi // | |
| 168 | - __fixunsxfsi // missing | |
| 169 | - __fixunssfdi // convert to u64, rounding towards zero. negative values become 0. | |
| 170 | - __fixunsdfdi // | |
| 171 | - __fixunstfdi // | |
| 172 | - __fixunsxfdi // missing | |
| 173 | - __fixunssfti // convert to u128, rounding towards zero. negative values become 0. | |
| 174 | - __fixunsdfti // | |
| 175 | - __fixunstfdi // | |
| 176 | - __fixunsxfti // missing | |
| 177 | ||
| 178 | - __floatsisf // convert i32 to floating point | |
| 179 | - __floatsidf // | |
| 180 | - __floatsitf // | |
| 181 | - __floatsixf // missing | |
| 182 | - __floatdisf // convert i64 to floating point | |
| 183 | - __floatdidf // | |
| 184 | - __floatditf // | |
| 185 | - __floatdixf // missing | |
| 186 | - __floattisf // convert i128 to floating point | |
| 187 | - __floattidf // | |
| 188 | - __floattixf // missing | |
| 189 | ||
| 190 | - __floatunsisf // convert i32 to floating point | |
| 191 | - __floatunsidf // | |
| 192 | - __floatunsitf // | |
| 193 | - __floatunsixf // missing | |
| 194 | - __floatundisf // convert i64 to floating point | |
| 195 | - __floatundidf // | |
| 196 | - __floatunditf // | |
| 197 | - __floatundixf // missing | |
| 198 | - __floatuntisf // convert i128 to floating point | |
| 199 | - __floatuntidf // | |
| 200 | - __floatuntitf // | |
| 201 | - __floatuntixf // missing | |
| 202 | ||
| 203 | #### Float Comparison | |
| 204 | - __cmpsf2 // return (a<b)=>-1,(a==b)=>0,(a>b)=>1,Nan=>1 dont rely on this | |
| 205 | - __cmpdf2 // exported from __lesf2, __ledf2, __letf2 (below) | |
| 206 | - __cmptf2 // | |
| 207 | - __unordsf2 // (input==NaN) => out!=0 else out=0, | |
| 208 | - __unorddf2 // __only reliable for (input!=Nan)__ | |
| 209 | - __unordtf2 // | |
| 210 | - __eqsf2 // (a!=NaN) and (b!=Nan) and (a==b) => output=0 | |
| 211 | - __eqdf2 // | |
| 212 | - __eqtf2 // | |
| 213 | - __nesf2 // (a==NaN) or (b==Nan) or (a!=b) => output!=0 | |
| 214 | - __nedf2 // | |
| 215 | - __netf2 // | |
| 216 | - __gesf2 // (a!=Nan) and (b!=Nan) and (a>=b) => output>=0 | |
| 217 | - __gedf2 // | |
| 218 | - __getf2 // | |
| 219 | - __ltsf2 // (a!=Nan) and (b!=Nan) and (a<b) => output<0 | |
| 220 | - __ltdf2 // | |
| 221 | - __lttf2 // | |
| 222 | - __lesf2 // (a!=Nan) and (b!=Nan) and (a<=b) => output<=0 | |
| 223 | - __ledf2 // | |
| 224 | - __letf2 // | |
| 225 | - __gtsf2 // (a!=Nan) and (b!=Nan) and (a>b) => output>0 | |
| 226 | - __gtdf2 // | |
| 227 | - __gttf2 // | |
| 228 | ||
| 229 | #### Float Arithmetic | |
| 230 | - __addsf3 // a + b f32 | |
| 231 | - __adddf3 // a + b f64 | |
| 232 | - __addtf3 // a + b f128 | |
| 233 | - __addxf3 // a + b f80 | |
| 234 | - __aeabi_fadd // a + b f64 ARM: AAPCS | |
| 235 | - __aeabi_dadd // a + b f64 ARM: AAPCS | |
| 236 | - __subsf3 // a - b | |
| 237 | - __subdf3 // a - b | |
| 238 | - __subtf3 // a - b | |
| 239 | - __subxf3 // a - b f80 | |
| 240 | - __aeabi_fsub // a - b f64 ARM: AAPCS | |
| 241 | - __aeabi_dsub // a - b f64 ARM: AAPCS | |
| 242 | - __mulsf3 // a * b | |
| 243 | - __muldf3 // a * b | |
| 244 | - __multf3 // a * b | |
| 245 | - __mulxf3 // a * b missing | |
| 246 | - __divsf3 // a / b | |
| 247 | - __divdf3 // a / b | |
| 248 | - __divtf3 // a / b | |
| 249 | - __divxf3 // a / b missing | |
| 250 | - __negsf2 // -a symbol-level compatibility: libgcc uses this for the rl78 | |
| 251 | - __negdf2 // -a unnecessary: can be lowered directly to a xor | |
| 252 | - __negtf2 // -a | |
| 253 | - __negxf2 // -a | |
| 9 | 254 | |
| 10 | Any bugs should be solved by trying to duplicate the bug upstream. | |
| 11 | * If the bug exists upstream, get it fixed with the LLVM team and then port | |
| 12 | the fix downstream to Zig. | |
| 13 | * If the bug only exists in Zig, something went wrong porting the code, | |
| 14 | and you can run the C code and Zig code side by side in a debugger | |
| 15 | to figure out what's happening differently. | |
| 255 | #### Floating point raised to integer power | |
| 256 | - __powisf2 // unclear, if supported a ^ b | |
| 257 | - __powidf2 // | |
| 258 | - __powitf2 // | |
| 259 | - __powixf2 // | |
| 260 | - __mulsc3 // unsupported (a+ib) * (c+id) | |
| 261 | - __muldc3 // | |
| 262 | - __multc3 // | |
| 263 | - __mulxc3 // | |
| 264 | - __divsc3 // unsupported (a+ib) * / (c+id) | |
| 265 | - __divdc3 // | |
| 266 | - __divtc3 // | |
| 267 | - __divxc3 // |
lib/std/special/compiler_rt/extend_f80.zig+1-1| ... | ... | @@ -11,7 +11,7 @@ pub fn __extendhfxf2(a: F16T) callconv(.C) f80 { |
| 11 | 11 | return extendF80(f16, @bitCast(u16, a)); |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | pub fn __extendffxf2(a: f32) callconv(.C) f80 { | |
| 14 | pub fn __extendsfxf2(a: f32) callconv(.C) f80 { | |
| 15 | 15 | return extendF80(f32, @bitCast(u32, a)); |
| 16 | 16 | } |
| 17 | 17 |
lib/std/special/compiler_rt/trunc_f80.zig+1-1| ... | ... | @@ -10,7 +10,7 @@ pub fn __truncxfhf2(a: f80) callconv(.C) F16T { |
| 10 | 10 | return @bitCast(F16T, trunc(f16, a)); |
| 11 | 11 | } |
| 12 | 12 | |
| 13 | pub fn __truncxfff2(a: f80) callconv(.C) f32 { | |
| 13 | pub fn __truncxfsf2(a: f80) callconv(.C) f32 { | |
| 14 | 14 | return trunc(f32, a); |
| 15 | 15 | } |
| 16 | 16 |
src/stage1/codegen.cpp+2-2| ... | ... | @@ -1641,7 +1641,7 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty |
| 1641 | 1641 | break; |
| 1642 | 1642 | case 32: |
| 1643 | 1643 | return_type = g->builtin_types.entry_f32->llvm_type; |
| 1644 | func_name = "__truncxfff2"; | |
| 1644 | func_name = "__truncxfsf2"; | |
| 1645 | 1645 | break; |
| 1646 | 1646 | case 64: |
| 1647 | 1647 | return_type = g->builtin_types.entry_f64->llvm_type; |
| ... | ... | @@ -1670,7 +1670,7 @@ static LLVMValueRef gen_soft_f80_widen_or_shorten(CodeGen *g, ZigType *actual_ty |
| 1670 | 1670 | break; |
| 1671 | 1671 | case 32: |
| 1672 | 1672 | param_type = g->builtin_types.entry_f32->llvm_type; |
| 1673 | func_name = "__extendffxf2"; | |
| 1673 | func_name = "__extendsfxf2"; | |
| 1674 | 1674 | break; |
| 1675 | 1675 | case 64: |
| 1676 | 1676 | param_type = g->builtin_types.entry_f64->llvm_type; |