kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit 10edd3fecf8e36b56b5b8b41b653755dd44de48c
parent 05db6b973f7e1398455d363ebd3ba815c3f82d53
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu,  7 May 2026 11:32:37 -0700

lib/ consolidation into fewer files and exhaustive build.sh via clang

Diffstat:
Mlib/README.md | 269++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Alib/arm/aeabi.c | 20++++++++++++++++++++
Dlib/arm/aeabi_dcmp.S | 45---------------------------------------------
Dlib/arm/aeabi_drsub.c | 14--------------
Dlib/arm/aeabi_fcmp.S | 45---------------------------------------------
Dlib/arm/aeabi_frsub.c | 14--------------
Dlib/arm/aeabi_idivmod.S | 33---------------------------------
Dlib/arm/aeabi_idivmod_thumb1.S | 28----------------------------
Dlib/arm/aeabi_ldivmod.S | 34----------------------------------
Dlib/arm/aeabi_memcmp.S | 23-----------------------
Dlib/arm/aeabi_memcmp_thumb1.S | 25-------------------------
Dlib/arm/aeabi_memcpy.S | 23-----------------------
Dlib/arm/aeabi_memcpy_thumb1.S | 25-------------------------
Dlib/arm/aeabi_memmove.S | 22----------------------
Dlib/arm/aeabi_memmove_thumb1.S | 24------------------------
Dlib/arm/aeabi_memset.S | 37-------------------------------------
Dlib/arm/aeabi_memset_thumb1.S | 42------------------------------------------
Alib/arm/aeabi_thumb1.S | 261+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/arm/aeabi_thumb2.S | 268+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/arm/aeabi_uidivmod.S | 34----------------------------------
Dlib/arm/aeabi_uidivmod_thumb1.S | 31-------------------------------
Dlib/arm/aeabi_uldivmod.S | 34----------------------------------
Mlib/build.sh | 172++++++++++++++++++++++++++++++-------------------------------------------------
Dlib/fp/adddf3.c | 17-----------------
Dlib/fp/addsf3.c | 17-----------------
Dlib/fp/comparedf2.c | 52----------------------------------------------------
Dlib/fp/comparesf2.c | 52----------------------------------------------------
Dlib/fp/divdf3.c | 25-------------------------
Dlib/fp/divsf3.c | 27---------------------------
Dlib/fp/extendsfdf2.c | 17-----------------
Dlib/fp/fixdfdi.c | 26--------------------------
Dlib/fp/fixdfsi.c | 21---------------------
Dlib/fp/fixsfdi.c | 26--------------------------
Dlib/fp/fixsfsi.c | 21---------------------
Dlib/fp/fixunsdfdi.c | 24------------------------
Dlib/fp/fixunsdfsi.c | 19-------------------
Dlib/fp/fixunssfdi.c | 24------------------------
Dlib/fp/fixunssfsi.c | 23-----------------------
Dlib/fp/floatdidf.c | 35-----------------------------------
Dlib/fp/floatdisf.c | 30------------------------------
Dlib/fp/floatsidf.c | 51---------------------------------------------------
Dlib/fp/floatsisf.c | 59-----------------------------------------------------------
Dlib/fp/floatundidf.c | 35-----------------------------------
Dlib/fp/floatundisf.c | 30------------------------------
Dlib/fp/floatunsidf.c | 40----------------------------------------
Dlib/fp/floatunsisf.c | 50--------------------------------------------------
Alib/fp/fp.c | 512+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/fp/fp_mode.c | 22----------------------
Dlib/fp/muldf3.c | 18------------------
Dlib/fp/mulsf3.c | 18------------------
Dlib/fp/negdf2.c | 17-----------------
Dlib/fp/negsf2.c | 17-----------------
Dlib/fp/subdf3.c | 20--------------------
Dlib/fp/subsf3.c | 20--------------------
Dlib/fp/truncdfsf2.c | 17-----------------
Dlib/fp_tf/addtf3.c | 21---------------------
Dlib/fp_tf/comparetf2.c | 51---------------------------------------------------
Dlib/fp_tf/divtf3.c | 27---------------------------
Dlib/fp_tf/extenddftf2.c | 20--------------------
Dlib/fp_tf/extendsftf2.c | 20--------------------
Dlib/fp_tf/fixtfdi.c | 21---------------------
Dlib/fp_tf/fixtfsi.c | 21---------------------
Dlib/fp_tf/fixtfti.c | 21---------------------
Dlib/fp_tf/fixunstfdi.c | 19-------------------
Dlib/fp_tf/fixunstfsi.c | 19-------------------
Dlib/fp_tf/fixunstfti.c | 19-------------------
Dlib/fp_tf/floatditf.c | 47-----------------------------------------------
Dlib/fp_tf/floatsitf.c | 47-----------------------------------------------
Dlib/fp_tf/floattitf.c | 36------------------------------------
Dlib/fp_tf/floatunditf.c | 38--------------------------------------
Dlib/fp_tf/floatunsitf.c | 38--------------------------------------
Dlib/fp_tf/floatuntitf.c | 36------------------------------------
Alib/fp_tf/fp_tf.c | 387+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/fp_tf/multf3.c | 20--------------------
Dlib/fp_tf/subtf3.c | 22----------------------
Dlib/fp_tf/trunctfdf2.c | 20--------------------
Dlib/fp_tf/trunctfsf2.c | 20--------------------
Dlib/fp_ti/fixdfti.c | 24------------------------
Dlib/fp_ti/fixsfti.c | 24------------------------
Dlib/fp_ti/fixunsdfti.c | 20--------------------
Dlib/fp_ti/fixunssfti.c | 23-----------------------
Dlib/fp_ti/floattidf.c | 32--------------------------------
Dlib/fp_ti/floattisf.c | 31-------------------------------
Dlib/fp_ti/floatuntidf.c | 32--------------------------------
Dlib/fp_ti/floatuntisf.c | 31-------------------------------
Alib/fp_ti/fp_ti.c | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/impl/fp_extend.h | 277-------------------------------------------------------------------------------
Mlib/impl/fp_extend_impl.inc | 259++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Dlib/impl/fp_trunc.h | 259-------------------------------------------------------------------------------
Mlib/impl/fp_trunc_impl.inc | 243++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Dlib/impl/int_to_fp.h | 174-------------------------------------------------------------------------------
Mlib/impl/int_to_fp_impl.inc | 158++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mlib/include/common/fp_lib.h | 1-
Dlib/include/ilp32_le/int_endianness.h | 13-------------
Mlib/include/ilp32_le/int_lib.h | 43++++++++++++++++++++++++++++++++++++++++++-
Dlib/include/ilp32_le/int_types.h | 48------------------------------------------------
Dlib/include/llp64_le/int_endianness.h | 13-------------
Mlib/include/llp64_le/int_lib.h | 64+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Dlib/include/llp64_le/int_types.h | 69---------------------------------------------------------------------
Dlib/include/lp64_le/int_endianness.h | 13-------------
Mlib/include/lp64_le/int_lib.h | 69++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Dlib/include/lp64_le/int_types.h | 74--------------------------------------------------------------------------
Mlib/include/lp64_le_ldbl128/tf_supplement.h | 6+++---
Dlib/int/absvdi2.c | 25-------------------------
Dlib/int/bswapdi2.c | 25-------------------------
Dlib/int/bswapsi2.c | 20--------------------
Dlib/int/clzdi2.c | 25-------------------------
Dlib/int/clzsi2.c | 48------------------------------------------------
Dlib/int/cmpdi2.c | 34----------------------------------
Dlib/int/ctzdi2.c | 25-------------------------
Dlib/int/ctzsi2.c | 53-----------------------------------------------------
Dlib/int/divdi3.c | 25-------------------------
Dlib/int/divmoddi4.c | 28----------------------------
Dlib/int/ffsdi2.c | 27---------------------------
Alib/int/int.c | 558+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/int/int_util.c | 20--------------------
Dlib/int/moddi3.c | 25-------------------------
Dlib/int/negdi2.c | 21---------------------
Dlib/int/paritydi2.c | 25-------------------------
Dlib/int/paritysi2.c | 23-----------------------
Dlib/int/popcountdi2.c | 32--------------------------------
Dlib/int/popcountsi2.c | 29-----------------------------
Dlib/int/ucmpdi2.c | 34----------------------------------
Dlib/int/udivdi3.c | 24------------------------
Dlib/int/udivmoddi4.c | 191-------------------------------------------------------------------------------
Dlib/int/umoddi3.c | 24------------------------
Dlib/int32/ashldi3.c | 36------------------------------------
Dlib/int32/ashrdi3.c | 37-------------------------------------
Alib/int32/int32.c | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/int32/lshrdi3.c | 35-----------------------------------
Dlib/int32/muldi3.c | 48------------------------------------------------
Dlib/int64/ashlti3.c | 37-------------------------------------
Dlib/int64/ashrti3.c | 38--------------------------------------
Dlib/int64/clzti2.c | 27---------------------------
Dlib/int64/ctzti2.c | 27---------------------------
Dlib/int64/divmodti4.c | 30------------------------------
Dlib/int64/divti3.c | 27---------------------------
Alib/int64/int64.c | 383+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/int64/lshrti3.c | 36------------------------------------
Dlib/int64/modti3.c | 27---------------------------
Dlib/int64/multi3.c | 49-------------------------------------------------
Dlib/int64/negti2.c | 23-----------------------
Dlib/int64/udivmodti4.c | 148-------------------------------------------------------------------------------
Dlib/int64/udivti3.c | 21---------------------
Dlib/int64/umodti3.c | 23-----------------------
Dlib/riscv/restore_rv32.S | 73-------------------------------------------------------------------------
Dlib/riscv/restore_rv64.S | 82-------------------------------------------------------------------------------
Alib/riscv/rv32.S | 147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/riscv/rv64.S | 169+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dlib/riscv/save_rv32.S | 88-------------------------------------------------------------------------------
Dlib/riscv/save_rv64.S | 101-------------------------------------------------------------------------------
151 files changed, 4042 insertions(+), 5163 deletions(-)

diff --git a/lib/README.md b/lib/README.md @@ -1,77 +1,84 @@ # lib/ — `libcfree_rt.a` source -Per-op runtime helpers for cfree, copied from +Runtime helpers for cfree, derived from [compiler-rt 18.1.8](https://github.com/llvm/llvm-project/releases/tag/llvmorg-18.1.8) -(`lib/builtins/`) and stripped to remove ifdefs that select between targets. -The build system picks files by directory; each `.c` / `.S` file compiles to -exactly one target without preprocessor branching. +(`lib/builtins/`) and stripped of all target-dispatch ifdefs. Every helper +that varies across targets is selected by directory + compile flags, not +preprocessor branches inside source. + +The build compiles **exactly one master `.c` (and/or `.S`) file per feature +flag** — no globbing of per-op files. Per-op snippets are inlined directly +into the master, with the per-precision / per-(src,dst) machinery from +`impl/` re-applied for each section. License: Apache-2.0 WITH LLVM-exception (see `LICENSE-compiler-rt.txt`). The hand-written `mem/mem.c` is 0BSD; relicense as desired. ## Layout -### Source dirs (each `.c` / `.S` becomes one object in `libcfree_rt.a`) - -| Directory | Purpose | Built on | -| -------------- | --------------------------------------------------------- | ----------------------------------------- | -| `int/` | Integer helpers needed on every target | All | -| `int32/` | 64-bit ops synthesized from 32-bit | ILP32 only | -| `int64/` | 128-bit ops via `__int128` | LP64 / LLP64 only | -| `fp/` | Soft-float `sf` (binary32) and `df` (binary64) | FPU-less targets (RV{32,64}I, ARM softfp, WASM) | -| `fp_tf/` | Soft-float `tf` (binary128) | Targets with binary128 long double (e.g. aarch64 `-mlong-double-128`) | -| `fp_ti/` | `__int128` ↔ float | LP64 / LLP64 + soft-float | -| `arm/` | ARM AAPCS / AEABI aliases & wrappers | 32-bit ARM | -| `riscv/` | `__riscv_save_*` / `__riscv_restore_*` (`-msave-restore`) | RISC-V (per-xlen file) | -| `mem/` | `memcpy` / `memmove` / `memset` / `memcmp` (weak) | All; user libc overrides | -| `atomic/` | `__atomic_*` fallback shim | All | - -### Build-time include dirs (consumed by the source dirs above; nothing here lands in `libcfree_rt.a`) - -| Directory | Consumed by | -| -------------------------- | ------------------------------------------------------------------------------------------ | -| `impl/` | `int/divdi3.c` etc. (via `int_div_impl.inc`); every `fp*/`, `fp_tf/`, `fp_ti/` file | -| `include/common/` | All `.c` (transitively, via the per-target `int_lib.h`); `arm/*.S` includes `assembly.h` | -| `include/lp64_le/` | LP64 builds; selected via `-Iinclude/lp64_le` | -| `include/llp64_le/` | LLP64 (Win64) builds | -| `include/ilp32_le/` | ILP32 builds | -| `include/lp64_le_ldbl128/` | Extra `-include tf_supplement.h` when compiling `fp_tf/` on binary128-long-double targets | -| `atomic/atomic_common.inc` | `atomic/atomic_freestanding.c` | +### Master files (each becomes one object in `libcfree_rt.a`) + +| File | Purpose | Built on | +| -------------------------- | ----------------------------------------------------------- | --------------------------------------------------- | +| `int/int.c` | Integer helpers needed on every target | All | +| `int32/int32.c` | 64-bit ops synthesized from 32-bit | ILP32 only | +| `int64/int64.c` | 128-bit ops via `__int128` | LP64 / LLP64 only | +| `fp/fp.c` | Soft-float `sf` (binary32) + `df` (binary64) + sf↔df + `fp_mode` | FPU-less (RV{32,64}I, ARM softfp, WASM) | +| `fp_tf/fp_tf.c` | Soft-float `tf` (binary128) + sf↔tf + df↔tf + i128↔tf | Targets with binary128 long double (e.g. aarch64 `-mlong-double-128`) | +| `fp_ti/fp_ti.c` | `__int128` ↔ sf/df + sf/df → ti fix | LP64 / LLP64 + soft-float | +| `arm/aeabi_thumb2.S` | AEABI div/mod/mem* + soft-float compares (ARMv7+/Thumb2) | 32-bit ARM, ARMv7+/Thumb2 | +| `arm/aeabi_thumb1.S` | Same, Thumb1-tuned (no tail-calls, simpler instr forms) | 32-bit ARM, ARMv6-M (Cortex-M0/M0+/M1) | +| `arm/aeabi.c` | AEABI `__aeabi_drsub` / `__aeabi_frsub` (ISA-agnostic) | 32-bit ARM (both ISA modes) | +| `riscv/rv32.S` | `__riscv_save_*` + `__riscv_restore_*` (rv32) | RISC-V rv32 with `-msave-restore` | +| `riscv/rv64.S` | `__riscv_save_*` + `__riscv_restore_*` (rv64) | RISC-V rv64 with `-msave-restore` | +| `mem/mem.c` | `memcpy` / `memmove` / `memset` / `memcmp` (weak) | All; user libc overrides | +| `atomic/atomic_freestanding.c` | `__atomic_*` fallback shim | All | + +### Build-time include dirs (consumed by the masters; nothing here lands in `libcfree_rt.a`) + +| Directory | Consumed by | +| -------------------------- | ---------------------------------------------------------------------------------------------------------- | +| `impl/` | `int/int.c` (via `int_div_impl.inc`); every `fp*` master (via `fp_*_impl.inc`, `fp_extend_impl.inc`, `fp_trunc_impl.inc`, `int_to_fp_impl.inc`) | +| `include/common/` | All masters (transitively, via the per-target `int_lib.h`); `arm/aeabi_thumb*.S` includes `assembly.h` | +| `include/lp64_le/` | LP64 builds; selected via `-Iinclude/lp64_le` | +| `include/llp64_le/` | LLP64 (Win64) builds | +| `include/ilp32_le/` | ILP32 builds | +| `include/lp64_le_ldbl128/` | Extra `-include tf_supplement.h` when compiling `fp_tf/fp_tf.c` on binary128-long-double targets | +| `atomic/atomic_common.inc` | `atomic/atomic_freestanding.c` | ## How the build picks files ```text target tuple ⟶ compile -x86_64-linux / aarch64-linux / aarch64-darwin / rv64 - ⟶ int/* int64/* fp/* +x86_64-linux / x86_64-darwin / aarch64-darwin / rv64 + ⟶ int/int.c int64/int64.c fp/fp.c atomic/atomic_freestanding.c mem/mem.c -Iinclude/lp64_le -DHAS_INT128=1 -x86_64-windows ⟶ int/* int64/* fp/* atomic/* mem/* - -Iinclude/llp64_le +x86_64-windows ⟶ same set, -Iinclude/llp64_le -DHAS_INT128=1 -i386-* / arm32-* / rv32 / wasm32 ⟶ int/* int32/* fp/* atomic/* mem/* +i386-* / arm32-* / rv32 / wasm32 ⟶ int/int.c int32/int32.c fp/fp.c + atomic/atomic_freestanding.c + mem/mem.c -Iinclude/ilp32_le -DHAS_INT128=0 -aarch64-* with binary128 long double ⟶ above + fp_tf/* fp_ti/* +aarch64-linux (binary128 long double) ⟶ above LP64 set + fp_tf/fp_tf.c + + fp_ti/fp_ti.c -include include/lp64_le_ldbl128/tf_supplement.h -rv32 with -msave-restore ⟶ above + riscv/save_rv32.S riscv/restore_rv32.S -rv64 with -msave-restore ⟶ above + riscv/save_rv64.S riscv/restore_rv64.S -arm32 ARMv7+/Thumb2 (AEABI) ⟶ above + arm/aeabi_*.{S,c} (excluding *_thumb1.S) -arm32 ARMv6-M Thumb1 (Cortex-M0/M0+/M1) ⟶ above + arm/aeabi_*_thumb1.S - + the AEABI files with no Thumb1 variant - (aeabi_ldivmod.S, aeabi_uldivmod.S, - aeabi_dcmp.S, aeabi_fcmp.S, - aeabi_drsub.c, aeabi_frsub.c) +rv32 with -msave-restore ⟶ above + riscv/rv32.S +rv64 with -msave-restore ⟶ above + riscv/rv64.S +arm32 ARMv7+/Thumb2 (AEABI) ⟶ above + arm/aeabi_thumb2.S + arm/aeabi.c +arm32 ARMv6-M Thumb1 (Cortex-M0/M0+/M1) ⟶ above + arm/aeabi_thumb1.S + arm/aeabi.c ``` -`-Iinclude/common` is always added. +`-Iinclude/common` and `-Iimpl` are always added. The full set of variants +is in `build.sh`. ## Endianness @@ -79,68 +86,105 @@ All headers assume `__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__`. cfree's supported targets (x86, ARM-LE, RISC-V, WASM) are LE in practice. Big-endian support would need a parallel `*_be/` header set; not provided. +## Re-includable templates in `impl/` and `include/common/fp_lib.h` + +Each master compiles to one TU. To support multiple precisions and multiple +(src, dst) pairs in that single TU, the upstream compiler-rt's +single-precision-per-TU model was extended: + +- **`include/common/fp_lib.h`** is re-includable. Caller `#define`s + `SINGLE_PRECISION`, `DOUBLE_PRECISION`, or `QUAD_PRECISION`, then + `#include "fp_lib.h"`. The header emits suffix-renamed typedefs and + static inlines (`fp_t_sf`, `rep_clz_df`, ...) once per (TU, precision), + and sets bare-name `#define` aliases (`fp_t`, `rep_clz`, ...) so caller + code uses bare names that resolve to the right suffixed entity. + `include/common/fp_lib_undef.h` clears the bare aliases between sections + that switch precision or (src,dst) pair. +- **`impl/fp_*_impl.inc`** (add, mul, div, compare, fixint, fixuint) are + re-includable. Their static `__addXf3__` / `__leXf2__` / etc. are + suffix-renamed via `_FP_NAME(...)`; emission is gated per (TU, precision) + via `FP_<OP>_<SUFFIX>_EMITTED`. `fp_fixint_impl.inc` / `fp_fixuint_impl.inc` + take an additional caller-supplied `FP_FIX_SUFFIX` so each fix call site + gets its own helper instance. +- **`impl/fp_extend_impl.inc`**, **`fp_trunc_impl.inc`**, and + **`int_to_fp_impl.inc`** suffix-rename by the (src, dst) pair token + (`sfdf`, `sftf`, `dftf`, ...). One emission per (TU, pair). Each + inc bundles its own type/helper setup at the top (formerly the + separate `fp_extend.h` / `fp_trunc.h` / `int_to_fp.h` partner headers). +- **`impl/int_div_impl.inc`** takes a caller-supplied `INT_DIV_SUFFIX` and + emits suffixed `__udivXi3_<suf>` / `__divXi3_<suf>` etc. so the master + can include the inc multiple times in one TU (e.g. once per of + `divdi3`, `udivdi3`, `moddi3`, `umoddi3` in `int.c`). + +In short: every template that the master includes more than once per TU +either uses a precision-derived suffix (auto, via `FP_LIB_SUFFIX`) or a +caller-defined suffix. + ## Files with surviving preprocessor logic -The "no ifdefs" rule is applied to every `.c` and `.S` source — none branch on -target. Some headers and shared `.inc` files retain preprocessor logic that is -*not* target dispatch: +The "no target-dispatch ifdefs" rule is applied to every master. Some +templates retain preprocessor logic that is *not* target dispatch: -- `impl/*.inc`, `impl/*.h`, `include/common/fp_lib.h` — parameterized via +- `impl/*.inc`, `include/common/fp_lib.h` — parameterized via `SINGLE_PRECISION` / `DOUBLE_PRECISION` / `QUAD_PRECISION` and the - `SRC_*` / `DST_*` selectors. Each `.c` file `#define`s exactly one before - the include; this is the metaprogramming model compiler-rt uses for fp ops. -- `include/common/assembly.h` — abstracts assembler syntax (ELF vs Mach-O vs - COFF symbol decoration, ARM/Thumb mode markers, etc.). Heavily ifdef'd by - design; consumed only by `arm/*.S`. -- `atomic/atomic_common.inc` — keys the 16-byte cases off `HAS_INT128`, set - by the build (`-DHAS_INT128=1` on 64-bit, `-DHAS_INT128=0` on 32-bit). + `SRC_*` / `DST_*` selectors set by the master before each inclusion. +- `include/common/assembly.h` — abstracts assembler syntax (ELF vs Mach-O + vs COFF symbol decoration, ARM/Thumb mode markers, etc.). Heavily + ifdef'd by design; consumed only by `arm/aeabi_thumb{1,2}.S`. +- `atomic/atomic_common.inc` — keys the 16-byte cases off `HAS_INT128`, + set by the build (`-DHAS_INT128=1` on 64-bit, `-DHAS_INT128=0` on 32-bit). -## Notes per directory +## Notes per master ### `mem/mem.c` -Hand-written portable C (not from compiler-rt). All four functions are weak so -a user libc, or a tuned arch-specific replacement, wins at link time. The -existing `arm/aeabi_mem*.S` files forward to these symbols. - -### `atomic/` -`atomic_freestanding.c` defines a pointer-sized `_Atomic(uintptr_t)` spinlock -as the lock primitive (no OS dependency) then `#include`s `atomic_common.inc`, -which contains the dispatch logic and all `__atomic_*_N` expansions. The -shim calls the GCC `__atomic_*` builtin family (the one cfree documents in -`doc/builtins.md`); upstream's Clang-only `__c11_atomic_*` calls were -translated. Public symbols are exported via `#pragma redefine_extname` from -`_c`-suffixed names so they don't collide with the clang builtins of the -same name. - -### `arm/` -AEABI aliases for div/mod, soft-float compares, and the `aeabi_mem{cpy,move,set,clr}` -size-specialized wrappers. Six files have a `*_thumb1.S` companion for -ARMv6-M (Cortex-M0/M0+/M1), where the ISA can't tail-call (`b memcpy`) or -fold the `subs/muls` form into one instruction: -`aeabi_idivmod`, `aeabi_uidivmod`, `aeabi_memcpy`, `aeabi_memmove`, -`aeabi_memset`, `aeabi_memcmp`. The build picks one variant per symbol — -the Thumb1 file for ARMv6-M, the base file for ARMv7+/Thumb2. The remaining -AEABI files (`aeabi_ldivmod`, `aeabi_uldivmod`, `aeabi_{d,f}cmp`, -`aeabi_{d,f}rsub`) are ISA-agnostic and used as-is on both. - -### `riscv/` -`save.S` / `restore.S` upstream are one file each, gated on `__riscv_xlen`. -Split into `save_rv32.S` / `save_rv64.S` and `restore_rv32.S` / `restore_rv64.S`. -The embedded ABI variants (`__riscv_32e` / `__riscv_64e`) were not carried over. - -### `fp_tf/` +Hand-written portable C (not from compiler-rt). All four functions are weak +so a user libc, or a tuned arch-specific replacement, wins at link time. +`arm/aeabi_thumb{1,2}.S`'s `aeabi_mem*` symbols forward to these. + +### `atomic/atomic_freestanding.c` +Defines a pointer-sized `_Atomic(uintptr_t)` spinlock as the lock primitive +(no OS dependency) then `#include`s `atomic_common.inc`, which contains the +dispatch logic and all `__atomic_*_N` expansions. The shim calls the GCC +`__atomic_*` builtin family (the one cfree documents in `doc/builtins.md`); +upstream's Clang-only `__c11_atomic_*` calls were translated. Public symbols +are exported via `#pragma redefine_extname` from `_c`-suffixed names so they +don't collide with the clang builtins of the same name. + +### `arm/aeabi_thumb{1,2}.S` +AEABI aliases for div/mod, soft-float compares, and the +`aeabi_mem{cpy,move,set,clr}` size-specialized wrappers. Two ISA-mode +variants: +- **Thumb2** — used on ARMv7+/Thumb2; tail-calls into `memcpy` etc., uses + `subs/muls` folding. +- **Thumb1** — used on ARMv6-M (Cortex-M0/M0+/M1); avoids tail-calls (no + `b memcpy`) and the folded `subs/muls` form. +Both files contain the same ISA-agnostic helpers (`aeabi_ldivmod`, +`aeabi_uldivmod`, `aeabi_{d,f}cmp`) inline plus their respective ISA-tuned +versions of the dual helpers (`aeabi_idivmod`, `aeabi_uidivmod`, and the +four `aeabi_mem*`). + +### `arm/aeabi.c` +`__aeabi_drsub` and `__aeabi_frsub`. Built alongside whichever +`aeabi_thumb{1,2}.S` is selected. + +### `riscv/rv{32,64}.S` +Combined `save_*` + `restore_*`. Upstream's `save.S` / `restore.S` are +gated on `__riscv_xlen`; cfree splits per xlen. The embedded ABI variants +(`__riscv_32e` / `__riscv_64e`) are not carried over. + +### `fp_tf/fp_tf.c` Compile only on targets where `long double` is IEEE binary128 (typically -`aarch64` with `-mlong-double-128`). The build must `-include` -`lp64_le_ldbl128/tf_supplement.h` so `tf_float`, `CRT_HAS_TF_MODE`, etc. are -defined before `fp_lib.h` is processed. +`aarch64` with `-mlong-double-128`). The build must `-include` +`lp64_le_ldbl128/tf_supplement.h` so `tf_float`, `CRT_HAS_TF_MODE`, etc. +are defined before `fp_lib.h` is processed. -### Compare files -`fp/comparesf2.c`, `fp/comparedf2.c`, `fp_tf/comparetf2.c` define every variant -(`__eqXf2`, `__ltXf2`, `__neXf2`, `__gtXf2`) as a separate function rather than -using `COMPILER_RT_ALIAS`. Replaces an object-format-conditional macro with a -handful of one-line wrappers. +### Compare helpers +The `comparesf2` / `comparedf2` / `comparetf2` sections of the fp masters +define every variant (`__eqXf2`, `__ltXf2`, `__neXf2`, `__gtXf2`) as a +separate function rather than using `COMPILER_RT_ALIAS`. Replaces an +object-format-conditional macro with a handful of one-line wrappers. -### `int/int_util.c` +### `int_util` section of `int/int.c` Replaced upstream's hosted/kernel/Apple/Win32 abort cascade with a single freestanding `__compilerrt_abort_impl` that calls `__builtin_trap()`. @@ -156,12 +200,25 @@ These are documented in `doc/builtins.md` but not provided here: ## Updating from a newer compiler-rt -When pulling in a new release: -1. Diff `lib/builtins/*.c` against the corresponding files here. Per-op files - typically need only the `__ARM_EABI__` / `__MINGW32__` / `__SOFTFP__` blocks - re-stripped. -2. Re-strip `int_util.c` to the freestanding-only abort path. -3. Re-split any new `riscv/` or `arm/` files that combine modes. -4. Diff `int_lib.h` / `int_types.h` / `fp_lib.h` against the per-target copies - under `include/`; update for any new feature gates that aren't legitimately - target-orthogonal. +The per-op layout that lived in upstream's `lib/builtins/<op>.c` is now +inlined into masters here. To pull in a newer release: + +1. Identify which builtins changed between releases (`git log` or release + notes). For each changed builtin: + - Find its inlined block in the matching cfree master (each block is + prefixed by `// ---- <upstream filename> ----`). + - Diff that block against upstream `lib/builtins/<op>.c`. Drop any + re-introduced target-dispatch ifdefs (`__ARM_EABI__`, `__MINGW32__`, + `__SOFTFP__`). +2. If `int_util.c` changed upstream, re-strip to the freestanding-only + abort path. +3. If `riscv/save.S` / `restore.S` changed, re-split into the per-xlen + inline blocks of `riscv/rv{32,64}.S`. +4. Diff `int_lib.h` / `fp_lib.h` against the per-target copies under + `include/`; update for any new feature gates that aren't legitimately + target-orthogonal. Note: upstream's `int_endianness.h` and + `int_types.h` are folded into each per-target `int_lib.h`. Note also + that cfree's `fp_lib.h` has been refactored into a re-includable form + (per-precision suffix-renaming plus bare-name aliases) — pull upstream + changes into the precision blocks; don't revert the suffix machinery. +5. Run `bash build.sh` and confirm all 13 variants pass. diff --git a/lib/arm/aeabi.c b/lib/arm/aeabi.c @@ -0,0 +1,20 @@ +// Consolidated AEABI soft-float C helpers for cfree's libcfree_rt.a. +// The build compiles only this one file per ISA mode; the per-op files are +// #included as snippets and not directly built. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// ---- aeabi_drsub.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" + +AEABI_RTABI fp_t __aeabi_dsub(fp_t, fp_t); + +AEABI_RTABI fp_t __aeabi_drsub(fp_t a, fp_t b) { return __aeabi_dsub(b, a); } +#include "fp_lib_undef.h" +// ---- aeabi_frsub.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" + +AEABI_RTABI fp_t __aeabi_fsub(fp_t, fp_t); + +AEABI_RTABI fp_t __aeabi_frsub(fp_t a, fp_t b) { return __aeabi_fsub(b, a); } diff --git a/lib/arm/aeabi_dcmp.S b/lib/arm/aeabi_dcmp.S @@ -1,45 +0,0 @@ -//===-- aeabi_dcmp.S - EABI dcmp* implementation ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// int __aeabi_dcmp{eq,lt,le,ge,gt}(double a, double b) { -// int result = __{eq,lt,le,ge,gt}df2(a, b); -// if (result {==,<,<=,>=,>} 0) { -// return 1; -// } else { -// return 0; -// } -// } - -# define CONVERT_DCMP_ARGS_TO_DF2_ARGS - -#define DEFINE_AEABI_DCMP(cond) \ - .syntax unified SEPARATOR \ - .p2align 2 SEPARATOR \ -DEFINE_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) \ - push { r4, lr } SEPARATOR \ - CONVERT_DCMP_ARGS_TO_DF2_ARGS SEPARATOR \ - bl SYMBOL_NAME(__ ## cond ## df2) SEPARATOR \ - cmp r0, #0 SEPARATOR \ - b ## cond 1f SEPARATOR \ - movs r0, #0 SEPARATOR \ - pop { r4, pc } SEPARATOR \ -1: SEPARATOR \ - movs r0, #1 SEPARATOR \ - pop { r4, pc } SEPARATOR \ -END_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) - -DEFINE_AEABI_DCMP(eq) -DEFINE_AEABI_DCMP(lt) -DEFINE_AEABI_DCMP(le) -DEFINE_AEABI_DCMP(ge) -DEFINE_AEABI_DCMP(gt) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/arm/aeabi_drsub.c b/lib/arm/aeabi_drsub.c @@ -1,14 +0,0 @@ -//===-- lib/arm/aeabi_drsub.c - Double-precision subtraction --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -AEABI_RTABI fp_t __aeabi_dsub(fp_t, fp_t); - -AEABI_RTABI fp_t __aeabi_drsub(fp_t a, fp_t b) { return __aeabi_dsub(b, a); } diff --git a/lib/arm/aeabi_fcmp.S b/lib/arm/aeabi_fcmp.S @@ -1,45 +0,0 @@ -//===-- aeabi_fcmp.S - EABI fcmp* implementation ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// int __aeabi_fcmp{eq,lt,le,ge,gt}(float a, float b) { -// int result = __{eq,lt,le,ge,gt}sf2(a, b); -// if (result {==,<,<=,>=,>} 0) { -// return 1; -// } else { -// return 0; -// } -// } - -# define CONVERT_FCMP_ARGS_TO_SF2_ARGS - -#define DEFINE_AEABI_FCMP(cond) \ - .syntax unified SEPARATOR \ - .p2align 2 SEPARATOR \ -DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) \ - push { r4, lr } SEPARATOR \ - CONVERT_FCMP_ARGS_TO_SF2_ARGS SEPARATOR \ - bl SYMBOL_NAME(__ ## cond ## sf2) SEPARATOR \ - cmp r0, #0 SEPARATOR \ - b ## cond 1f SEPARATOR \ - movs r0, #0 SEPARATOR \ - pop { r4, pc } SEPARATOR \ -1: SEPARATOR \ - movs r0, #1 SEPARATOR \ - pop { r4, pc } SEPARATOR \ -END_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) - -DEFINE_AEABI_FCMP(eq) -DEFINE_AEABI_FCMP(lt) -DEFINE_AEABI_FCMP(le) -DEFINE_AEABI_FCMP(ge) -DEFINE_AEABI_FCMP(gt) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/arm/aeabi_frsub.c b/lib/arm/aeabi_frsub.c @@ -1,14 +0,0 @@ -//===-- lib/arm/aeabi_frsub.c - Single-precision subtraction --------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" - -AEABI_RTABI fp_t __aeabi_fsub(fp_t, fp_t); - -AEABI_RTABI fp_t __aeabi_frsub(fp_t a, fp_t b) { return __aeabi_fsub(b, a); } diff --git a/lib/arm/aeabi_idivmod.S b/lib/arm/aeabi_idivmod.S @@ -1,33 +0,0 @@ -//===-- aeabi_idivmod.S - EABI idivmod implementation ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// struct { int quot, int rem} __aeabi_idivmod(int numerator, int denominator) { -// int rem, quot; -// quot = __divmodsi4(numerator, denominator, &rem); -// return {quot, rem}; -// } - - - .syntax unified - .text - DEFINE_CODE_STATE - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_idivmod) - push { lr } - sub sp, sp, #4 - mov r2, sp - bl SYMBOL_NAME(__divmodsi4) - ldr r1, [sp] - add sp, sp, #4 - pop { pc } -END_COMPILERRT_FUNCTION(__aeabi_idivmod) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/arm/aeabi_idivmod_thumb1.S b/lib/arm/aeabi_idivmod_thumb1.S @@ -1,28 +0,0 @@ -//===-- aeabi_idivmod_thumb1.S - Thumb1 (Cortex-M0/M1) variant -----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Thumb1 has no muls-with-3-operands and limited register-set instructions, -// so __aeabi_idivmod is implemented as: quot = __divsi3(num, denom); -// rem = num - quot * denom. -// Used on ARMv6-M (Cortex-M0/M0+/M1). -//===----------------------------------------------------------------------===// - -#include "assembly.h" - - .syntax unified - .text - DEFINE_CODE_STATE - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_idivmod) - push {r0, r1, lr} - bl SYMBOL_NAME(__divsi3) - pop {r1, r2, r3} // now r0 = quot, r1 = num, r2 = denom - muls r2, r0, r2 // r2 = quot * denom - subs r1, r1, r2 - JMP (r3) -END_COMPILERRT_FUNCTION(__aeabi_idivmod) - -NO_EXEC_STACK_DIRECTIVE diff --git a/lib/arm/aeabi_ldivmod.S b/lib/arm/aeabi_ldivmod.S @@ -1,34 +0,0 @@ -//===-- aeabi_ldivmod.S - EABI ldivmod implementation ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// struct { int64_t quot, int64_t rem} -// __aeabi_ldivmod(int64_t numerator, int64_t denominator) { -// int64_t rem, quot; -// quot = __divmoddi4(numerator, denominator, &rem); -// return {quot, rem}; -// } - - - .syntax unified - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_ldivmod) - push {r6, lr} - sub sp, sp, #16 - add r6, sp, #8 - str r6, [sp] - bl SYMBOL_NAME(__divmoddi4) - ldr r2, [sp, #8] - ldr r3, [sp, #12] - add sp, sp, #16 - pop {r6, pc} -END_COMPILERRT_FUNCTION(__aeabi_ldivmod) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/arm/aeabi_memcmp.S b/lib/arm/aeabi_memcmp.S @@ -1,23 +0,0 @@ -//===-- aeabi_memcmp.S - EABI memcmp implementation -----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// void __aeabi_memcmp(void *dest, void *src, size_t n) { memcmp(dest, src, n); } - - .syntax unified - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memcmp) - b memcmp -END_COMPILERRT_FUNCTION(__aeabi_memcmp) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp4, __aeabi_memcmp) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp8, __aeabi_memcmp) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/arm/aeabi_memcmp_thumb1.S b/lib/arm/aeabi_memcmp_thumb1.S @@ -1,25 +0,0 @@ -//===-- aeabi_memcmp_thumb1.S - Thumb1 (Cortex-M0/M1) variant ------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Used on ARMv6-M (Cortex-M0/M0+/M1). -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// void __aeabi_memcmp(void *dest, void *src, size_t n) { memcmp(dest, src, n); } - - .syntax unified - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memcmp) - push {r7, lr} - bl memcmp - pop {r7, pc} -END_COMPILERRT_FUNCTION(__aeabi_memcmp) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp4, __aeabi_memcmp) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp8, __aeabi_memcmp) - -NO_EXEC_STACK_DIRECTIVE diff --git a/lib/arm/aeabi_memcpy.S b/lib/arm/aeabi_memcpy.S @@ -1,23 +0,0 @@ -//===-- aeabi_memcpy.S - EABI memcpy implementation -----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// void __aeabi_memcpy(void *dest, void *src, size_t n) { memcpy(dest, src, n); } - - .syntax unified - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memcpy) - b memcpy -END_COMPILERRT_FUNCTION(__aeabi_memcpy) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy4, __aeabi_memcpy) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy8, __aeabi_memcpy) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/arm/aeabi_memcpy_thumb1.S b/lib/arm/aeabi_memcpy_thumb1.S @@ -1,25 +0,0 @@ -//===-- aeabi_memcpy_thumb1.S - Thumb1 (Cortex-M0/M1) variant ------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Used on ARMv6-M (Cortex-M0/M0+/M1). -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// void __aeabi_memcpy(void *dest, void *src, size_t n) { memcpy(dest, src, n); } - - .syntax unified - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memcpy) - push {r7, lr} - bl memcpy - pop {r7, pc} -END_COMPILERRT_FUNCTION(__aeabi_memcpy) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy4, __aeabi_memcpy) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy8, __aeabi_memcpy) - -NO_EXEC_STACK_DIRECTIVE diff --git a/lib/arm/aeabi_memmove.S b/lib/arm/aeabi_memmove.S @@ -1,22 +0,0 @@ -//===-- aeabi_memmove.S - EABI memmove implementation --------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===---------------------------------------------------------------------===// - -#include "assembly.h" - -// void __aeabi_memmove(void *dest, void *src, size_t n) { memmove(dest, src, n); } - - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memmove) - b memmove -END_COMPILERRT_FUNCTION(__aeabi_memmove) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove4, __aeabi_memmove) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove8, __aeabi_memmove) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/arm/aeabi_memmove_thumb1.S b/lib/arm/aeabi_memmove_thumb1.S @@ -1,24 +0,0 @@ -//===-- aeabi_memmove_thumb1.S - Thumb1 (Cortex-M0/M1) variant -----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Used on ARMv6-M (Cortex-M0/M0+/M1). -//===---------------------------------------------------------------------===// - -#include "assembly.h" - -// void __aeabi_memmove(void *dest, void *src, size_t n) { memmove(dest, src, n); } - - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memmove) - push {r7, lr} - bl memmove - pop {r7, pc} -END_COMPILERRT_FUNCTION(__aeabi_memmove) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove4, __aeabi_memmove) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove8, __aeabi_memmove) - -NO_EXEC_STACK_DIRECTIVE diff --git a/lib/arm/aeabi_memset.S b/lib/arm/aeabi_memset.S @@ -1,37 +0,0 @@ -//===-- aeabi_memset.S - EABI memset implementation -----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// void __aeabi_memset(void *dest, size_t n, int c) { memset(dest, c, n); } -// void __aeabi_memclr(void *dest, size_t n) { __aeabi_memset(dest, n, 0); } - - .syntax unified - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memset) - mov r3, r1 - mov r1, r2 - mov r2, r3 - b memset -END_COMPILERRT_FUNCTION(__aeabi_memset) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset4, __aeabi_memset) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset8, __aeabi_memset) - - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memclr) - mov r2, r1 - movs r1, #0 - b memset -END_COMPILERRT_FUNCTION(__aeabi_memclr) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr4, __aeabi_memclr) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr8, __aeabi_memclr) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/arm/aeabi_memset_thumb1.S b/lib/arm/aeabi_memset_thumb1.S @@ -1,42 +0,0 @@ -//===-- aeabi_memset_thumb1.S - Thumb1 (Cortex-M0/M1) variant ------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Thumb1 lacks an unconditional `b <reg>` to a far symbol, so we bl/pop -// instead of tail-calling memset. Used on ARMv6-M (Cortex-M0/M0+/M1). -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// void __aeabi_memset(void *dest, size_t n, int c) { memset(dest, c, n); } -// void __aeabi_memclr(void *dest, size_t n) { __aeabi_memset(dest, n, 0); } - - .syntax unified - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memset) - mov r3, r1 - mov r1, r2 - mov r2, r3 - push {r7, lr} - bl memset - pop {r7, pc} -END_COMPILERRT_FUNCTION(__aeabi_memset) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset4, __aeabi_memset) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset8, __aeabi_memset) - - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_memclr) - mov r2, r1 - movs r1, #0 - push {r7, lr} - bl memset - pop {r7, pc} -END_COMPILERRT_FUNCTION(__aeabi_memclr) - -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr4, __aeabi_memclr) -DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr8, __aeabi_memclr) - -NO_EXEC_STACK_DIRECTIVE diff --git a/lib/arm/aeabi_thumb1.S b/lib/arm/aeabi_thumb1.S @@ -0,0 +1,261 @@ +// Consolidated AEABI helpers for cfree's libcfree_rt.a (ARM Thumb1 mode). +// The build assembles only this one file for the Thumb1 ISA mode; the per-op +// files are #included as snippets and not directly built. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// ISA-agnostic helpers +// ---- aeabi_ldivmod.S ---- +#include "assembly.h" + +// struct { int64_t quot, int64_t rem} +// __aeabi_ldivmod(int64_t numerator, int64_t denominator) { +// int64_t rem, quot; +// quot = __divmoddi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_ldivmod) + push {r6, lr} + sub sp, sp, #16 + add r6, sp, #8 + str r6, [sp] + bl SYMBOL_NAME(__divmoddi4) + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r6, pc} +END_COMPILERRT_FUNCTION(__aeabi_ldivmod) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_uldivmod.S ---- +#include "assembly.h" + +// struct { uint64_t quot, uint64_t rem} +// __aeabi_uldivmod(uint64_t numerator, uint64_t denominator) { +// uint64_t rem, quot; +// quot = __udivmoddi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod) + push {r6, lr} + sub sp, sp, #16 + add r6, sp, #8 + str r6, [sp] + bl SYMBOL_NAME(__udivmoddi4) + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r6, pc} +END_COMPILERRT_FUNCTION(__aeabi_uldivmod) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_dcmp.S ---- +#include "assembly.h" + +// int __aeabi_dcmp{eq,lt,le,ge,gt}(double a, double b) { +// int result = __{eq,lt,le,ge,gt}df2(a, b); +// if (result {==,<,<=,>=,>} 0) { +// return 1; +// } else { +// return 0; +// } +// } + +# define CONVERT_DCMP_ARGS_TO_DF2_ARGS + +#define DEFINE_AEABI_DCMP(cond) \ + .syntax unified SEPARATOR \ + .p2align 2 SEPARATOR \ +DEFINE_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) \ + push { r4, lr } SEPARATOR \ + CONVERT_DCMP_ARGS_TO_DF2_ARGS SEPARATOR \ + bl SYMBOL_NAME(__ ## cond ## df2) SEPARATOR \ + cmp r0, #0 SEPARATOR \ + b ## cond 1f SEPARATOR \ + movs r0, #0 SEPARATOR \ + pop { r4, pc } SEPARATOR \ +1: SEPARATOR \ + movs r0, #1 SEPARATOR \ + pop { r4, pc } SEPARATOR \ +END_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) + +DEFINE_AEABI_DCMP(eq) +DEFINE_AEABI_DCMP(lt) +DEFINE_AEABI_DCMP(le) +DEFINE_AEABI_DCMP(ge) +DEFINE_AEABI_DCMP(gt) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_fcmp.S ---- +#include "assembly.h" + +// int __aeabi_fcmp{eq,lt,le,ge,gt}(float a, float b) { +// int result = __{eq,lt,le,ge,gt}sf2(a, b); +// if (result {==,<,<=,>=,>} 0) { +// return 1; +// } else { +// return 0; +// } +// } + +# define CONVERT_FCMP_ARGS_TO_SF2_ARGS + +#define DEFINE_AEABI_FCMP(cond) \ + .syntax unified SEPARATOR \ + .p2align 2 SEPARATOR \ +DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) \ + push { r4, lr } SEPARATOR \ + CONVERT_FCMP_ARGS_TO_SF2_ARGS SEPARATOR \ + bl SYMBOL_NAME(__ ## cond ## sf2) SEPARATOR \ + cmp r0, #0 SEPARATOR \ + b ## cond 1f SEPARATOR \ + movs r0, #0 SEPARATOR \ + pop { r4, pc } SEPARATOR \ +1: SEPARATOR \ + movs r0, #1 SEPARATOR \ + pop { r4, pc } SEPARATOR \ +END_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) + +DEFINE_AEABI_FCMP(eq) +DEFINE_AEABI_FCMP(lt) +DEFINE_AEABI_FCMP(le) +DEFINE_AEABI_FCMP(ge) +DEFINE_AEABI_FCMP(gt) + +NO_EXEC_STACK_DIRECTIVE + + +// Thumb1-specific helpers +// ---- aeabi_idivmod_thumb1.S ---- +#include "assembly.h" + + .syntax unified + .text + DEFINE_CODE_STATE + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_idivmod) + push {r0, r1, lr} + bl SYMBOL_NAME(__divsi3) + pop {r1, r2, r3} // now r0 = quot, r1 = num, r2 = denom + muls r2, r0, r2 // r2 = quot * denom + subs r1, r1, r2 + JMP (r3) +END_COMPILERRT_FUNCTION(__aeabi_idivmod) + +NO_EXEC_STACK_DIRECTIVE +// ---- aeabi_uidivmod_thumb1.S ---- +#include "assembly.h" + + .syntax unified + .text + DEFINE_CODE_STATE + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_uidivmod) + cmp r0, r1 + bcc LOCAL_LABEL(case_denom_larger) + push {r0, r1, lr} + bl SYMBOL_NAME(__aeabi_uidiv) + pop {r1, r2, r3} + muls r2, r0, r2 // r2 = quot * denom + subs r1, r1, r2 + JMP (r3) +LOCAL_LABEL(case_denom_larger): + movs r1, r0 + movs r0, #0 + JMP (lr) +END_COMPILERRT_FUNCTION(__aeabi_uidivmod) + +NO_EXEC_STACK_DIRECTIVE +// ---- aeabi_memcpy_thumb1.S ---- +#include "assembly.h" + +// void __aeabi_memcpy(void *dest, void *src, size_t n) { memcpy(dest, src, n); } + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memcpy) + push {r7, lr} + bl memcpy + pop {r7, pc} +END_COMPILERRT_FUNCTION(__aeabi_memcpy) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy4, __aeabi_memcpy) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy8, __aeabi_memcpy) + +NO_EXEC_STACK_DIRECTIVE +// ---- aeabi_memmove_thumb1.S ---- +#include "assembly.h" + +// void __aeabi_memmove(void *dest, void *src, size_t n) { memmove(dest, src, n); } + + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memmove) + push {r7, lr} + bl memmove + pop {r7, pc} +END_COMPILERRT_FUNCTION(__aeabi_memmove) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove4, __aeabi_memmove) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove8, __aeabi_memmove) + +NO_EXEC_STACK_DIRECTIVE +// ---- aeabi_memset_thumb1.S ---- +#include "assembly.h" + +// void __aeabi_memset(void *dest, size_t n, int c) { memset(dest, c, n); } +// void __aeabi_memclr(void *dest, size_t n) { __aeabi_memset(dest, n, 0); } + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memset) + mov r3, r1 + mov r1, r2 + mov r2, r3 + push {r7, lr} + bl memset + pop {r7, pc} +END_COMPILERRT_FUNCTION(__aeabi_memset) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset4, __aeabi_memset) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset8, __aeabi_memset) + + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memclr) + mov r2, r1 + movs r1, #0 + push {r7, lr} + bl memset + pop {r7, pc} +END_COMPILERRT_FUNCTION(__aeabi_memclr) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr4, __aeabi_memclr) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr8, __aeabi_memclr) + +NO_EXEC_STACK_DIRECTIVE +// ---- aeabi_memcmp_thumb1.S ---- +#include "assembly.h" + +// void __aeabi_memcmp(void *dest, void *src, size_t n) { memcmp(dest, src, n); } + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memcmp) + push {r7, lr} + bl memcmp + pop {r7, pc} +END_COMPILERRT_FUNCTION(__aeabi_memcmp) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp4, __aeabi_memcmp) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp8, __aeabi_memcmp) + +NO_EXEC_STACK_DIRECTIVE diff --git a/lib/arm/aeabi_thumb2.S b/lib/arm/aeabi_thumb2.S @@ -0,0 +1,268 @@ +// Consolidated AEABI helpers for cfree's libcfree_rt.a (ARM Thumb2 mode). +// The build assembles only this one file for the Thumb2 ISA mode; the per-op +// files are #included as snippets and not directly built. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// ISA-agnostic helpers +// ---- aeabi_ldivmod.S ---- +#include "assembly.h" + +// struct { int64_t quot, int64_t rem} +// __aeabi_ldivmod(int64_t numerator, int64_t denominator) { +// int64_t rem, quot; +// quot = __divmoddi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_ldivmod) + push {r6, lr} + sub sp, sp, #16 + add r6, sp, #8 + str r6, [sp] + bl SYMBOL_NAME(__divmoddi4) + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r6, pc} +END_COMPILERRT_FUNCTION(__aeabi_ldivmod) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_uldivmod.S ---- +#include "assembly.h" + +// struct { uint64_t quot, uint64_t rem} +// __aeabi_uldivmod(uint64_t numerator, uint64_t denominator) { +// uint64_t rem, quot; +// quot = __udivmoddi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod) + push {r6, lr} + sub sp, sp, #16 + add r6, sp, #8 + str r6, [sp] + bl SYMBOL_NAME(__udivmoddi4) + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r6, pc} +END_COMPILERRT_FUNCTION(__aeabi_uldivmod) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_dcmp.S ---- +#include "assembly.h" + +// int __aeabi_dcmp{eq,lt,le,ge,gt}(double a, double b) { +// int result = __{eq,lt,le,ge,gt}df2(a, b); +// if (result {==,<,<=,>=,>} 0) { +// return 1; +// } else { +// return 0; +// } +// } + +# define CONVERT_DCMP_ARGS_TO_DF2_ARGS + +#define DEFINE_AEABI_DCMP(cond) \ + .syntax unified SEPARATOR \ + .p2align 2 SEPARATOR \ +DEFINE_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) \ + push { r4, lr } SEPARATOR \ + CONVERT_DCMP_ARGS_TO_DF2_ARGS SEPARATOR \ + bl SYMBOL_NAME(__ ## cond ## df2) SEPARATOR \ + cmp r0, #0 SEPARATOR \ + b ## cond 1f SEPARATOR \ + movs r0, #0 SEPARATOR \ + pop { r4, pc } SEPARATOR \ +1: SEPARATOR \ + movs r0, #1 SEPARATOR \ + pop { r4, pc } SEPARATOR \ +END_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) + +DEFINE_AEABI_DCMP(eq) +DEFINE_AEABI_DCMP(lt) +DEFINE_AEABI_DCMP(le) +DEFINE_AEABI_DCMP(ge) +DEFINE_AEABI_DCMP(gt) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_fcmp.S ---- +#include "assembly.h" + +// int __aeabi_fcmp{eq,lt,le,ge,gt}(float a, float b) { +// int result = __{eq,lt,le,ge,gt}sf2(a, b); +// if (result {==,<,<=,>=,>} 0) { +// return 1; +// } else { +// return 0; +// } +// } + +# define CONVERT_FCMP_ARGS_TO_SF2_ARGS + +#define DEFINE_AEABI_FCMP(cond) \ + .syntax unified SEPARATOR \ + .p2align 2 SEPARATOR \ +DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) \ + push { r4, lr } SEPARATOR \ + CONVERT_FCMP_ARGS_TO_SF2_ARGS SEPARATOR \ + bl SYMBOL_NAME(__ ## cond ## sf2) SEPARATOR \ + cmp r0, #0 SEPARATOR \ + b ## cond 1f SEPARATOR \ + movs r0, #0 SEPARATOR \ + pop { r4, pc } SEPARATOR \ +1: SEPARATOR \ + movs r0, #1 SEPARATOR \ + pop { r4, pc } SEPARATOR \ +END_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) + +DEFINE_AEABI_FCMP(eq) +DEFINE_AEABI_FCMP(lt) +DEFINE_AEABI_FCMP(le) +DEFINE_AEABI_FCMP(ge) +DEFINE_AEABI_FCMP(gt) + +NO_EXEC_STACK_DIRECTIVE + + +// Thumb2-specific helpers +// ---- aeabi_idivmod.S ---- +#include "assembly.h" + +// struct { int quot, int rem} __aeabi_idivmod(int numerator, int denominator) { +// int rem, quot; +// quot = __divmodsi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + + + .syntax unified + .text + DEFINE_CODE_STATE + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_idivmod) + push { lr } + sub sp, sp, #4 + mov r2, sp + bl SYMBOL_NAME(__divmodsi4) + ldr r1, [sp] + add sp, sp, #4 + pop { pc } +END_COMPILERRT_FUNCTION(__aeabi_idivmod) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_uidivmod.S ---- +#include "assembly.h" + +// struct { unsigned quot, unsigned rem} +// __aeabi_uidivmod(unsigned numerator, unsigned denominator) { +// unsigned rem, quot; +// quot = __udivmodsi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + + + .syntax unified + .text + DEFINE_CODE_STATE + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_uidivmod) + push { lr } + sub sp, sp, #4 + mov r2, sp + bl SYMBOL_NAME(__udivmodsi4) + ldr r1, [sp] + add sp, sp, #4 + pop { pc } +END_COMPILERRT_FUNCTION(__aeabi_uidivmod) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_memcpy.S ---- +#include "assembly.h" + +// void __aeabi_memcpy(void *dest, void *src, size_t n) { memcpy(dest, src, n); } + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memcpy) + b memcpy +END_COMPILERRT_FUNCTION(__aeabi_memcpy) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy4, __aeabi_memcpy) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy8, __aeabi_memcpy) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_memmove.S ---- +#include "assembly.h" + +// void __aeabi_memmove(void *dest, void *src, size_t n) { memmove(dest, src, n); } + + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memmove) + b memmove +END_COMPILERRT_FUNCTION(__aeabi_memmove) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove4, __aeabi_memmove) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove8, __aeabi_memmove) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_memset.S ---- +#include "assembly.h" + +// void __aeabi_memset(void *dest, size_t n, int c) { memset(dest, c, n); } +// void __aeabi_memclr(void *dest, size_t n) { __aeabi_memset(dest, n, 0); } + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memset) + mov r3, r1 + mov r1, r2 + mov r2, r3 + b memset +END_COMPILERRT_FUNCTION(__aeabi_memset) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset4, __aeabi_memset) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset8, __aeabi_memset) + + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memclr) + mov r2, r1 + movs r1, #0 + b memset +END_COMPILERRT_FUNCTION(__aeabi_memclr) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr4, __aeabi_memclr) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr8, __aeabi_memclr) + +NO_EXEC_STACK_DIRECTIVE + +// ---- aeabi_memcmp.S ---- +#include "assembly.h" + +// void __aeabi_memcmp(void *dest, void *src, size_t n) { memcmp(dest, src, n); } + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_memcmp) + b memcmp +END_COMPILERRT_FUNCTION(__aeabi_memcmp) + +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp4, __aeabi_memcmp) +DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp8, __aeabi_memcmp) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/lib/arm/aeabi_uidivmod.S b/lib/arm/aeabi_uidivmod.S @@ -1,34 +0,0 @@ -//===-- aeabi_uidivmod.S - EABI uidivmod implementation -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// struct { unsigned quot, unsigned rem} -// __aeabi_uidivmod(unsigned numerator, unsigned denominator) { -// unsigned rem, quot; -// quot = __udivmodsi4(numerator, denominator, &rem); -// return {quot, rem}; -// } - - - .syntax unified - .text - DEFINE_CODE_STATE - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_uidivmod) - push { lr } - sub sp, sp, #4 - mov r2, sp - bl SYMBOL_NAME(__udivmodsi4) - ldr r1, [sp] - add sp, sp, #4 - pop { pc } -END_COMPILERRT_FUNCTION(__aeabi_uidivmod) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/arm/aeabi_uidivmod_thumb1.S b/lib/arm/aeabi_uidivmod_thumb1.S @@ -1,31 +0,0 @@ -//===-- aeabi_uidivmod_thumb1.S - Thumb1 (Cortex-M0/M1) variant ----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Used on ARMv6-M (Cortex-M0/M0+/M1). -//===----------------------------------------------------------------------===// - -#include "assembly.h" - - .syntax unified - .text - DEFINE_CODE_STATE - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_uidivmod) - cmp r0, r1 - bcc LOCAL_LABEL(case_denom_larger) - push {r0, r1, lr} - bl SYMBOL_NAME(__aeabi_uidiv) - pop {r1, r2, r3} - muls r2, r0, r2 // r2 = quot * denom - subs r1, r1, r2 - JMP (r3) -LOCAL_LABEL(case_denom_larger): - movs r1, r0 - movs r0, #0 - JMP (lr) -END_COMPILERRT_FUNCTION(__aeabi_uidivmod) - -NO_EXEC_STACK_DIRECTIVE diff --git a/lib/arm/aeabi_uldivmod.S b/lib/arm/aeabi_uldivmod.S @@ -1,34 +0,0 @@ -//===-- aeabi_uldivmod.S - EABI uldivmod implementation -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "assembly.h" - -// struct { uint64_t quot, uint64_t rem} -// __aeabi_uldivmod(uint64_t numerator, uint64_t denominator) { -// uint64_t rem, quot; -// quot = __udivmoddi4(numerator, denominator, &rem); -// return {quot, rem}; -// } - - - .syntax unified - .p2align 2 -DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod) - push {r6, lr} - sub sp, sp, #16 - add r6, sp, #8 - str r6, [sp] - bl SYMBOL_NAME(__udivmoddi4) - ldr r2, [sp, #8] - ldr r3, [sp, #12] - add sp, sp, #16 - pop {r6, pc} -END_COMPILERRT_FUNCTION(__aeabi_uldivmod) - -NO_EXEC_STACK_DIRECTIVE - diff --git a/lib/build.sh b/lib/build.sh @@ -1,16 +1,10 @@ -#!/usr/bin/env bash +#!/bin/sh # -# build.sh — exhaustive build of libcfree_rt.a for every (target, mode) tuple -# cfree supports. Compiles every required source file with clang for each -# variant; on success, archives the objects with llvm-ar (if present) into -# $OUT/libcfree_rt-<variant>.a. -# -# Reports OK / FAIL per variant; exits non-zero if any fail. -# Override defaults via env: CC=clang OUT=/tmp/cfree_rt_build AR=llvm-ar. -# -# Run from anywhere — the script self-locates and cd's to lib/ first. +# build2.sh — POSIX sh port of build.sh. Same behavior, no arrays, no +# pipefail, no local. Source/flag lists are space-separated strings; +# unquoted expansion does the splitting. -set -uo pipefail +set -u cd "$(dirname "$0")" || exit 1 @@ -18,57 +12,51 @@ CC=${CC:-clang} AR=${AR:-llvm-ar} OUT=${OUT:-/tmp/cfree_rt_build} -# Freestanding, warnings on, common headers reachable. -fno-builtin keeps the -# compiler from rewriting our memcpy/memset/etc. into recursive calls. -COMMON_FLAGS=(-c -ffreestanding -fno-builtin -Wall -Wextra - -Iinclude/common -Iimpl) +COMMON_FLAGS="-c -ffreestanding -fno-builtin -Wall -Wextra -Iinclude/common -Iimpl" mkdir -p "$OUT" OK=0 FAIL=0 -FAILED_VARIANTS=() +FAILED_VARIANTS="" #------------------------------------------------------------------------------- -# build_variant <name> "<extra cc flags>" <source files...> +# build_variant <name> <extra-cc-flags> <sources> #------------------------------------------------------------------------------- build_variant() { - local name=$1 - local flags_str=$2 - shift 2 - local sources=("$@") - # shellcheck disable=SC2206 - local flags=( $flags_str ) - - local out="$OUT/$name" + name=$1 + flags=$2 + sources=$3 + + out="$OUT/$name" mkdir -p "$out" - local log="$out/build.log" + log="$out/build.log" : >"$log" - local objs=() - local nfail=0 - for src in "${sources[@]}"; do - local obj="$out/$(echo "$src" | tr / _).o" - if "$CC" "${COMMON_FLAGS[@]}" "${flags[@]}" -o "$obj" "$src" >>"$log" 2>&1; then - objs+=("$obj") + objs="" + nfail=0 + total=0 + for src in $sources; do + total=$((total+1)) + obj="$out/$(echo "$src" | tr / _).o" + if $CC $COMMON_FLAGS $flags -o "$obj" "$src" >>"$log" 2>&1; then + objs="$objs $obj" else nfail=$((nfail+1)) echo "FAIL: $src" >>"$log" fi done - local total=${#sources[@]} if [ $nfail -ne 0 ]; then printf " %-32s FAIL (%d/%d sources failed; see %s)\n" \ "$name" "$nfail" "$total" "$log" FAIL=$((FAIL+1)) - FAILED_VARIANTS+=("$name") + FAILED_VARIANTS="$FAILED_VARIANTS $name" return fi - # Archive (best-effort; not fatal if AR is missing). if command -v "$AR" >/dev/null 2>&1; then - local archive="$OUT/libcfree_rt-$name.a" - if "$AR" rcs "$archive" "${objs[@]}" 2>>"$log"; then + archive="$OUT/libcfree_rt-$name.a" + if $AR rcs "$archive" $objs 2>>"$log"; then printf " %-32s OK (%d objs → %s)\n" \ "$name" "$total" "$(basename "$archive")" else @@ -83,142 +71,110 @@ build_variant() { } #------------------------------------------------------------------------------- -# Source sets +# Source sets — one master .c (and/or .S) per feature flag. Each master +# #include's its per-op snippets in dependency order; the per-op files +# are NOT compiled directly. #------------------------------------------------------------------------------- - -INT_C=( int/*.c ) -INT32_C=( int32/*.c ) -INT64_C=( int64/*.c ) -FP_C=( fp/*.c ) -FP_TF_C=( fp_tf/*.c ) -FP_TI_C=( fp_ti/*.c ) -MEM_C=( mem/mem.c ) -ATOMIC_C=( atomic/atomic_freestanding.c ) - -# ARM AEABI: 6 base files have a *_thumb1.S companion (idivmod, uidivmod, -# memcpy, memmove, memset, memcmp). The Thumb2 build uses base files only; -# the Thumb1 build uses *_thumb1.S in place of those base files, plus the -# ISA-agnostic ones (ldivmod, uldivmod, dcmp, fcmp, drsub, frsub). -ARM_AEABI_THUMB2=( arm/aeabi_*.S arm/aeabi_*.c ) -# Filter out *_thumb1.S from the Thumb2 list. -_t2=() -for f in "${ARM_AEABI_THUMB2[@]}"; do - case "$f" in *_thumb1.S) ;; *) _t2+=("$f") ;; esac -done -ARM_AEABI_THUMB2=("${_t2[@]}") - -# Build the Thumb1 list: every *_thumb1.S, plus any base file whose stem has -# no *_thumb1.S partner. -_thumb1_stems=() -for f in arm/aeabi_*_thumb1.S; do - _thumb1_stems+=( "$(basename "$f" _thumb1.S)" ) -done -ARM_AEABI_THUMB1=( arm/aeabi_*_thumb1.S ) -for f in "${ARM_AEABI_THUMB2[@]}"; do - stem=$(basename "$f" .S); stem=$(basename "$stem" .c) - has_t1=0 - for s in "${_thumb1_stems[@]}"; do - [ "$stem" = "$s" ] && { has_t1=1; break; } - done - [ $has_t1 -eq 0 ] && ARM_AEABI_THUMB1+=("$f") -done - -RV32_SR=( riscv/save_rv32.S riscv/restore_rv32.S ) -RV64_SR=( riscv/save_rv64.S riscv/restore_rv64.S ) +INT_C="int/int.c" +INT32_C="int32/int32.c" +INT64_C="int64/int64.c" +FP_C="fp/fp.c" +FP_TF_C="fp_tf/fp_tf.c" +FP_TI_C="fp_ti/fp_ti.c" +MEM_C="mem/mem.c" +ATOMIC_C="atomic/atomic_freestanding.c" + +# ARM AEABI: one master .S per ISA mode (Thumb2 vs Thumb1) plus one +# ISA-agnostic .c (drsub + frsub). +ARM_AEABI_THUMB2="arm/aeabi_thumb2.S arm/aeabi.c" +ARM_AEABI_THUMB1="arm/aeabi_thumb1.S arm/aeabi.c" + +# RISC-V save/restore: one master .S per xlen. +RV32_SR="riscv/rv32.S" +RV64_SR="riscv/rv64.S" #------------------------------------------------------------------------------- -# Variants — each combination of (data model, target, mode) cfree supports. +# Variants #------------------------------------------------------------------------------- echo "Building libcfree_rt for every supported (target, mode) tuple" echo " CC=$CC, AR=$AR, OUT=$OUT" echo # ---- LP64 little-endian ------------------------------------------------------ - -# x86_64 Linux / Darwin / RV64 / aarch64 base: int + int64 + fp + atomic + mem. -# binary64 long double (no fp_tf). -LP64_BASE=( "${INT_C[@]}" "${INT64_C[@]}" "${FP_C[@]}" "${MEM_C[@]}" "${ATOMIC_C[@]}" ) +LP64_BASE="$INT_C $INT64_C $FP_C $MEM_C $ATOMIC_C" build_variant x86_64-linux \ "--target=x86_64-linux-gnu -Iinclude/lp64_le -DHAS_INT128=1" \ - "${LP64_BASE[@]}" + "$LP64_BASE" build_variant x86_64-apple-darwin \ "--target=x86_64-apple-darwin -Iinclude/lp64_le -DHAS_INT128=1" \ - "${LP64_BASE[@]}" + "$LP64_BASE" -# aarch64-linux: long double is binary128 by default (no flag to change), -# so the build pulls in fp_tf + fp_ti and pre-includes tf_supplement.h. +# aarch64-linux: long double is binary128; needs fp_tf + fp_ti and the +# tf_supplement.h pre-include. build_variant aarch64-linux \ "--target=aarch64-linux-gnu \ -Iinclude/lp64_le_ldbl128 -Iinclude/lp64_le -DHAS_INT128=1 \ -include include/lp64_le_ldbl128/tf_supplement.h" \ - "${INT_C[@]}" "${INT64_C[@]}" "${FP_C[@]}" "${FP_TF_C[@]}" "${FP_TI_C[@]}" \ - "${MEM_C[@]}" "${ATOMIC_C[@]}" + "$INT_C $INT64_C $FP_C $FP_TF_C $FP_TI_C $MEM_C $ATOMIC_C" -# aarch64-apple-darwin: long double is binary64 (no fp_tf needed). build_variant aarch64-apple-darwin \ "--target=aarch64-apple-darwin -Iinclude/lp64_le -DHAS_INT128=1" \ - "${LP64_BASE[@]}" + "$LP64_BASE" -# RISC-V 64 (soft-float) — with and without -msave-restore. build_variant riscv64-elf \ "--target=riscv64-unknown-elf -mabi=lp64 -march=rv64imafd \ -Iinclude/lp64_le -DHAS_INT128=1" \ - "${LP64_BASE[@]}" + "$LP64_BASE" build_variant riscv64-elf-save-restore \ "--target=riscv64-unknown-elf -mabi=lp64 -march=rv64imafd -msave-restore \ -Iinclude/lp64_le -DHAS_INT128=1" \ - "${LP64_BASE[@]}" "${RV64_SR[@]}" + "$LP64_BASE $RV64_SR" # ---- LLP64 little-endian (Win64) -------------------------------------------- - build_variant x86_64-pc-windows \ "--target=x86_64-pc-windows-msvc -Iinclude/llp64_le -DHAS_INT128=1" \ - "${INT_C[@]}" "${INT64_C[@]}" "${FP_C[@]}" "${MEM_C[@]}" "${ATOMIC_C[@]}" + "$INT_C $INT64_C $FP_C $MEM_C $ATOMIC_C" # ---- ILP32 little-endian ----------------------------------------------------- - -ILP32_BASE=( "${INT_C[@]}" "${INT32_C[@]}" "${FP_C[@]}" "${MEM_C[@]}" "${ATOMIC_C[@]}" ) +ILP32_BASE="$INT_C $INT32_C $FP_C $MEM_C $ATOMIC_C" build_variant i386-linux \ "--target=i386-linux-gnu -Iinclude/ilp32_le -DHAS_INT128=0" \ - "${ILP32_BASE[@]}" + "$ILP32_BASE" build_variant wasm32 \ "--target=wasm32-unknown-unknown -Iinclude/ilp32_le -DHAS_INT128=0" \ - "${ILP32_BASE[@]}" + "$ILP32_BASE" build_variant riscv32-elf \ "--target=riscv32-unknown-elf -mabi=ilp32 -march=rv32imafd \ -Iinclude/ilp32_le -DHAS_INT128=0" \ - "${ILP32_BASE[@]}" + "$ILP32_BASE" build_variant riscv32-elf-save-restore \ "--target=riscv32-unknown-elf -mabi=ilp32 -march=rv32imafd -msave-restore \ -Iinclude/ilp32_le -DHAS_INT128=0" \ - "${ILP32_BASE[@]}" "${RV32_SR[@]}" + "$ILP32_BASE $RV32_SR" -# ARM32 ARMv7+/Thumb2 (AEABI). The .S files use the AEABI base PCS regardless -# of FPU presence, so one variant covers soft- and hard-float targets. build_variant arm-eabi-thumb2 \ "--target=arm-none-eabi -march=armv7-a -mthumb -mfloat-abi=soft \ -Iinclude/ilp32_le -DHAS_INT128=0" \ - "${ILP32_BASE[@]}" "${ARM_AEABI_THUMB2[@]}" + "$ILP32_BASE $ARM_AEABI_THUMB2" -# ARM32 ARMv6-M / Cortex-M0/M0+/M1 (Thumb1). build_variant arm-eabi-thumb1 \ "--target=arm-none-eabi -march=armv6-m -mthumb -mfloat-abi=soft \ -Iinclude/ilp32_le -DHAS_INT128=0" \ - "${ILP32_BASE[@]}" "${ARM_AEABI_THUMB1[@]}" + "$ILP32_BASE $ARM_AEABI_THUMB1" #------------------------------------------------------------------------------- echo echo "Summary: $OK ok, $FAIL failed" if [ $FAIL -ne 0 ]; then echo "Failed variants:" - for v in "${FAILED_VARIANTS[@]}"; do + for v in $FAILED_VARIANTS; do echo " - $v ($OUT/$v/build.log)" done exit 1 diff --git a/lib/fp/adddf3.c b/lib/fp/adddf3.c @@ -1,17 +0,0 @@ -//===-- lib/adddf3.c - Double-precision addition ------------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements double-precision soft-float addition. -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_add_impl.inc" - -COMPILER_RT_ABI double __adddf3(double a, double b) { return __addXf3__(a, b); } - diff --git a/lib/fp/addsf3.c b/lib/fp/addsf3.c @@ -1,17 +0,0 @@ -//===-- lib/addsf3.c - Single-precision addition ------------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements single-precision soft-float addition. -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_add_impl.inc" - -COMPILER_RT_ABI float __addsf3(float a, float b) { return __addXf3__(a, b); } - diff --git a/lib/fp/comparedf2.c b/lib/fp/comparedf2.c @@ -1,52 +0,0 @@ -//===-- lib/comparedf2.c - Double-precision comparisons -----------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// // This file implements the following soft-float comparison routines: -// -// __eqdf2 __gedf2 __unorddf2 -// __ledf2 __gtdf2 -// __ltdf2 -// __nedf2 -// -// The semantics of the routines grouped in each column are identical, so there -// is a single implementation for each, and wrappers to provide the other names. -// -// The main routines behave as follows: -// -// __ledf2(a,b) returns -1 if a < b -// 0 if a == b -// 1 if a > b -// 1 if either a or b is NaN -// -// __gedf2(a,b) returns -1 if a < b -// 0 if a == b -// 1 if a > b -// -1 if either a or b is NaN -// -// __unorddf2(a,b) returns 0 if both a and b are numbers -// 1 if either a or b is NaN -// -// Note that __ledf2( ) and __gedf2( ) are identical except in their handling of -// NaN values. -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -#include "fp_compare_impl.inc" - -COMPILER_RT_ABI CMP_RESULT __ledf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __eqdf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __ltdf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __nedf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __gedf2(fp_t a, fp_t b) { return __geXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __gtdf2(fp_t a, fp_t b) { return __geXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __unorddf2(fp_t a, fp_t b) { return __unordXf2__(a, b); } - - diff --git a/lib/fp/comparesf2.c b/lib/fp/comparesf2.c @@ -1,52 +0,0 @@ -//===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the following soft-fp_t comparison routines: -// -// __eqsf2 __gesf2 __unordsf2 -// __lesf2 __gtsf2 -// __ltsf2 -// __nesf2 -// -// The semantics of the routines grouped in each column are identical, so there -// is a single implementation for each, and wrappers to provide the other names. -// -// The main routines behave as follows: -// -// __lesf2(a,b) returns -1 if a < b -// 0 if a == b -// 1 if a > b -// 1 if either a or b is NaN -// -// __gesf2(a,b) returns -1 if a < b -// 0 if a == b -// 1 if a > b -// -1 if either a or b is NaN -// -// __unordsf2(a,b) returns 0 if both a and b are numbers -// 1 if either a or b is NaN -// -// Note that __lesf2( ) and __gesf2( ) are identical except in their handling of -// NaN values. -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" - -#include "fp_compare_impl.inc" - -COMPILER_RT_ABI CMP_RESULT __lesf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __eqsf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __ltsf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __nesf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __gesf2(fp_t a, fp_t b) { return __geXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __gtsf2(fp_t a, fp_t b) { return __geXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __unordsf2(fp_t a, fp_t b){ return __unordXf2__(a, b); } - - diff --git a/lib/fp/divdf3.c b/lib/fp/divdf3.c @@ -1,25 +0,0 @@ -//===-- lib/divdf3.c - Double-precision division ------------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements double-precision soft-float division -// with the IEEE-754 default rounding (to nearest, ties to even). -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION - -#define NUMBER_OF_HALF_ITERATIONS 3 -#define NUMBER_OF_FULL_ITERATIONS 1 - -#include "fp_div_impl.inc" - -COMPILER_RT_ABI fp_t __divdf3(fp_t a, fp_t b) { return __divXf3__(a, b); } - - -#undef NUMBER_OF_HALF_ITERATIONS -#undef NUMBER_OF_FULL_ITERATIONS diff --git a/lib/fp/divsf3.c b/lib/fp/divsf3.c @@ -1,27 +0,0 @@ -//===-- lib/divsf3.c - Single-precision division ------------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements single-precision soft-float division -// with the IEEE-754 default rounding (to nearest, ties to even). -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION - -#define NUMBER_OF_HALF_ITERATIONS 0 -#define NUMBER_OF_FULL_ITERATIONS 3 -#define USE_NATIVE_FULL_ITERATIONS - -#include "fp_div_impl.inc" - -COMPILER_RT_ABI fp_t __divsf3(fp_t a, fp_t b) { return __divXf3__(a, b); } - - -#undef NUMBER_OF_HALF_ITERATIONS -#undef NUMBER_OF_FULL_ITERATIONS -#undef USE_NATIVE_FULL_ITERATIONS diff --git a/lib/fp/extendsfdf2.c b/lib/fp/extendsfdf2.c @@ -1,17 +0,0 @@ -//===-- lib/extendsfdf2.c - single -> double conversion -----------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define SRC_SINGLE -#define DST_DOUBLE -#include "fp_extend_impl.inc" - -COMPILER_RT_ABI double __extendsfdf2(float a) { return __extendXfYf2__(a); } - - -#undef SRC_SINGLE -#undef DST_DOUBLE diff --git a/lib/fp/fixdfdi.c b/lib/fp/fixdfdi.c @@ -1,26 +0,0 @@ -//===-- fixdfdi.c - Implement __fixdfdi -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -// Support for systems that don't have hardware floating-point; there are no -// flags to set, and we don't want to code-gen to an unknown soft-float -// implementation. - -#define fixint_t di_int -#define fixuint_t du_int -#define FP_FIX_SUFFIX fixdfdi -#include "fp_fixint_impl.inc" - -COMPILER_RT_ABI di_int __fixdfdi(fp_t a) { return __fixint(a); } - - -#undef fixint_t -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp/fixdfsi.c b/lib/fp/fixdfsi.c @@ -1,21 +0,0 @@ -//===-- fixdfsi.c - Implement __fixdfsi -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" -#define fixint_t si_int -#define fixuint_t su_int -#define FP_FIX_SUFFIX fixdfsi -#include "fp_fixint_impl.inc" - -COMPILER_RT_ABI si_int __fixdfsi(fp_t a) { return __fixint(a); } - - -#undef fixint_t -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp/fixsfdi.c b/lib/fp/fixsfdi.c @@ -1,26 +0,0 @@ -//===-- fixsfdi.c - Implement __fixsfdi -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" - -// Support for systems that don't have hardware floating-point; there are no -// flags to set, and we don't want to code-gen to an unknown soft-float -// implementation. - -#define fixint_t di_int -#define fixuint_t du_int -#define FP_FIX_SUFFIX fixsfdi -#include "fp_fixint_impl.inc" - -COMPILER_RT_ABI di_int __fixsfdi(fp_t a) { return __fixint(a); } - - -#undef fixint_t -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp/fixsfsi.c b/lib/fp/fixsfsi.c @@ -1,21 +0,0 @@ -//===-- fixsfsi.c - Implement __fixsfsi -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" -#define fixint_t si_int -#define fixuint_t su_int -#define FP_FIX_SUFFIX fixsfsi -#include "fp_fixint_impl.inc" - -COMPILER_RT_ABI si_int __fixsfsi(fp_t a) { return __fixint(a); } - - -#undef fixint_t -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp/fixunsdfdi.c b/lib/fp/fixunsdfdi.c @@ -1,24 +0,0 @@ -//===-- fixunsdfdi.c - Implement __fixunsdfdi -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -// Support for systems that don't have hardware floating-point; there are no -// flags to set, and we don't want to code-gen to an unknown soft-float -// implementation. - -#define fixuint_t du_int -#define FP_FIX_SUFFIX fixunsdfdi -#include "fp_fixuint_impl.inc" - -COMPILER_RT_ABI du_int __fixunsdfdi(fp_t a) { return __fixuint(a); } - - -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp/fixunsdfsi.c b/lib/fp/fixunsdfsi.c @@ -1,19 +0,0 @@ -//===-- fixunsdfsi.c - Implement __fixunsdfsi -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" -#define fixuint_t su_int -#define FP_FIX_SUFFIX fixunsdfsi -#include "fp_fixuint_impl.inc" - -COMPILER_RT_ABI su_int __fixunsdfsi(fp_t a) { return __fixuint(a); } - - -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp/fixunssfdi.c b/lib/fp/fixunssfdi.c @@ -1,24 +0,0 @@ -//===-- fixunssfdi.c - Implement __fixunssfdi -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" - -// Support for systems that don't have hardware floating-point; there are no -// flags to set, and we don't want to code-gen to an unknown soft-float -// implementation. - -#define fixuint_t du_int -#define FP_FIX_SUFFIX fixunssfdi -#include "fp_fixuint_impl.inc" - -COMPILER_RT_ABI du_int __fixunssfdi(fp_t a) { return __fixuint(a); } - - -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp/fixunssfsi.c b/lib/fp/fixunssfsi.c @@ -1,23 +0,0 @@ -//===-- fixunssfsi.c - Implement __fixunssfsi -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __fixunssfsi for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" -#define fixuint_t su_int -#define FP_FIX_SUFFIX fixunssfsi -#include "fp_fixuint_impl.inc" - -COMPILER_RT_ABI su_int __fixunssfsi(fp_t a) { return __fixuint(a); } - - -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp/floatdidf.c b/lib/fp/floatdidf.c @@ -1,35 +0,0 @@ -//===-- floatdidf.c - Implement __floatdidf -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __floatdidf for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: convert a to a double, rounding toward even. - -// Assumption: double is a IEEE 64 bit floating point type -// di_int is a 64 bit integral type - -// seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm -// mmmm - -// Support for systems that don't have hardware floating-point; there are no -// flags to set, and we don't want to code-gen to an unknown soft-float -// implementation. - -#define SRC_I64 -#define DST_DOUBLE -#include "int_to_fp_impl.inc" - -COMPILER_RT_ABI double __floatdidf(di_int a) { return __floatXiYf__(a); } - - -#undef SRC_I64 -#undef DST_DOUBLE diff --git a/lib/fp/floatdisf.c b/lib/fp/floatdisf.c @@ -1,30 +0,0 @@ -//===-- floatdisf.c - Implement __floatdisf -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __floatdisf for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -// Returns: convert a to a float, rounding toward even. - -// Assumption: float is a IEEE 32 bit floating point type -// di_int is a 64 bit integral type - -// seee eeee emmm mmmm mmmm mmmm mmmm mmmm - -#include "int_lib.h" - -#define SRC_I64 -#define DST_SINGLE -#include "int_to_fp_impl.inc" - -COMPILER_RT_ABI float __floatdisf(di_int a) { return __floatXiYf__(a); } - - -#undef SRC_I64 -#undef DST_SINGLE diff --git a/lib/fp/floatsidf.c b/lib/fp/floatsidf.c @@ -1,51 +0,0 @@ -//===-- lib/floatsidf.c - integer -> double-precision conversion --*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements integer to double-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -#include "int_lib.h" - -COMPILER_RT_ABI fp_t __floatsidf(si_int a) { - - const int aWidth = sizeof a * CHAR_BIT; - - // Handle zero as a special case to protect clz - if (a == 0) - return fromRep(0); - - // All other cases begin by extracting the sign and absolute value of a - rep_t sign = 0; - su_int aAbs = (su_int)a; - if (a < 0) { - sign = signBit; - aAbs = -aAbs; - } - - // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - clzsi(aAbs); - rep_t result; - - // Shift a into the significand field and clear the implicit bit. Extra - // cast to unsigned int is necessary to get the correct behavior for - // the input INT_MIN. - const int shift = significandBits - exponent; - result = (rep_t)aAbs << shift ^ implicitBit; - - // Insert the exponent - result += (rep_t)(exponent + exponentBias) << significandBits; - // Insert the sign bit and return - return fromRep(result | sign); -} - diff --git a/lib/fp/floatsisf.c b/lib/fp/floatsisf.c @@ -1,59 +0,0 @@ -//===-- lib/floatsisf.c - integer -> single-precision conversion --*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements integer to single-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" - -#include "int_lib.h" - -COMPILER_RT_ABI fp_t __floatsisf(si_int a) { - - const int aWidth = sizeof a * CHAR_BIT; - - // Handle zero as a special case to protect clz - if (a == 0) - return fromRep(0); - - // All other cases begin by extracting the sign and absolute value of a - rep_t sign = 0; - su_int aAbs = (su_int)a; - if (a < 0) { - sign = signBit; - aAbs = -aAbs; - } - - // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - clzsi(aAbs); - rep_t result; - - // Shift a into the significand field, rounding if it is a right-shift - if (exponent <= significandBits) { - const int shift = significandBits - exponent; - result = (rep_t)aAbs << shift ^ implicitBit; - } else { - const int shift = exponent - significandBits; - result = (rep_t)aAbs >> shift ^ implicitBit; - rep_t round = (rep_t)aAbs << (typeWidth - shift); - if (round > signBit) - result++; - if (round == signBit) - result += result & 1; - } - - // Insert the exponent - result += (rep_t)(exponent + exponentBias) << significandBits; - // Insert the sign bit and return - return fromRep(result | sign); -} - diff --git a/lib/fp/floatundidf.c b/lib/fp/floatundidf.c @@ -1,35 +0,0 @@ -//===-- floatundidf.c - Implement __floatundidf ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __floatundidf for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -// Returns: convert a to a double, rounding toward even. - -// Assumption: double is a IEEE 64 bit floating point type -// du_int is a 64 bit integral type - -// seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm -// mmmm - -#include "int_lib.h" - -// Support for systems that don't have hardware floating-point; there are no -// flags to set, and we don't want to code-gen to an unknown soft-float -// implementation. - -#define SRC_U64 -#define DST_DOUBLE -#include "int_to_fp_impl.inc" - -COMPILER_RT_ABI double __floatundidf(du_int a) { return __floatXiYf__(a); } - - -#undef SRC_U64 -#undef DST_DOUBLE diff --git a/lib/fp/floatundisf.c b/lib/fp/floatundisf.c @@ -1,30 +0,0 @@ -//===-- floatundisf.c - Implement __floatundisf ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __floatundisf for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -// Returns: convert a to a float, rounding toward even. - -// Assumption: float is a IEEE 32 bit floating point type -// du_int is a 64 bit integral type - -// seee eeee emmm mmmm mmmm mmmm mmmm mmmm - -#include "int_lib.h" - -#define SRC_U64 -#define DST_SINGLE -#include "int_to_fp_impl.inc" - -COMPILER_RT_ABI float __floatundisf(du_int a) { return __floatXiYf__(a); } - - -#undef SRC_U64 -#undef DST_SINGLE diff --git a/lib/fp/floatunsidf.c b/lib/fp/floatunsidf.c @@ -1,40 +0,0 @@ -//===-- lib/floatunsidf.c - uint -> double-precision conversion ---*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements unsigned integer to double-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -#include "int_lib.h" - -COMPILER_RT_ABI fp_t __floatunsidf(su_int a) { - - const int aWidth = sizeof a * CHAR_BIT; - - // Handle zero as a special case to protect clz - if (a == 0) - return fromRep(0); - - // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - clzsi(a); - rep_t result; - - // Shift a into the significand field and clear the implicit bit. - const int shift = significandBits - exponent; - result = (rep_t)a << shift ^ implicitBit; - - // Insert the exponent - result += (rep_t)(exponent + exponentBias) << significandBits; - return fromRep(result); -} - diff --git a/lib/fp/floatunsisf.c b/lib/fp/floatunsisf.c @@ -1,50 +0,0 @@ -//===-- lib/floatunsisf.c - uint -> single-precision conversion ---*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements unsigned integer to single-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" - -#include "int_lib.h" - -COMPILER_RT_ABI fp_t __floatunsisf(su_int a) { - - const int aWidth = sizeof a * CHAR_BIT; - - // Handle zero as a special case to protect clz - if (a == 0) - return fromRep(0); - - // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - clzsi(a); - rep_t result; - - // Shift a into the significand field, rounding if it is a right-shift - if (exponent <= significandBits) { - const int shift = significandBits - exponent; - result = (rep_t)a << shift ^ implicitBit; - } else { - const int shift = exponent - significandBits; - result = (rep_t)a >> shift ^ implicitBit; - rep_t round = (rep_t)a << (typeWidth - shift); - if (round > signBit) - result++; - if (round == signBit) - result += result & 1; - } - - // Insert the exponent - result += (rep_t)(exponent + exponentBias) << significandBits; - return fromRep(result); -} - diff --git a/lib/fp/fp.c b/lib/fp/fp.c @@ -0,0 +1,512 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Consolidated soft-float runtime helpers for cfree's libcfree_rt.a. +// The build compiles only this one file; the per-op .c files are #included +// as snippets and not directly compiled. The fp_lib_undef.h reset header is +// included between sections that switch precision or (src,dst) pair. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// ============================================================ +// Section 1: SINGLE precision arith / compare / conv +// ============================================================ +// ---- addsf3.c ---- +#define SINGLE_PRECISION +#include "fp_add_impl.inc" + +COMPILER_RT_ABI float __addsf3(float a, float b) { return __addXf3__(a, b); } + +// ---- subsf3.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" + +// Subtraction; flip the sign bit of b and add. +COMPILER_RT_ABI fp_t __subsf3(fp_t a, fp_t b) { + return __addsf3(a, fromRep(toRep(b) ^ signBit)); +} + +// ---- mulsf3.c ---- +#define SINGLE_PRECISION +#include "fp_mul_impl.inc" + +COMPILER_RT_ABI fp_t __mulsf3(fp_t a, fp_t b) { return __mulXf3__(a, b); } + +// ---- divsf3.c ---- +#define SINGLE_PRECISION + +#define NUMBER_OF_HALF_ITERATIONS 0 +#define NUMBER_OF_FULL_ITERATIONS 3 +#define USE_NATIVE_FULL_ITERATIONS + +#include "fp_div_impl.inc" + +COMPILER_RT_ABI fp_t __divsf3(fp_t a, fp_t b) { return __divXf3__(a, b); } + + +#undef NUMBER_OF_HALF_ITERATIONS +#undef NUMBER_OF_FULL_ITERATIONS +#undef USE_NATIVE_FULL_ITERATIONS +// ---- negsf2.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" + +COMPILER_RT_ABI fp_t __negsf2(fp_t a) { return fromRep(toRep(a) ^ signBit); } + +// ---- comparesf2.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" + +#include "fp_compare_impl.inc" + +COMPILER_RT_ABI CMP_RESULT __lesf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __eqsf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __ltsf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __nesf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __gesf2(fp_t a, fp_t b) { return __geXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __gtsf2(fp_t a, fp_t b) { return __geXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __unordsf2(fp_t a, fp_t b){ return __unordXf2__(a, b); } + + +// ---- floatsisf.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" + +#include "int_lib.h" + +COMPILER_RT_ABI fp_t __floatsisf(si_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) + return fromRep(0); + + // All other cases begin by extracting the sign and absolute value of a + rep_t sign = 0; + su_int aAbs = (su_int)a; + if (a < 0) { + sign = signBit; + aAbs = -aAbs; + } + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - clzsi(aAbs); + rep_t result; + + // Shift a into the significand field, rounding if it is a right-shift + if (exponent <= significandBits) { + const int shift = significandBits - exponent; + result = (rep_t)aAbs << shift ^ implicitBit; + } else { + const int shift = exponent - significandBits; + result = (rep_t)aAbs >> shift ^ implicitBit; + rep_t round = (rep_t)aAbs << (typeWidth - shift); + if (round > signBit) + result++; + if (round == signBit) + result += result & 1; + } + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + // Insert the sign bit and return + return fromRep(result | sign); +} + +// ---- floatunsisf.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" + +#include "int_lib.h" + +COMPILER_RT_ABI fp_t __floatunsisf(su_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) + return fromRep(0); + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - clzsi(a); + rep_t result; + + // Shift a into the significand field, rounding if it is a right-shift + if (exponent <= significandBits) { + const int shift = significandBits - exponent; + result = (rep_t)a << shift ^ implicitBit; + } else { + const int shift = exponent - significandBits; + result = (rep_t)a >> shift ^ implicitBit; + rep_t round = (rep_t)a << (typeWidth - shift); + if (round > signBit) + result++; + if (round == signBit) + result += result & 1; + } + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + return fromRep(result); +} + +// ---- floatdisf.c ---- +#include "int_lib.h" + +#define SRC_I64 +#define DST_SINGLE +#include "int_to_fp_impl.inc" + +COMPILER_RT_ABI float __floatdisf(di_int a) { return __floatXiYf__(a); } + + +#undef SRC_I64 +#undef DST_SINGLE +// ---- floatundisf.c ---- +#include "int_lib.h" + +#define SRC_U64 +#define DST_SINGLE +#include "int_to_fp_impl.inc" + +COMPILER_RT_ABI float __floatundisf(du_int a) { return __floatXiYf__(a); } + + +#undef SRC_U64 +#undef DST_SINGLE +// ---- fixsfsi.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" +#define fixint_t si_int +#define fixuint_t su_int +#define FP_FIX_SUFFIX fixsfsi +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI si_int __fixsfsi(fp_t a) { return __fixint(a); } + + +#undef fixint_t +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixsfdi.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" + +// Support for systems that don't have hardware floating-point; there are no +// flags to set, and we don't want to code-gen to an unknown soft-float +// implementation. + +#define fixint_t di_int +#define fixuint_t du_int +#define FP_FIX_SUFFIX fixsfdi +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI di_int __fixsfdi(fp_t a) { return __fixint(a); } + + +#undef fixint_t +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixunssfsi.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" +#define fixuint_t su_int +#define FP_FIX_SUFFIX fixunssfsi +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI su_int __fixunssfsi(fp_t a) { return __fixuint(a); } + + +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixunssfdi.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" + +// Support for systems that don't have hardware floating-point; there are no +// flags to set, and we don't want to code-gen to an unknown soft-float +// implementation. + +#define fixuint_t du_int +#define FP_FIX_SUFFIX fixunssfdi +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI du_int __fixunssfdi(fp_t a) { return __fixuint(a); } + + +#undef fixuint_t +#undef FP_FIX_SUFFIX + +#include "fp_lib_undef.h" + +// ============================================================ +// Section 2: DOUBLE precision arith / compare / conv +// ============================================================ +// ---- adddf3.c ---- +#define DOUBLE_PRECISION +#include "fp_add_impl.inc" + +COMPILER_RT_ABI double __adddf3(double a, double b) { return __addXf3__(a, b); } + +// ---- subdf3.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" + +// Subtraction; flip the sign bit of b and add. +COMPILER_RT_ABI fp_t __subdf3(fp_t a, fp_t b) { + return __adddf3(a, fromRep(toRep(b) ^ signBit)); +} + +// ---- muldf3.c ---- +#define DOUBLE_PRECISION +#include "fp_mul_impl.inc" + +COMPILER_RT_ABI fp_t __muldf3(fp_t a, fp_t b) { return __mulXf3__(a, b); } + +// ---- divdf3.c ---- +#define DOUBLE_PRECISION + +#define NUMBER_OF_HALF_ITERATIONS 3 +#define NUMBER_OF_FULL_ITERATIONS 1 + +#include "fp_div_impl.inc" + +COMPILER_RT_ABI fp_t __divdf3(fp_t a, fp_t b) { return __divXf3__(a, b); } + + +#undef NUMBER_OF_HALF_ITERATIONS +#undef NUMBER_OF_FULL_ITERATIONS +// ---- negdf2.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" + +COMPILER_RT_ABI fp_t __negdf2(fp_t a) { return fromRep(toRep(a) ^ signBit); } + +// ---- comparedf2.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" + +#include "fp_compare_impl.inc" + +COMPILER_RT_ABI CMP_RESULT __ledf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __eqdf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __ltdf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __nedf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __gedf2(fp_t a, fp_t b) { return __geXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __gtdf2(fp_t a, fp_t b) { return __geXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __unorddf2(fp_t a, fp_t b) { return __unordXf2__(a, b); } + + +// ---- floatsidf.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" + +#include "int_lib.h" + +COMPILER_RT_ABI fp_t __floatsidf(si_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) + return fromRep(0); + + // All other cases begin by extracting the sign and absolute value of a + rep_t sign = 0; + su_int aAbs = (su_int)a; + if (a < 0) { + sign = signBit; + aAbs = -aAbs; + } + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - clzsi(aAbs); + rep_t result; + + // Shift a into the significand field and clear the implicit bit. Extra + // cast to unsigned int is necessary to get the correct behavior for + // the input INT_MIN. + const int shift = significandBits - exponent; + result = (rep_t)aAbs << shift ^ implicitBit; + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + // Insert the sign bit and return + return fromRep(result | sign); +} + +// ---- floatunsidf.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" + +#include "int_lib.h" + +COMPILER_RT_ABI fp_t __floatunsidf(su_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) + return fromRep(0); + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - clzsi(a); + rep_t result; + + // Shift a into the significand field and clear the implicit bit. + const int shift = significandBits - exponent; + result = (rep_t)a << shift ^ implicitBit; + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + return fromRep(result); +} + +// ---- floatdidf.c ---- +#include "int_lib.h" + +// Returns: convert a to a double, rounding toward even. + +// Assumption: double is a IEEE 64 bit floating point type +// di_int is a 64 bit integral type + +// seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm +// mmmm + +// Support for systems that don't have hardware floating-point; there are no +// flags to set, and we don't want to code-gen to an unknown soft-float +// implementation. + +#define SRC_I64 +#define DST_DOUBLE +#include "int_to_fp_impl.inc" + +COMPILER_RT_ABI double __floatdidf(di_int a) { return __floatXiYf__(a); } + + +#undef SRC_I64 +#undef DST_DOUBLE +// ---- floatundidf.c ---- +#include "int_lib.h" + +// Support for systems that don't have hardware floating-point; there are no +// flags to set, and we don't want to code-gen to an unknown soft-float +// implementation. + +#define SRC_U64 +#define DST_DOUBLE +#include "int_to_fp_impl.inc" + +COMPILER_RT_ABI double __floatundidf(du_int a) { return __floatXiYf__(a); } + + +#undef SRC_U64 +#undef DST_DOUBLE +// ---- fixdfsi.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" +#define fixint_t si_int +#define fixuint_t su_int +#define FP_FIX_SUFFIX fixdfsi +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI si_int __fixdfsi(fp_t a) { return __fixint(a); } + + +#undef fixint_t +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixdfdi.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" + +// Support for systems that don't have hardware floating-point; there are no +// flags to set, and we don't want to code-gen to an unknown soft-float +// implementation. + +#define fixint_t di_int +#define fixuint_t du_int +#define FP_FIX_SUFFIX fixdfdi +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI di_int __fixdfdi(fp_t a) { return __fixint(a); } + + +#undef fixint_t +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixunsdfsi.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" +#define fixuint_t su_int +#define FP_FIX_SUFFIX fixunsdfsi +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI su_int __fixunsdfsi(fp_t a) { return __fixuint(a); } + + +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixunsdfdi.c ---- +#define DOUBLE_PRECISION +#include "fp_lib.h" + +// Support for systems that don't have hardware floating-point; there are no +// flags to set, and we don't want to code-gen to an unknown soft-float +// implementation. + +#define fixuint_t du_int +#define FP_FIX_SUFFIX fixunsdfdi +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI du_int __fixunsdfdi(fp_t a) { return __fixuint(a); } + + +#undef fixuint_t +#undef FP_FIX_SUFFIX + +#include "fp_lib_undef.h" + +// ============================================================ +// Section 3: sf -> df extend +// ============================================================ +// ---- extendsfdf2.c ---- +#define SRC_SINGLE +#define DST_DOUBLE +#include "fp_extend_impl.inc" + +COMPILER_RT_ABI double __extendsfdf2(float a) { return __extendXfYf2__(a); } + + +#undef SRC_SINGLE +#undef DST_DOUBLE + +#include "fp_lib_undef.h" + +// ============================================================ +// Section 4: df -> sf truncate +// ============================================================ +// ---- truncdfsf2.c ---- +#define SRC_DOUBLE +#define DST_SINGLE +#include "fp_trunc_impl.inc" + +COMPILER_RT_ABI float __truncdfsf2(double a) { return __truncXfYf2__(a); } + + +#undef SRC_DOUBLE +#undef DST_SINGLE + +#include "fp_lib_undef.h" + +// ============================================================ +// Section 5: fp_mode (precision-independent) +// ============================================================ +// ---- fp_mode.c ---- +#include "fp_mode.h" + +// IEEE-754 default rounding (to nearest, ties to even). +CRT_FE_ROUND_MODE __fe_getround(void) { return CRT_FE_TONEAREST; } + +int __fe_raise_inexact(void) { + return 0; +} diff --git a/lib/fp/fp_mode.c b/lib/fp/fp_mode.c @@ -1,22 +0,0 @@ -//===----- lib/fp_mode.c - Floaing-point environment mode utilities --C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file provides a default implementation of fp_mode.h for architectures -// that does not support or does not have an implementation of floating point -// environment mode. -// -//===----------------------------------------------------------------------===// - -#include "fp_mode.h" - -// IEEE-754 default rounding (to nearest, ties to even). -CRT_FE_ROUND_MODE __fe_getround(void) { return CRT_FE_TONEAREST; } - -int __fe_raise_inexact(void) { - return 0; -} diff --git a/lib/fp/muldf3.c b/lib/fp/muldf3.c @@ -1,18 +0,0 @@ -//===-- lib/muldf3.c - Double-precision multiplication ------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements double-precision soft-float multiplication -// with the IEEE-754 default rounding (to nearest, ties to even). -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_mul_impl.inc" - -COMPILER_RT_ABI fp_t __muldf3(fp_t a, fp_t b) { return __mulXf3__(a, b); } - diff --git a/lib/fp/mulsf3.c b/lib/fp/mulsf3.c @@ -1,18 +0,0 @@ -//===-- lib/mulsf3.c - Single-precision multiplication ------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements single-precision soft-float multiplication -// with the IEEE-754 default rounding (to nearest, ties to even). -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_mul_impl.inc" - -COMPILER_RT_ABI fp_t __mulsf3(fp_t a, fp_t b) { return __mulXf3__(a, b); } - diff --git a/lib/fp/negdf2.c b/lib/fp/negdf2.c @@ -1,17 +0,0 @@ -//===-- lib/negdf2.c - double-precision negation ------------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements double-precision soft-float negation. -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -COMPILER_RT_ABI fp_t __negdf2(fp_t a) { return fromRep(toRep(a) ^ signBit); } - diff --git a/lib/fp/negsf2.c b/lib/fp/negsf2.c @@ -1,17 +0,0 @@ -//===-- lib/negsf2.c - single-precision negation ------------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements single-precision soft-float negation. -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" - -COMPILER_RT_ABI fp_t __negsf2(fp_t a) { return fromRep(toRep(a) ^ signBit); } - diff --git a/lib/fp/subdf3.c b/lib/fp/subdf3.c @@ -1,20 +0,0 @@ -//===-- lib/adddf3.c - Double-precision subtraction ---------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements double-precision soft-float subtraction. -// -//===----------------------------------------------------------------------===// - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -// Subtraction; flip the sign bit of b and add. -COMPILER_RT_ABI fp_t __subdf3(fp_t a, fp_t b) { - return __adddf3(a, fromRep(toRep(b) ^ signBit)); -} - diff --git a/lib/fp/subsf3.c b/lib/fp/subsf3.c @@ -1,20 +0,0 @@ -//===-- lib/subsf3.c - Single-precision subtraction ---------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements single-precision soft-float subtraction. -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" - -// Subtraction; flip the sign bit of b and add. -COMPILER_RT_ABI fp_t __subsf3(fp_t a, fp_t b) { - return __addsf3(a, fromRep(toRep(b) ^ signBit)); -} - diff --git a/lib/fp/truncdfsf2.c b/lib/fp/truncdfsf2.c @@ -1,17 +0,0 @@ -//===-- lib/truncdfsf2.c - double -> single conversion ------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define SRC_DOUBLE -#define DST_SINGLE -#include "fp_trunc_impl.inc" - -COMPILER_RT_ABI float __truncdfsf2(double a) { return __truncXfYf2__(a); } - - -#undef SRC_DOUBLE -#undef DST_SINGLE diff --git a/lib/fp_tf/addtf3.c b/lib/fp_tf/addtf3.c @@ -1,21 +0,0 @@ -//===-- lib/addtf3.c - Quad-precision addition --------------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements quad-precision soft-float addition. -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#include "fp_add_impl.inc" - -COMPILER_RT_ABI fp_t __addtf3(fp_t a, fp_t b) { - return __addXf3__(a, b); -} - diff --git a/lib/fp_tf/comparetf2.c b/lib/fp_tf/comparetf2.c @@ -1,51 +0,0 @@ -//===-- lib/comparetf2.c - Quad-precision comparisons -------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// // This file implements the following soft-float comparison routines: -// -// __eqtf2 __getf2 __unordtf2 -// __letf2 __gttf2 -// __lttf2 -// __netf2 -// -// The semantics of the routines grouped in each column are identical, so there -// is a single implementation for each, and wrappers to provide the other names. -// -// The main routines behave as follows: -// -// __letf2(a,b) returns -1 if a < b -// 0 if a == b -// 1 if a > b -// 1 if either a or b is NaN -// -// __getf2(a,b) returns -1 if a < b -// 0 if a == b -// 1 if a > b -// -1 if either a or b is NaN -// -// __unordtf2(a,b) returns 0 if both a and b are numbers -// 1 if either a or b is NaN -// -// Note that __letf2( ) and __getf2( ) are identical except in their handling of -// NaN values. -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#include "fp_compare_impl.inc" - -COMPILER_RT_ABI CMP_RESULT __letf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __eqtf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __lttf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __netf2(fp_t a, fp_t b) { return __leXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __getf2(fp_t a, fp_t b) { return __geXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __gttf2(fp_t a, fp_t b) { return __geXf2__(a, b); } -COMPILER_RT_ABI CMP_RESULT __unordtf2(fp_t a, fp_t b) { return __unordXf2__(a, b); } - diff --git a/lib/fp_tf/divtf3.c b/lib/fp_tf/divtf3.c @@ -1,27 +0,0 @@ -//===-- lib/divtf3.c - Quad-precision division --------------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements quad-precision soft-float division -// with the IEEE-754 default rounding (to nearest, ties to even). -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - - -#define NUMBER_OF_HALF_ITERATIONS 4 -#define NUMBER_OF_FULL_ITERATIONS 1 - -#include "fp_div_impl.inc" - -COMPILER_RT_ABI fp_t __divtf3(fp_t a, fp_t b) { return __divXf3__(a, b); } - - -#undef NUMBER_OF_HALF_ITERATIONS -#undef NUMBER_OF_FULL_ITERATIONS diff --git a/lib/fp_tf/extenddftf2.c b/lib/fp_tf/extenddftf2.c @@ -1,20 +0,0 @@ -//===-- lib/extenddftf2.c - double -> quad conversion -------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define SRC_DOUBLE -#define DST_QUAD -#include "fp_extend_impl.inc" - -COMPILER_RT_ABI dst_t __extenddftf2(src_t a) { return __extendXfYf2__(a); } - - -#undef SRC_DOUBLE -#undef DST_QUAD diff --git a/lib/fp_tf/extendsftf2.c b/lib/fp_tf/extendsftf2.c @@ -1,20 +0,0 @@ -//===-- lib/extendsftf2.c - single -> quad conversion -------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define SRC_SINGLE -#define DST_QUAD -#include "fp_extend_impl.inc" - -COMPILER_RT_ABI dst_t __extendsftf2(src_t a) { return __extendXfYf2__(a); } - - -#undef SRC_SINGLE -#undef DST_QUAD diff --git a/lib/fp_tf/fixtfdi.c b/lib/fp_tf/fixtfdi.c @@ -1,21 +0,0 @@ -//===-- fixtfdi.c - Implement __fixtfdi -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define fixint_t di_int -#define fixuint_t du_int -#define FP_FIX_SUFFIX fixtfdi -#include "fp_fixint_impl.inc" - -COMPILER_RT_ABI di_int __fixtfdi(fp_t a) { return __fixint(a); } - -#undef fixint_t -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_tf/fixtfsi.c b/lib/fp_tf/fixtfsi.c @@ -1,21 +0,0 @@ -//===-- fixtfsi.c - Implement __fixtfsi -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define fixint_t si_int -#define fixuint_t su_int -#define FP_FIX_SUFFIX fixtfsi -#include "fp_fixint_impl.inc" - -COMPILER_RT_ABI si_int __fixtfsi(fp_t a) { return __fixint(a); } - -#undef fixint_t -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_tf/fixtfti.c b/lib/fp_tf/fixtfti.c @@ -1,21 +0,0 @@ -//===-- fixtfti.c - Implement __fixtfti -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define fixint_t ti_int -#define fixuint_t tu_int -#define FP_FIX_SUFFIX fixtfti -#include "fp_fixint_impl.inc" - -COMPILER_RT_ABI ti_int __fixtfti(fp_t a) { return __fixint(a); } - -#undef fixint_t -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_tf/fixunstfdi.c b/lib/fp_tf/fixunstfdi.c @@ -1,19 +0,0 @@ -//===-- fixunstfdi.c - Implement __fixunstfdi -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define fixuint_t du_int -#define FP_FIX_SUFFIX fixunstfdi -#include "fp_fixuint_impl.inc" - -COMPILER_RT_ABI du_int __fixunstfdi(fp_t a) { return __fixuint(a); } - -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_tf/fixunstfsi.c b/lib/fp_tf/fixunstfsi.c @@ -1,19 +0,0 @@ -//===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define fixuint_t su_int -#define FP_FIX_SUFFIX fixunstfsi -#include "fp_fixuint_impl.inc" - -COMPILER_RT_ABI su_int __fixunstfsi(fp_t a) { return __fixuint(a); } - -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_tf/fixunstfti.c b/lib/fp_tf/fixunstfti.c @@ -1,19 +0,0 @@ -//===-- fixunstfsi.c - Implement __fixunstfsi -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define fixuint_t tu_int -#define FP_FIX_SUFFIX fixunstfti -#include "fp_fixuint_impl.inc" - -COMPILER_RT_ABI tu_int __fixunstfti(fp_t a) { return __fixuint(a); } - -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_tf/floatditf.c b/lib/fp_tf/floatditf.c @@ -1,47 +0,0 @@ -//===-- lib/floatditf.c - integer -> quad-precision conversion ----*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements di_int to quad-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -COMPILER_RT_ABI fp_t __floatditf(di_int a) { - - const int aWidth = sizeof a * CHAR_BIT; - - // Handle zero as a special case to protect clz - if (a == 0) - return fromRep(0); - - // All other cases begin by extracting the sign and absolute value of a - rep_t sign = 0; - du_int aAbs = (du_int)a; - if (a < 0) { - sign = signBit; - aAbs = ~(du_int)a + 1U; - } - - // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clzll(aAbs); - rep_t result; - - // Shift a into the significand field, rounding if it is a right-shift - const int shift = significandBits - exponent; - result = (rep_t)aAbs << shift ^ implicitBit; - - // Insert the exponent - result += (rep_t)(exponent + exponentBias) << significandBits; - // Insert the sign bit and return - return fromRep(result | sign); -} - diff --git a/lib/fp_tf/floatsitf.c b/lib/fp_tf/floatsitf.c @@ -1,47 +0,0 @@ -//===-- lib/floatsitf.c - integer -> quad-precision conversion ----*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements integer to quad-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -COMPILER_RT_ABI fp_t __floatsitf(si_int a) { - - const int aWidth = sizeof a * CHAR_BIT; - - // Handle zero as a special case to protect clz - if (a == 0) - return fromRep(0); - - // All other cases begin by extracting the sign and absolute value of a - rep_t sign = 0; - su_int aAbs = (su_int)a; - if (a < 0) { - sign = signBit; - aAbs = -aAbs; - } - - // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - clzsi(aAbs); - rep_t result; - - // Shift a into the significand field and clear the implicit bit. - const int shift = significandBits - exponent; - result = (rep_t)aAbs << shift ^ implicitBit; - - // Insert the exponent - result += (rep_t)(exponent + exponentBias) << significandBits; - // Insert the sign bit and return - return fromRep(result | sign); -} - diff --git a/lib/fp_tf/floattitf.c b/lib/fp_tf/floattitf.c @@ -1,36 +0,0 @@ -//===-- lib/floattitf.c - int128 -> quad-precision conversion -----*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements ti_int to quad-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" -#include "int_lib.h" - -#define SRC_I128 -#define DST_QUAD -#include "int_to_fp_impl.inc" - -// Returns: convert a ti_int to a fp_t, rounding toward even. - -// Assumption: fp_t is a IEEE 128 bit floating point type -// ti_int is a 128 bit integral type - -// seee eeee eeee eeee mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm -// mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm -// mmmm mmmm mmmm - -COMPILER_RT_ABI fp_t __floattitf(ti_int a) { return __floatXiYf__(a); } - - -#undef SRC_I128 -#undef DST_QUAD diff --git a/lib/fp_tf/floatunditf.c b/lib/fp_tf/floatunditf.c @@ -1,38 +0,0 @@ -//===-- lib/floatunditf.c - uint -> quad-precision conversion -----*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements du_int to quad-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -COMPILER_RT_ABI fp_t __floatunditf(du_int a) { - - const int aWidth = sizeof a * CHAR_BIT; - - // Handle zero as a special case to protect clz - if (a == 0) - return fromRep(0); - - // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - __builtin_clzll(a); - rep_t result; - - // Shift a into the significand field and clear the implicit bit. - const int shift = significandBits - exponent; - result = (rep_t)a << shift ^ implicitBit; - - // Insert the exponent - result += (rep_t)(exponent + exponentBias) << significandBits; - return fromRep(result); -} - diff --git a/lib/fp_tf/floatunsitf.c b/lib/fp_tf/floatunsitf.c @@ -1,38 +0,0 @@ -//===-- lib/floatunsitf.c - uint -> quad-precision conversion -----*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements unsigned integer to quad-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -COMPILER_RT_ABI fp_t __floatunsitf(su_int a) { - - const int aWidth = sizeof a * CHAR_BIT; - - // Handle zero as a special case to protect clz - if (a == 0) - return fromRep(0); - - // Exponent of (fp_t)a is the width of abs(a). - const int exponent = (aWidth - 1) - clzsi(a); - rep_t result; - - // Shift a into the significand field and clear the implicit bit. - const int shift = significandBits - exponent; - result = (rep_t)a << shift ^ implicitBit; - - // Insert the exponent - result += (rep_t)(exponent + exponentBias) << significandBits; - return fromRep(result); -} - diff --git a/lib/fp_tf/floatuntitf.c b/lib/fp_tf/floatuntitf.c @@ -1,36 +0,0 @@ -//===-- lib/floatuntitf.c - uint128 -> quad-precision conversion --*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements tu_int to quad-precision conversion for the -// compiler-rt library in the IEEE-754 default round-to-nearest, ties-to-even -// mode. -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" -#include "int_lib.h" - -#define SRC_U128 -#define DST_QUAD -#include "int_to_fp_impl.inc" - -// Returns: convert a tu_int to a fp_t, rounding toward even. - -// Assumption: fp_t is a IEEE 128 bit floating point type -// tu_int is a 128 bit integral type - -// seee eeee eeee eeee mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm -// mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm -// mmmm mmmm mmmm - -COMPILER_RT_ABI fp_t __floatuntitf(tu_int a) { return __floatXiYf__(a); } - - -#undef SRC_U128 -#undef DST_QUAD diff --git a/lib/fp_tf/fp_tf.c b/lib/fp_tf/fp_tf.c @@ -0,0 +1,387 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Consolidated soft-float runtime helpers for cfree's libcfree_rt.a. +// The build compiles only this one file; the per-op .c files are #included +// as snippets and not directly compiled. The fp_lib_undef.h reset header is +// included between sections that switch precision or (src,dst) pair. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// ============================================================ +// Section 1: QUAD precision arith / compare / conv / fix +// ============================================================ +// ---- addtf3.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#include "fp_add_impl.inc" + +COMPILER_RT_ABI fp_t __addtf3(fp_t a, fp_t b) { + return __addXf3__(a, b); +} + +// ---- subtf3.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +COMPILER_RT_ABI fp_t __addtf3(fp_t a, fp_t b); + +// Subtraction; flip the sign bit of b and add. +COMPILER_RT_ABI fp_t __subtf3(fp_t a, fp_t b) { + return __addtf3(a, fromRep(toRep(b) ^ signBit)); +} + +// ---- multf3.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#include "fp_mul_impl.inc" + +COMPILER_RT_ABI fp_t __multf3(fp_t a, fp_t b) { return __mulXf3__(a, b); } + +// ---- divtf3.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + + +#define NUMBER_OF_HALF_ITERATIONS 4 +#define NUMBER_OF_FULL_ITERATIONS 1 + +#include "fp_div_impl.inc" + +COMPILER_RT_ABI fp_t __divtf3(fp_t a, fp_t b) { return __divXf3__(a, b); } + + +#undef NUMBER_OF_HALF_ITERATIONS +#undef NUMBER_OF_FULL_ITERATIONS +// ---- comparetf2.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#include "fp_compare_impl.inc" + +COMPILER_RT_ABI CMP_RESULT __letf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __eqtf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __lttf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __netf2(fp_t a, fp_t b) { return __leXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __getf2(fp_t a, fp_t b) { return __geXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __gttf2(fp_t a, fp_t b) { return __geXf2__(a, b); } +COMPILER_RT_ABI CMP_RESULT __unordtf2(fp_t a, fp_t b) { return __unordXf2__(a, b); } + +// ---- floatsitf.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +COMPILER_RT_ABI fp_t __floatsitf(si_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) + return fromRep(0); + + // All other cases begin by extracting the sign and absolute value of a + rep_t sign = 0; + su_int aAbs = (su_int)a; + if (a < 0) { + sign = signBit; + aAbs = -aAbs; + } + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - clzsi(aAbs); + rep_t result; + + // Shift a into the significand field and clear the implicit bit. + const int shift = significandBits - exponent; + result = (rep_t)aAbs << shift ^ implicitBit; + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + // Insert the sign bit and return + return fromRep(result | sign); +} + +// ---- floatunsitf.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +COMPILER_RT_ABI fp_t __floatunsitf(su_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) + return fromRep(0); + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - clzsi(a); + rep_t result; + + // Shift a into the significand field and clear the implicit bit. + const int shift = significandBits - exponent; + result = (rep_t)a << shift ^ implicitBit; + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + return fromRep(result); +} + +// ---- floatditf.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +COMPILER_RT_ABI fp_t __floatditf(di_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) + return fromRep(0); + + // All other cases begin by extracting the sign and absolute value of a + rep_t sign = 0; + du_int aAbs = (du_int)a; + if (a < 0) { + sign = signBit; + aAbs = ~(du_int)a + 1U; + } + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - __builtin_clzll(aAbs); + rep_t result; + + // Shift a into the significand field, rounding if it is a right-shift + const int shift = significandBits - exponent; + result = (rep_t)aAbs << shift ^ implicitBit; + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + // Insert the sign bit and return + return fromRep(result | sign); +} + +// ---- floatunditf.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +COMPILER_RT_ABI fp_t __floatunditf(du_int a) { + + const int aWidth = sizeof a * CHAR_BIT; + + // Handle zero as a special case to protect clz + if (a == 0) + return fromRep(0); + + // Exponent of (fp_t)a is the width of abs(a). + const int exponent = (aWidth - 1) - __builtin_clzll(a); + rep_t result; + + // Shift a into the significand field and clear the implicit bit. + const int shift = significandBits - exponent; + result = (rep_t)a << shift ^ implicitBit; + + // Insert the exponent + result += (rep_t)(exponent + exponentBias) << significandBits; + return fromRep(result); +} + +// ---- floattitf.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" +#include "int_lib.h" + +#define SRC_I128 +#define DST_QUAD +#include "int_to_fp_impl.inc" + +// Returns: convert a ti_int to a fp_t, rounding toward even. + +// Assumption: fp_t is a IEEE 128 bit floating point type +// ti_int is a 128 bit integral type + +// seee eeee eeee eeee mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm +// mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm +// mmmm mmmm mmmm + +COMPILER_RT_ABI fp_t __floattitf(ti_int a) { return __floatXiYf__(a); } + + +#undef SRC_I128 +#undef DST_QUAD +// ---- floatuntitf.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" +#include "int_lib.h" + +#define SRC_U128 +#define DST_QUAD +#include "int_to_fp_impl.inc" + +// Returns: convert a tu_int to a fp_t, rounding toward even. + +// Assumption: fp_t is a IEEE 128 bit floating point type +// tu_int is a 128 bit integral type + +// seee eeee eeee eeee mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm +// mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm +// mmmm mmmm mmmm + +COMPILER_RT_ABI fp_t __floatuntitf(tu_int a) { return __floatXiYf__(a); } + + +#undef SRC_U128 +#undef DST_QUAD +// ---- fixtfsi.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define fixint_t si_int +#define fixuint_t su_int +#define FP_FIX_SUFFIX fixtfsi +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI si_int __fixtfsi(fp_t a) { return __fixint(a); } + +#undef fixint_t +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixtfdi.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define fixint_t di_int +#define fixuint_t du_int +#define FP_FIX_SUFFIX fixtfdi +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI di_int __fixtfdi(fp_t a) { return __fixint(a); } + +#undef fixint_t +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixtfti.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define fixint_t ti_int +#define fixuint_t tu_int +#define FP_FIX_SUFFIX fixtfti +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI ti_int __fixtfti(fp_t a) { return __fixint(a); } + +#undef fixint_t +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixunstfsi.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define fixuint_t su_int +#define FP_FIX_SUFFIX fixunstfsi +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI su_int __fixunstfsi(fp_t a) { return __fixuint(a); } + +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixunstfdi.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define fixuint_t du_int +#define FP_FIX_SUFFIX fixunstfdi +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI du_int __fixunstfdi(fp_t a) { return __fixuint(a); } + +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixunstfti.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define fixuint_t tu_int +#define FP_FIX_SUFFIX fixunstfti +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI tu_int __fixunstfti(fp_t a) { return __fixuint(a); } + +#undef fixuint_t +#undef FP_FIX_SUFFIX + +#include "fp_lib_undef.h" + +// ============================================================ +// Section 2: sf -> tf extend +// ============================================================ +// ---- extendsftf2.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define SRC_SINGLE +#define DST_QUAD +#include "fp_extend_impl.inc" + +COMPILER_RT_ABI dst_t __extendsftf2(src_t a) { return __extendXfYf2__(a); } + + +#undef SRC_SINGLE +#undef DST_QUAD + +#include "fp_lib_undef.h" + +// ============================================================ +// Section 3: df -> tf extend +// ============================================================ +// ---- extenddftf2.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define SRC_DOUBLE +#define DST_QUAD +#include "fp_extend_impl.inc" + +COMPILER_RT_ABI dst_t __extenddftf2(src_t a) { return __extendXfYf2__(a); } + + +#undef SRC_DOUBLE +#undef DST_QUAD + +#include "fp_lib_undef.h" + +// ============================================================ +// Section 4: tf -> sf truncate +// ============================================================ +// ---- trunctfsf2.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define SRC_QUAD +#define DST_SINGLE +#include "fp_trunc_impl.inc" + +COMPILER_RT_ABI dst_t __trunctfsf2(src_t a) { return __truncXfYf2__(a); } + + +#undef SRC_QUAD +#undef DST_SINGLE + +#include "fp_lib_undef.h" + +// ============================================================ +// Section 5: tf -> df truncate +// ============================================================ +// ---- trunctfdf2.c ---- +#define QUAD_PRECISION +#include "fp_lib.h" + +#define SRC_QUAD +#define DST_DOUBLE +#include "fp_trunc_impl.inc" + +COMPILER_RT_ABI dst_t __trunctfdf2(src_t a) { return __truncXfYf2__(a); } + + +#undef SRC_QUAD +#undef DST_DOUBLE diff --git a/lib/fp_tf/multf3.c b/lib/fp_tf/multf3.c @@ -1,20 +0,0 @@ -//===-- lib/multf3.c - Quad-precision multiplication --------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements quad-precision soft-float multiplication -// with the IEEE-754 default rounding (to nearest, ties to even). -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#include "fp_mul_impl.inc" - -COMPILER_RT_ABI fp_t __multf3(fp_t a, fp_t b) { return __mulXf3__(a, b); } - diff --git a/lib/fp_tf/subtf3.c b/lib/fp_tf/subtf3.c @@ -1,22 +0,0 @@ -//===-- lib/subtf3.c - Quad-precision subtraction -----------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements quad-precision soft-float subtraction. -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -COMPILER_RT_ABI fp_t __addtf3(fp_t a, fp_t b); - -// Subtraction; flip the sign bit of b and add. -COMPILER_RT_ABI fp_t __subtf3(fp_t a, fp_t b) { - return __addtf3(a, fromRep(toRep(b) ^ signBit)); -} - diff --git a/lib/fp_tf/trunctfdf2.c b/lib/fp_tf/trunctfdf2.c @@ -1,20 +0,0 @@ -//===-- lib/truncdfsf2.c - quad -> double conversion --------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define SRC_QUAD -#define DST_DOUBLE -#include "fp_trunc_impl.inc" - -COMPILER_RT_ABI dst_t __trunctfdf2(src_t a) { return __truncXfYf2__(a); } - - -#undef SRC_QUAD -#undef DST_DOUBLE diff --git a/lib/fp_tf/trunctfsf2.c b/lib/fp_tf/trunctfsf2.c @@ -1,20 +0,0 @@ -//===-- lib/trunctfsf2.c - quad -> single conversion --------------*- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#define QUAD_PRECISION -#include "fp_lib.h" - -#define SRC_QUAD -#define DST_SINGLE -#include "fp_trunc_impl.inc" - -COMPILER_RT_ABI dst_t __trunctfsf2(src_t a) { return __truncXfYf2__(a); } - - -#undef SRC_QUAD -#undef DST_SINGLE diff --git a/lib/fp_ti/fixdfti.c b/lib/fp_ti/fixdfti.c @@ -1,24 +0,0 @@ -//===-- fixdfti.c - Implement __fixdfti -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -#define DOUBLE_PRECISION -#include "fp_lib.h" - -#define fixint_t ti_int -#define fixuint_t tu_int -#define FP_FIX_SUFFIX fixdfti -#include "fp_fixint_impl.inc" - -COMPILER_RT_ABI ti_int __fixdfti(fp_t a) { return __fixint(a); } - - -#undef fixint_t -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_ti/fixsfti.c b/lib/fp_ti/fixsfti.c @@ -1,24 +0,0 @@ -//===-- fixsfti.c - Implement __fixsfti -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -#define SINGLE_PRECISION -#include "fp_lib.h" - -#define fixint_t ti_int -#define fixuint_t tu_int -#define FP_FIX_SUFFIX fixsfti -#include "fp_fixint_impl.inc" - -COMPILER_RT_ABI ti_int __fixsfti(fp_t a) { return __fixint(a); } - - -#undef fixint_t -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_ti/fixunsdfti.c b/lib/fp_ti/fixunsdfti.c @@ -1,20 +0,0 @@ -//===-- fixunsdfti.c - Implement __fixunsdfti -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -#define DOUBLE_PRECISION -#include "fp_lib.h" -#define fixuint_t tu_int -#define FP_FIX_SUFFIX fixunsdfti -#include "fp_fixuint_impl.inc" - -COMPILER_RT_ABI tu_int __fixunsdfti(fp_t a) { return __fixuint(a); } - -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_ti/fixunssfti.c b/lib/fp_ti/fixunssfti.c @@ -1,23 +0,0 @@ -//===-- fixunssfti.c - Implement __fixunssfti -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __fixunssfti for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#define SINGLE_PRECISION -#include "fp_lib.h" - -#define fixuint_t tu_int -#define FP_FIX_SUFFIX fixunssfti -#include "fp_fixuint_impl.inc" - -COMPILER_RT_ABI tu_int __fixunssfti(fp_t a) { return __fixuint(a); } - -#undef fixuint_t -#undef FP_FIX_SUFFIX diff --git a/lib/fp_ti/floattidf.c b/lib/fp_ti/floattidf.c @@ -1,32 +0,0 @@ -//===-- floattidf.c - Implement __floattidf -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __floattidf for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -#define SRC_I128 -#define DST_DOUBLE -#include "int_to_fp_impl.inc" - -// Returns: convert a to a double, rounding toward even. - -// Assumption: double is a IEEE 64 bit floating point type -// ti_int is a 128 bit integral type - -// seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm -// mmmm - -COMPILER_RT_ABI double __floattidf(ti_int a) { return __floatXiYf__(a); } - - -#undef SRC_I128 -#undef DST_DOUBLE diff --git a/lib/fp_ti/floattisf.c b/lib/fp_ti/floattisf.c @@ -1,31 +0,0 @@ -//===-- floattisf.c - Implement __floattisf -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __floattisf for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -#define SRC_I128 -#define DST_SINGLE -#include "int_to_fp_impl.inc" - -// Returns: convert a to a float, rounding toward even. - -// Assumption: float is a IEEE 32 bit floating point type -// ti_int is a 128 bit integral type - -// seee eeee emmm mmmm mmmm mmmm mmmm mmmm - -COMPILER_RT_ABI float __floattisf(ti_int a) { return __floatXiYf__(a); } - - -#undef SRC_I128 -#undef DST_SINGLE diff --git a/lib/fp_ti/floatuntidf.c b/lib/fp_ti/floatuntidf.c @@ -1,32 +0,0 @@ -//===-- floatuntidf.c - Implement __floatuntidf ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __floatuntidf for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -#define SRC_U128 -#define DST_DOUBLE -#include "int_to_fp_impl.inc" - -// Returns: convert a to a double, rounding toward even. - -// Assumption: double is a IEEE 64 bit floating point type -// tu_int is a 128 bit integral type - -// seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm -// mmmm - -COMPILER_RT_ABI double __floatuntidf(tu_int a) { return __floatXiYf__(a); } - - -#undef SRC_U128 -#undef DST_DOUBLE diff --git a/lib/fp_ti/floatuntisf.c b/lib/fp_ti/floatuntisf.c @@ -1,31 +0,0 @@ -//===-- floatuntisf.c - Implement __floatuntisf ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __floatuntisf for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -#define SRC_U128 -#define DST_SINGLE -#include "int_to_fp_impl.inc" - -// Returns: convert a to a float, rounding toward even. - -// Assumption: float is a IEEE 32 bit floating point type -// tu_int is a 128 bit integral type - -// seee eeee emmm mmmm mmmm mmmm mmmm mmmm - -COMPILER_RT_ABI float __floatuntisf(tu_int a) { return __floatXiYf__(a); } - - -#undef SRC_U128 -#undef DST_SINGLE diff --git a/lib/fp_ti/fp_ti.c b/lib/fp_ti/fp_ti.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Consolidated soft-float runtime helpers for cfree's libcfree_rt.a. +// The build compiles only this one file; the per-op .c files are #included +// as snippets and not directly compiled. The fp_lib_undef.h reset header is +// included between sections that switch precision or (src,dst) pair. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// ============================================================ +// Section 1: SINGLE precision — i128/u128 -> sf, and sf -> ti/tu fix +// ============================================================ +// ---- floattisf.c ---- +#include "int_lib.h" + + +#define SRC_I128 +#define DST_SINGLE +#include "int_to_fp_impl.inc" + +// Returns: convert a to a float, rounding toward even. + +// Assumption: float is a IEEE 32 bit floating point type +// ti_int is a 128 bit integral type + +// seee eeee emmm mmmm mmmm mmmm mmmm mmmm + +COMPILER_RT_ABI float __floattisf(ti_int a) { return __floatXiYf__(a); } + + +#undef SRC_I128 +#undef DST_SINGLE +// ---- floatuntisf.c ---- +#include "int_lib.h" + + +#define SRC_U128 +#define DST_SINGLE +#include "int_to_fp_impl.inc" + +// Returns: convert a to a float, rounding toward even. + +// Assumption: float is a IEEE 32 bit floating point type +// tu_int is a 128 bit integral type + +// seee eeee emmm mmmm mmmm mmmm mmmm mmmm + +COMPILER_RT_ABI float __floatuntisf(tu_int a) { return __floatXiYf__(a); } + + +#undef SRC_U128 +#undef DST_SINGLE +// ---- fixsfti.c ---- +#include "int_lib.h" + +#define SINGLE_PRECISION +#include "fp_lib.h" + +#define fixint_t ti_int +#define fixuint_t tu_int +#define FP_FIX_SUFFIX fixsfti +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI ti_int __fixsfti(fp_t a) { return __fixint(a); } + + +#undef fixint_t +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixunssfti.c ---- +#define SINGLE_PRECISION +#include "fp_lib.h" + +#define fixuint_t tu_int +#define FP_FIX_SUFFIX fixunssfti +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI tu_int __fixunssfti(fp_t a) { return __fixuint(a); } + +#undef fixuint_t +#undef FP_FIX_SUFFIX + +#include "fp_lib_undef.h" + +// ============================================================ +// Section 2: DOUBLE precision — i128/u128 -> df, and df -> ti/tu fix +// ============================================================ +// ---- floattidf.c ---- +#include "int_lib.h" + + +#define SRC_I128 +#define DST_DOUBLE +#include "int_to_fp_impl.inc" + +// Returns: convert a to a double, rounding toward even. + +// Assumption: double is a IEEE 64 bit floating point type +// ti_int is a 128 bit integral type + +// seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm +// mmmm + +COMPILER_RT_ABI double __floattidf(ti_int a) { return __floatXiYf__(a); } + + +#undef SRC_I128 +#undef DST_DOUBLE +// ---- floatuntidf.c ---- +#include "int_lib.h" + + +#define SRC_U128 +#define DST_DOUBLE +#include "int_to_fp_impl.inc" + +// Returns: convert a to a double, rounding toward even. + +// Assumption: double is a IEEE 64 bit floating point type +// tu_int is a 128 bit integral type + +// seee eeee eeee mmmm mmmm mmmm mmmm mmmm | mmmm mmmm mmmm mmmm mmmm mmmm mmmm +// mmmm + +COMPILER_RT_ABI double __floatuntidf(tu_int a) { return __floatXiYf__(a); } + + +#undef SRC_U128 +#undef DST_DOUBLE +// ---- fixdfti.c ---- +#include "int_lib.h" + +#define DOUBLE_PRECISION +#include "fp_lib.h" + +#define fixint_t ti_int +#define fixuint_t tu_int +#define FP_FIX_SUFFIX fixdfti +#include "fp_fixint_impl.inc" + +COMPILER_RT_ABI ti_int __fixdfti(fp_t a) { return __fixint(a); } + + +#undef fixint_t +#undef fixuint_t +#undef FP_FIX_SUFFIX +// ---- fixunsdfti.c ---- +#include "int_lib.h" + +#define DOUBLE_PRECISION +#include "fp_lib.h" +#define fixuint_t tu_int +#define FP_FIX_SUFFIX fixunsdfti +#include "fp_fixuint_impl.inc" + +COMPILER_RT_ABI tu_int __fixunsdfti(fp_t a) { return __fixuint(a); } + +#undef fixuint_t +#undef FP_FIX_SUFFIX diff --git a/lib/impl/fp_extend.h b/lib/impl/fp_extend.h @@ -1,277 +0,0 @@ -//===-lib/fp_extend.h - low precision -> high precision conversion -*- C -*-=// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Source/destination type setup for the extending FP conversions. Caller -// defines SRC_<X> (SINGLE/DOUBLE/80/HALF) and DST_<Y> (SINGLE/DOUBLE/QUAD) -// before each inclusion. -// -// Re-includable. Names that depend on the (src, dst) pair are emitted with -// a `_<src><dst>` suffix exactly once per (TU, pair); bare-name #define -// aliases are set on every inclusion so the body in `fp_extend_impl.inc` -// (and the caller) uses bare names that resolve to the right suffixed -// entity. Use the umbrella `fp_lib_undef.h` between sections in one TU to -// clear the bare-name aliases. -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Self-clean any prior inclusion's per-(src, dst) state. May coexist with -// fp_trunc.h / int_to_fp.h which define overlapping bare-name aliases. -#undef _FP_EXT_SRC_SUF -#undef _FP_EXT_DST_SUF -#undef SRC_REP_C -#undef DST_REP_C -#undef src_t -#undef src_rep_t -#undef dst_t -#undef dst_rep_t -#undef srcBits -#undef srcSigFracBits -#undef srcExpBits -#undef dstBits -#undef dstSigFracBits -#undef dstExpBits -#undef src_rep_t_clz -#undef src_rep_t_clz_impl -#undef srcToRep -#undef dstFromRep -#undef extract_sign_from_src -#undef extract_exp_from_src -#undef extract_sig_frac_from_src -#undef clz_in_sig_frac -#undef construct_dst_rep - -#if defined SRC_SINGLE -#define _FP_EXT_SRC_SUF sf -#elif defined SRC_DOUBLE -#define _FP_EXT_SRC_SUF df -#elif defined SRC_80 -#define _FP_EXT_SRC_SUF xf -#elif defined SRC_HALF -#define _FP_EXT_SRC_SUF hf -#else -#error Source should be half, single, or double precision! -#endif - -#if defined DST_SINGLE -#define _FP_EXT_DST_SUF sf -#elif defined DST_DOUBLE -#define _FP_EXT_DST_SUF df -#elif defined DST_QUAD -#define _FP_EXT_DST_SUF tf -#else -#error Destination should be single, double, or quad precision! -#endif - -#define _FP_EXT_PASTE4_(a, b, c, d) a##b##c##d -#define _FP_EXT_PASTE4(a, b, c, d) _FP_EXT_PASTE4_(a, b, c, d) -#define _FP_EXT_PAIR(stem) _FP_EXT_PASTE4(stem, _, _FP_EXT_SRC_SUF, _FP_EXT_DST_SUF) - -// ---- Bare-name aliases (re-set every inclusion). ------------------------ - -#define src_t _FP_EXT_PAIR(src_t) -#define src_rep_t _FP_EXT_PAIR(src_rep_t) -#define dst_t _FP_EXT_PAIR(dst_t) -#define dst_rep_t _FP_EXT_PAIR(dst_rep_t) -#define srcBits _FP_EXT_PAIR(srcBits) -#define srcSigFracBits _FP_EXT_PAIR(srcSigFracBits) -#define srcExpBits _FP_EXT_PAIR(srcExpBits) -#define dstBits _FP_EXT_PAIR(dstBits) -#define dstSigFracBits _FP_EXT_PAIR(dstSigFracBits) -#define dstExpBits _FP_EXT_PAIR(dstExpBits) -#define src_rep_t_clz_impl _FP_EXT_PAIR(src_rep_t_clz_impl) -#define srcToRep _FP_EXT_PAIR(srcToRep) -#define dstFromRep _FP_EXT_PAIR(dstFromRep) -#define extract_sign_from_src _FP_EXT_PAIR(extract_sign_from_src) -#define extract_exp_from_src _FP_EXT_PAIR(extract_exp_from_src) -#define extract_sig_frac_from_src _FP_EXT_PAIR(extract_sig_frac_from_src) -#define clz_in_sig_frac _FP_EXT_PAIR(clz_in_sig_frac) -#define construct_dst_rep _FP_EXT_PAIR(construct_dst_rep) - -// SRC_REP_C / DST_REP_C: textual macros (UINT32_C etc.); same body each -// inclusion within a precision. - -#if defined SRC_SINGLE -#define SRC_REP_C UINT32_C -#elif defined SRC_DOUBLE -#define SRC_REP_C UINT64_C -#elif defined SRC_80 -#define SRC_REP_C (__uint128_t) -#elif defined SRC_HALF -#define SRC_REP_C UINT16_C -#endif - -#if defined DST_SINGLE -#define DST_REP_C UINT32_C -#elif defined DST_DOUBLE -#define DST_REP_C UINT64_C -#elif defined DST_QUAD -#define DST_REP_C (__uint128_t) -#endif - -// ---- One-time emission per (TU, src+dst pair). -------------------------- -// Enumerate the pairs cfree actually uses (sf→df, sf→tf, df→tf). - -#if defined SRC_SINGLE && defined DST_DOUBLE && !defined FP_EXT_SFDF_EMITTED -#define FP_EXT_SFDF_EMITTED -#define _FP_EXT_EMIT 1 -#elif defined SRC_SINGLE && defined DST_QUAD && !defined FP_EXT_SFTF_EMITTED -#define FP_EXT_SFTF_EMITTED -#define _FP_EXT_EMIT 1 -#elif defined SRC_DOUBLE && defined DST_QUAD && !defined FP_EXT_DFTF_EMITTED -#define FP_EXT_DFTF_EMITTED -#define _FP_EXT_EMIT 1 -#endif - -#ifdef _FP_EXT_EMIT -#undef _FP_EXT_EMIT - -#if defined SRC_SINGLE -typedef float src_t; -typedef uint32_t src_rep_t; -static const int srcBits = sizeof(src_t) * CHAR_BIT; -static const int srcSigFracBits = 23; -// -1 accounts for the sign bit. -// srcBits - srcSigFracBits - 1 -static const int srcExpBits = 8; -#define src_rep_t_clz clzsi - -#elif defined SRC_DOUBLE -typedef double src_t; -typedef uint64_t src_rep_t; -static const int srcBits = sizeof(src_t) * CHAR_BIT; -static const int srcSigFracBits = 52; -// -1 accounts for the sign bit. -// srcBits - srcSigFracBits - 1 -static const int srcExpBits = 11; - -static inline int src_rep_t_clz_impl(src_rep_t a) { -#if defined __LP64__ - return __builtin_clzl(a); -#else - if (a & REP_C(0xffffffff00000000)) - return clzsi(a >> 32); - else - return 32 + clzsi(a & REP_C(0xffffffff)); -#endif -} -#define src_rep_t_clz src_rep_t_clz_impl - -#elif defined SRC_80 -typedef xf_float src_t; -typedef __uint128_t src_rep_t; -// sign bit, exponent and significand occupy the lower 80 bits. -static const int srcBits = 80; -static const int srcSigFracBits = 63; -// -1 accounts for the sign bit. -// -1 accounts for the explicitly stored integer bit. -// srcBits - srcSigFracBits - 1 - 1 -static const int srcExpBits = 15; - -#elif defined SRC_HALF -#ifdef COMPILER_RT_HAS_FLOAT16 -typedef _Float16 src_t; -#else -typedef uint16_t src_t; -#endif -typedef uint16_t src_rep_t; -static const int srcBits = sizeof(src_t) * CHAR_BIT; -static const int srcSigFracBits = 10; -// -1 accounts for the sign bit. -// srcBits - srcSigFracBits - 1 -static const int srcExpBits = 5; - -static inline int src_rep_t_clz_impl(src_rep_t a) { - return __builtin_clz(a) - 16; -} -#define src_rep_t_clz src_rep_t_clz_impl - -#endif // end source precision - -#if defined DST_SINGLE -typedef float dst_t; -typedef uint32_t dst_rep_t; -static const int dstBits = sizeof(dst_t) * CHAR_BIT; -static const int dstSigFracBits = 23; -// -1 accounts for the sign bit. -// dstBits - dstSigFracBits - 1 -static const int dstExpBits = 8; - -#elif defined DST_DOUBLE -typedef double dst_t; -typedef uint64_t dst_rep_t; -static const int dstBits = sizeof(dst_t) * CHAR_BIT; -static const int dstSigFracBits = 52; -// -1 accounts for the sign bit. -// dstBits - dstSigFracBits - 1 -static const int dstExpBits = 11; - -#elif defined DST_QUAD -typedef tf_float dst_t; -typedef __uint128_t dst_rep_t; -static const int dstBits = sizeof(dst_t) * CHAR_BIT; -static const int dstSigFracBits = 112; -// -1 accounts for the sign bit. -// dstBits - dstSigFracBits - 1 -static const int dstExpBits = 15; - -#endif // end destination precision - -// End of specialization parameters. - -// TODO: These helper routines should be placed into fp_lib.h -// Currently they depend on macros/constants defined above. - -static inline src_rep_t extract_sign_from_src(src_rep_t x) { - const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1); - return (x & srcSignMask) >> (srcBits - 1); -} - -static inline src_rep_t extract_exp_from_src(src_rep_t x) { - const int srcSigBits = srcBits - 1 - srcExpBits; - const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits; - return (x & srcExpMask) >> srcSigBits; -} - -static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) { - const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1; - return x & srcSigFracMask; -} - -#ifdef src_rep_t_clz -static inline int clz_in_sig_frac(src_rep_t sigFrac) { - const int skip = 1 + srcExpBits; - return src_rep_t_clz(sigFrac) - skip; -} -#endif - -static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) { - return (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac; -} - -// Two helper routines for conversion to and from the representation of -// floating-point data as integer values follow. - -static inline src_rep_t srcToRep(src_t x) { - const union { - src_t f; - src_rep_t i; - } rep = {.f = x}; - return rep.i; -} - -static inline dst_t dstFromRep(dst_rep_t x) { - const union { - dst_t f; - dst_rep_t i; - } rep = {.i = x}; - return rep.f; -} -// End helper routines. Conversion implementation follows. - -#endif // _FP_EXT_EMIT diff --git a/lib/impl/fp_extend_impl.inc b/lib/impl/fp_extend_impl.inc @@ -35,7 +35,264 @@ // //===----------------------------------------------------------------------===// -#include "fp_extend.h" +// ---- fp_extend.h (was a separate header; merged) ---- +#include "int_lib.h" + +// Self-clean any prior inclusion's per-(src, dst) state. May coexist with +// fp_trunc.h / int_to_fp.h which define overlapping bare-name aliases. +#undef _FP_EXT_SRC_SUF +#undef _FP_EXT_DST_SUF +#undef SRC_REP_C +#undef DST_REP_C +#undef src_t +#undef src_rep_t +#undef dst_t +#undef dst_rep_t +#undef srcBits +#undef srcSigFracBits +#undef srcExpBits +#undef dstBits +#undef dstSigFracBits +#undef dstExpBits +#undef src_rep_t_clz +#undef src_rep_t_clz_impl +#undef srcToRep +#undef dstFromRep +#undef extract_sign_from_src +#undef extract_exp_from_src +#undef extract_sig_frac_from_src +#undef clz_in_sig_frac +#undef construct_dst_rep + +#if defined SRC_SINGLE +#define _FP_EXT_SRC_SUF sf +#elif defined SRC_DOUBLE +#define _FP_EXT_SRC_SUF df +#elif defined SRC_80 +#define _FP_EXT_SRC_SUF xf +#elif defined SRC_HALF +#define _FP_EXT_SRC_SUF hf +#else +#error Source should be half, single, or double precision! +#endif + +#if defined DST_SINGLE +#define _FP_EXT_DST_SUF sf +#elif defined DST_DOUBLE +#define _FP_EXT_DST_SUF df +#elif defined DST_QUAD +#define _FP_EXT_DST_SUF tf +#else +#error Destination should be single, double, or quad precision! +#endif + +#define _FP_EXT_PASTE4_(a, b, c, d) a##b##c##d +#define _FP_EXT_PASTE4(a, b, c, d) _FP_EXT_PASTE4_(a, b, c, d) +#define _FP_EXT_PAIR(stem) _FP_EXT_PASTE4(stem, _, _FP_EXT_SRC_SUF, _FP_EXT_DST_SUF) + +// ---- Bare-name aliases (re-set every inclusion). ------------------------ + +#define src_t _FP_EXT_PAIR(src_t) +#define src_rep_t _FP_EXT_PAIR(src_rep_t) +#define dst_t _FP_EXT_PAIR(dst_t) +#define dst_rep_t _FP_EXT_PAIR(dst_rep_t) +#define srcBits _FP_EXT_PAIR(srcBits) +#define srcSigFracBits _FP_EXT_PAIR(srcSigFracBits) +#define srcExpBits _FP_EXT_PAIR(srcExpBits) +#define dstBits _FP_EXT_PAIR(dstBits) +#define dstSigFracBits _FP_EXT_PAIR(dstSigFracBits) +#define dstExpBits _FP_EXT_PAIR(dstExpBits) +#define src_rep_t_clz_impl _FP_EXT_PAIR(src_rep_t_clz_impl) +#define srcToRep _FP_EXT_PAIR(srcToRep) +#define dstFromRep _FP_EXT_PAIR(dstFromRep) +#define extract_sign_from_src _FP_EXT_PAIR(extract_sign_from_src) +#define extract_exp_from_src _FP_EXT_PAIR(extract_exp_from_src) +#define extract_sig_frac_from_src _FP_EXT_PAIR(extract_sig_frac_from_src) +#define clz_in_sig_frac _FP_EXT_PAIR(clz_in_sig_frac) +#define construct_dst_rep _FP_EXT_PAIR(construct_dst_rep) + +// SRC_REP_C / DST_REP_C: textual macros (UINT32_C etc.); same body each +// inclusion within a precision. + +#if defined SRC_SINGLE +#define SRC_REP_C UINT32_C +#elif defined SRC_DOUBLE +#define SRC_REP_C UINT64_C +#elif defined SRC_80 +#define SRC_REP_C (__uint128_t) +#elif defined SRC_HALF +#define SRC_REP_C UINT16_C +#endif + +#if defined DST_SINGLE +#define DST_REP_C UINT32_C +#elif defined DST_DOUBLE +#define DST_REP_C UINT64_C +#elif defined DST_QUAD +#define DST_REP_C (__uint128_t) +#endif + +// ---- One-time emission per (TU, src+dst pair). -------------------------- +// Enumerate the pairs cfree actually uses (sf→df, sf→tf, df→tf). + +#if defined SRC_SINGLE && defined DST_DOUBLE && !defined FP_EXT_SFDF_EMITTED +#define FP_EXT_SFDF_EMITTED +#define _FP_EXT_EMIT 1 +#elif defined SRC_SINGLE && defined DST_QUAD && !defined FP_EXT_SFTF_EMITTED +#define FP_EXT_SFTF_EMITTED +#define _FP_EXT_EMIT 1 +#elif defined SRC_DOUBLE && defined DST_QUAD && !defined FP_EXT_DFTF_EMITTED +#define FP_EXT_DFTF_EMITTED +#define _FP_EXT_EMIT 1 +#endif + +#ifdef _FP_EXT_EMIT +#undef _FP_EXT_EMIT + +#if defined SRC_SINGLE +typedef float src_t; +typedef uint32_t src_rep_t; +static const int srcBits = sizeof(src_t) * CHAR_BIT; +static const int srcSigFracBits = 23; +// -1 accounts for the sign bit. +// srcBits - srcSigFracBits - 1 +static const int srcExpBits = 8; +#define src_rep_t_clz clzsi + +#elif defined SRC_DOUBLE +typedef double src_t; +typedef uint64_t src_rep_t; +static const int srcBits = sizeof(src_t) * CHAR_BIT; +static const int srcSigFracBits = 52; +// -1 accounts for the sign bit. +// srcBits - srcSigFracBits - 1 +static const int srcExpBits = 11; + +static inline int src_rep_t_clz_impl(src_rep_t a) { +#if defined __LP64__ + return __builtin_clzl(a); +#else + if (a & REP_C(0xffffffff00000000)) + return clzsi(a >> 32); + else + return 32 + clzsi(a & REP_C(0xffffffff)); +#endif +} +#define src_rep_t_clz src_rep_t_clz_impl + +#elif defined SRC_80 +typedef xf_float src_t; +typedef __uint128_t src_rep_t; +// sign bit, exponent and significand occupy the lower 80 bits. +static const int srcBits = 80; +static const int srcSigFracBits = 63; +// -1 accounts for the sign bit. +// -1 accounts for the explicitly stored integer bit. +// srcBits - srcSigFracBits - 1 - 1 +static const int srcExpBits = 15; + +#elif defined SRC_HALF +#ifdef COMPILER_RT_HAS_FLOAT16 +typedef _Float16 src_t; +#else +typedef uint16_t src_t; +#endif +typedef uint16_t src_rep_t; +static const int srcBits = sizeof(src_t) * CHAR_BIT; +static const int srcSigFracBits = 10; +// -1 accounts for the sign bit. +// srcBits - srcSigFracBits - 1 +static const int srcExpBits = 5; + +static inline int src_rep_t_clz_impl(src_rep_t a) { + return __builtin_clz(a) - 16; +} +#define src_rep_t_clz src_rep_t_clz_impl + +#endif // end source precision + +#if defined DST_SINGLE +typedef float dst_t; +typedef uint32_t dst_rep_t; +static const int dstBits = sizeof(dst_t) * CHAR_BIT; +static const int dstSigFracBits = 23; +// -1 accounts for the sign bit. +// dstBits - dstSigFracBits - 1 +static const int dstExpBits = 8; + +#elif defined DST_DOUBLE +typedef double dst_t; +typedef uint64_t dst_rep_t; +static const int dstBits = sizeof(dst_t) * CHAR_BIT; +static const int dstSigFracBits = 52; +// -1 accounts for the sign bit. +// dstBits - dstSigFracBits - 1 +static const int dstExpBits = 11; + +#elif defined DST_QUAD +typedef tf_float dst_t; +typedef __uint128_t dst_rep_t; +static const int dstBits = sizeof(dst_t) * CHAR_BIT; +static const int dstSigFracBits = 112; +// -1 accounts for the sign bit. +// dstBits - dstSigFracBits - 1 +static const int dstExpBits = 15; + +#endif // end destination precision + +// End of specialization parameters. + +// TODO: These helper routines should be placed into fp_lib.h +// Currently they depend on macros/constants defined above. + +static inline src_rep_t extract_sign_from_src(src_rep_t x) { + const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1); + return (x & srcSignMask) >> (srcBits - 1); +} + +static inline src_rep_t extract_exp_from_src(src_rep_t x) { + const int srcSigBits = srcBits - 1 - srcExpBits; + const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits; + return (x & srcExpMask) >> srcSigBits; +} + +static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) { + const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1; + return x & srcSigFracMask; +} + +#ifdef src_rep_t_clz +static inline int clz_in_sig_frac(src_rep_t sigFrac) { + const int skip = 1 + srcExpBits; + return src_rep_t_clz(sigFrac) - skip; +} +#endif + +static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) { + return (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac; +} + +// Two helper routines for conversion to and from the representation of +// floating-point data as integer values follow. + +static inline src_rep_t srcToRep(src_t x) { + const union { + src_t f; + src_rep_t i; + } rep = {.f = x}; + return rep.i; +} + +static inline dst_t dstFromRep(dst_rep_t x) { + const union { + dst_t f; + dst_rep_t i; + } rep = {.i = x}; + return rep.f; +} +// End helper routines. Conversion implementation follows. + +#endif // _FP_EXT_EMIT #define __extendXfYf2__ _FP_EXT_PAIR(__extendXfYf2__) diff --git a/lib/impl/fp_trunc.h b/lib/impl/fp_trunc.h @@ -1,259 +0,0 @@ -//=== lib/fp_trunc.h - high precision -> low precision conversion *- C -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Source/destination precision setup for the truncating FP conversions. -// Caller defines SRC_<X> (SINGLE/DOUBLE/QUAD) and DST_<Y> -// (SINGLE/DOUBLE/80/HALF/BFLOAT) before each inclusion. -// -// Re-includable. Names that depend on the (src, dst) pair are emitted with -// a `_<src><dst>` suffix exactly once per (TU, pair); bare-name #define -// aliases are set every inclusion. Use the umbrella `fp_lib_undef.h` to -// clear the bare-name aliases between sections in one TU. -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Self-clean any prior inclusion's per-(src, dst) state. May coexist with -// fp_extend.h / int_to_fp.h which define overlapping bare-name aliases. -#undef _FP_TRUNC_SRC_SUF -#undef _FP_TRUNC_DST_SUF -#undef SRC_REP_C -#undef DST_REP_C -#undef src_t -#undef src_rep_t -#undef dst_t -#undef dst_rep_t -#undef srcBits -#undef srcSigFracBits -#undef srcExpBits -#undef dstBits -#undef dstSigFracBits -#undef dstExpBits -#undef srcToRep -#undef dstFromRep -#undef extract_sign_from_src -#undef extract_exp_from_src -#undef extract_sig_frac_from_src -#undef construct_dst_rep - -#if defined SRC_SINGLE -#define _FP_TRUNC_SRC_SUF sf -#elif defined SRC_DOUBLE -#define _FP_TRUNC_SRC_SUF df -#elif defined SRC_QUAD -#define _FP_TRUNC_SRC_SUF tf -#else -#error Source should be double precision or quad precision! -#endif - -#if defined DST_SINGLE -#define _FP_TRUNC_DST_SUF sf -#elif defined DST_DOUBLE -#define _FP_TRUNC_DST_SUF df -#elif defined DST_80 -#define _FP_TRUNC_DST_SUF xf -#elif defined DST_HALF -#define _FP_TRUNC_DST_SUF hf -#elif defined DST_BFLOAT -#define _FP_TRUNC_DST_SUF bf -#else -#error Destination should be single precision or double precision! -#endif - -#define _FP_TRUNC_PASTE4_(a, b, c, d) a##b##c##d -#define _FP_TRUNC_PASTE4(a, b, c, d) _FP_TRUNC_PASTE4_(a, b, c, d) -#define _FP_TRUNC_PAIR(stem) _FP_TRUNC_PASTE4(stem, _, _FP_TRUNC_SRC_SUF, _FP_TRUNC_DST_SUF) - -// ---- Bare-name aliases (re-set every inclusion). ------------------------ -// fp_extend.h uses identical bare names; the aliases here suffix-rename -// to fp_trunc-specific symbols (different pair tokens), so the two -// headers can coexist in one TU without colliding. - -#define src_t _FP_TRUNC_PAIR(src_t) -#define src_rep_t _FP_TRUNC_PAIR(src_rep_t) -#define dst_t _FP_TRUNC_PAIR(dst_t) -#define dst_rep_t _FP_TRUNC_PAIR(dst_rep_t) -#define srcBits _FP_TRUNC_PAIR(srcBits) -#define srcSigFracBits _FP_TRUNC_PAIR(srcSigFracBits) -#define srcExpBits _FP_TRUNC_PAIR(srcExpBits) -#define dstBits _FP_TRUNC_PAIR(dstBits) -#define dstSigFracBits _FP_TRUNC_PAIR(dstSigFracBits) -#define dstExpBits _FP_TRUNC_PAIR(dstExpBits) -#define srcToRep _FP_TRUNC_PAIR(srcToRep) -#define dstFromRep _FP_TRUNC_PAIR(dstFromRep) -#define extract_sign_from_src _FP_TRUNC_PAIR(extract_sign_from_src) -#define extract_exp_from_src _FP_TRUNC_PAIR(extract_exp_from_src) -#define extract_sig_frac_from_src _FP_TRUNC_PAIR(extract_sig_frac_from_src) -#define construct_dst_rep _FP_TRUNC_PAIR(construct_dst_rep) - -#if defined SRC_SINGLE -#define SRC_REP_C UINT32_C -#elif defined SRC_DOUBLE -#define SRC_REP_C UINT64_C -#elif defined SRC_QUAD -#define SRC_REP_C (__uint128_t) -#endif - -#if defined DST_SINGLE -#define DST_REP_C UINT32_C -#elif defined DST_DOUBLE -#define DST_REP_C UINT64_C -#elif defined DST_80 -#define DST_REP_C (__uint128_t) -#elif defined DST_HALF -#define DST_REP_C UINT16_C -#elif defined DST_BFLOAT -#define DST_REP_C UINT16_C -#endif - -// ---- One-time emission per (TU, src+dst pair). -------------------------- -// Pairs cfree uses: df→sf, tf→df, tf→sf. - -#if defined SRC_DOUBLE && defined DST_SINGLE && !defined FP_TRUNC_DFSF_EMITTED -#define FP_TRUNC_DFSF_EMITTED -#define _FP_TRUNC_EMIT 1 -#elif defined SRC_QUAD && defined DST_DOUBLE && !defined FP_TRUNC_TFDF_EMITTED -#define FP_TRUNC_TFDF_EMITTED -#define _FP_TRUNC_EMIT 1 -#elif defined SRC_QUAD && defined DST_SINGLE && !defined FP_TRUNC_TFSF_EMITTED -#define FP_TRUNC_TFSF_EMITTED -#define _FP_TRUNC_EMIT 1 -#endif - -#ifdef _FP_TRUNC_EMIT -#undef _FP_TRUNC_EMIT - -#if defined SRC_SINGLE -typedef float src_t; -typedef uint32_t src_rep_t; -static const int srcBits = sizeof(src_t) * CHAR_BIT; -static const int srcSigFracBits = 23; -// -1 accounts for the sign bit. -// srcBits - srcSigFracBits - 1 -static const int srcExpBits = 8; - -#elif defined SRC_DOUBLE -typedef double src_t; -typedef uint64_t src_rep_t; -static const int srcBits = sizeof(src_t) * CHAR_BIT; -static const int srcSigFracBits = 52; -// -1 accounts for the sign bit. -// srcBits - srcSigFracBits - 1 -static const int srcExpBits = 11; - -#elif defined SRC_QUAD -typedef tf_float src_t; -typedef __uint128_t src_rep_t; -static const int srcBits = sizeof(src_t) * CHAR_BIT; -static const int srcSigFracBits = 112; -// -1 accounts for the sign bit. -// srcBits - srcSigFracBits - 1 -static const int srcExpBits = 15; - -#endif // end source precision - -#if defined DST_DOUBLE -typedef double dst_t; -typedef uint64_t dst_rep_t; -static const int dstBits = sizeof(dst_t) * CHAR_BIT; -static const int dstSigFracBits = 52; -// -1 accounts for the sign bit. -// dstBits - dstSigFracBits - 1 -static const int dstExpBits = 11; - -#elif defined DST_80 -typedef xf_float dst_t; -typedef __uint128_t dst_rep_t; -static const int dstBits = 80; -static const int dstSigFracBits = 63; -// -1 accounts for the sign bit. -// -1 accounts for the explicitly stored integer bit. -// dstBits - dstSigFracBits - 1 - 1 -static const int dstExpBits = 15; - -#elif defined DST_SINGLE -typedef float dst_t; -typedef uint32_t dst_rep_t; -static const int dstBits = sizeof(dst_t) * CHAR_BIT; -static const int dstSigFracBits = 23; -// -1 accounts for the sign bit. -// dstBits - dstSigFracBits - 1 -static const int dstExpBits = 8; - -#elif defined DST_HALF -#ifdef COMPILER_RT_HAS_FLOAT16 -typedef _Float16 dst_t; -#else -typedef uint16_t dst_t; -#endif -typedef uint16_t dst_rep_t; -static const int dstBits = sizeof(dst_t) * CHAR_BIT; -static const int dstSigFracBits = 10; -// -1 accounts for the sign bit. -// dstBits - dstSigFracBits - 1 -static const int dstExpBits = 5; - -#elif defined DST_BFLOAT -typedef __bf16 dst_t; -typedef uint16_t dst_rep_t; -static const int dstBits = sizeof(dst_t) * CHAR_BIT; -static const int dstSigFracBits = 7; -// -1 accounts for the sign bit. -// dstBits - dstSigFracBits - 1 -static const int dstExpBits = 8; - -#endif // end destination precision - -// TODO: These helper routines should be placed into fp_lib.h -// Currently they depend on macros/constants defined above. - -static inline src_rep_t extract_sign_from_src(src_rep_t x) { - const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1); - return (x & srcSignMask) >> (srcBits - 1); -} - -static inline src_rep_t extract_exp_from_src(src_rep_t x) { - const int srcSigBits = srcBits - 1 - srcExpBits; - const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits; - return (x & srcExpMask) >> srcSigBits; -} - -static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) { - const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1; - return x & srcSigFracMask; -} - -static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) { - dst_rep_t result = (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac; - // Set the explicit integer bit in F80 if present. - if (dstBits == 80 && exp) { - result |= (DST_REP_C(1) << dstSigFracBits); - } - return result; -} - -// End of specialization parameters. Two helper routines for conversion to and -// from the representation of floating-point data as integer values follow. - -static inline src_rep_t srcToRep(src_t x) { - const union { - src_t f; - src_rep_t i; - } rep = {.f = x}; - return rep.i; -} - -static inline dst_t dstFromRep(dst_rep_t x) { - const union { - dst_t f; - dst_rep_t i; - } rep = {.i = x}; - return rep.f; -} - -#endif // _FP_TRUNC_EMIT diff --git a/lib/impl/fp_trunc_impl.inc b/lib/impl/fp_trunc_impl.inc @@ -36,7 +36,248 @@ // //===----------------------------------------------------------------------===// -#include "fp_trunc.h" +// ---- fp_trunc.h (was a separate header; merged) ---- +#include "int_lib.h" + +// Self-clean any prior inclusion's per-(src, dst) state. May coexist with +// fp_extend.h / int_to_fp.h which define overlapping bare-name aliases. +#undef _FP_TRUNC_SRC_SUF +#undef _FP_TRUNC_DST_SUF +#undef SRC_REP_C +#undef DST_REP_C +#undef src_t +#undef src_rep_t +#undef dst_t +#undef dst_rep_t +#undef srcBits +#undef srcSigFracBits +#undef srcExpBits +#undef dstBits +#undef dstSigFracBits +#undef dstExpBits +#undef srcToRep +#undef dstFromRep +#undef extract_sign_from_src +#undef extract_exp_from_src +#undef extract_sig_frac_from_src +#undef construct_dst_rep + +#if defined SRC_SINGLE +#define _FP_TRUNC_SRC_SUF sf +#elif defined SRC_DOUBLE +#define _FP_TRUNC_SRC_SUF df +#elif defined SRC_QUAD +#define _FP_TRUNC_SRC_SUF tf +#else +#error Source should be double precision or quad precision! +#endif + +#if defined DST_SINGLE +#define _FP_TRUNC_DST_SUF sf +#elif defined DST_DOUBLE +#define _FP_TRUNC_DST_SUF df +#elif defined DST_80 +#define _FP_TRUNC_DST_SUF xf +#elif defined DST_HALF +#define _FP_TRUNC_DST_SUF hf +#elif defined DST_BFLOAT +#define _FP_TRUNC_DST_SUF bf +#else +#error Destination should be single precision or double precision! +#endif + +#define _FP_TRUNC_PASTE4_(a, b, c, d) a##b##c##d +#define _FP_TRUNC_PASTE4(a, b, c, d) _FP_TRUNC_PASTE4_(a, b, c, d) +#define _FP_TRUNC_PAIR(stem) _FP_TRUNC_PASTE4(stem, _, _FP_TRUNC_SRC_SUF, _FP_TRUNC_DST_SUF) + +// ---- Bare-name aliases (re-set every inclusion). ------------------------ +// fp_extend.h uses identical bare names; the aliases here suffix-rename +// to fp_trunc-specific symbols (different pair tokens), so the two +// headers can coexist in one TU without colliding. + +#define src_t _FP_TRUNC_PAIR(src_t) +#define src_rep_t _FP_TRUNC_PAIR(src_rep_t) +#define dst_t _FP_TRUNC_PAIR(dst_t) +#define dst_rep_t _FP_TRUNC_PAIR(dst_rep_t) +#define srcBits _FP_TRUNC_PAIR(srcBits) +#define srcSigFracBits _FP_TRUNC_PAIR(srcSigFracBits) +#define srcExpBits _FP_TRUNC_PAIR(srcExpBits) +#define dstBits _FP_TRUNC_PAIR(dstBits) +#define dstSigFracBits _FP_TRUNC_PAIR(dstSigFracBits) +#define dstExpBits _FP_TRUNC_PAIR(dstExpBits) +#define srcToRep _FP_TRUNC_PAIR(srcToRep) +#define dstFromRep _FP_TRUNC_PAIR(dstFromRep) +#define extract_sign_from_src _FP_TRUNC_PAIR(extract_sign_from_src) +#define extract_exp_from_src _FP_TRUNC_PAIR(extract_exp_from_src) +#define extract_sig_frac_from_src _FP_TRUNC_PAIR(extract_sig_frac_from_src) +#define construct_dst_rep _FP_TRUNC_PAIR(construct_dst_rep) + +#if defined SRC_SINGLE +#define SRC_REP_C UINT32_C +#elif defined SRC_DOUBLE +#define SRC_REP_C UINT64_C +#elif defined SRC_QUAD +#define SRC_REP_C (__uint128_t) +#endif + +#if defined DST_SINGLE +#define DST_REP_C UINT32_C +#elif defined DST_DOUBLE +#define DST_REP_C UINT64_C +#elif defined DST_80 +#define DST_REP_C (__uint128_t) +#elif defined DST_HALF +#define DST_REP_C UINT16_C +#elif defined DST_BFLOAT +#define DST_REP_C UINT16_C +#endif + +// ---- One-time emission per (TU, src+dst pair). -------------------------- +// Pairs cfree uses: df→sf, tf→df, tf→sf. + +#if defined SRC_DOUBLE && defined DST_SINGLE && !defined FP_TRUNC_DFSF_EMITTED +#define FP_TRUNC_DFSF_EMITTED +#define _FP_TRUNC_EMIT 1 +#elif defined SRC_QUAD && defined DST_DOUBLE && !defined FP_TRUNC_TFDF_EMITTED +#define FP_TRUNC_TFDF_EMITTED +#define _FP_TRUNC_EMIT 1 +#elif defined SRC_QUAD && defined DST_SINGLE && !defined FP_TRUNC_TFSF_EMITTED +#define FP_TRUNC_TFSF_EMITTED +#define _FP_TRUNC_EMIT 1 +#endif + +#ifdef _FP_TRUNC_EMIT +#undef _FP_TRUNC_EMIT + +#if defined SRC_SINGLE +typedef float src_t; +typedef uint32_t src_rep_t; +static const int srcBits = sizeof(src_t) * CHAR_BIT; +static const int srcSigFracBits = 23; +// -1 accounts for the sign bit. +// srcBits - srcSigFracBits - 1 +static const int srcExpBits = 8; + +#elif defined SRC_DOUBLE +typedef double src_t; +typedef uint64_t src_rep_t; +static const int srcBits = sizeof(src_t) * CHAR_BIT; +static const int srcSigFracBits = 52; +// -1 accounts for the sign bit. +// srcBits - srcSigFracBits - 1 +static const int srcExpBits = 11; + +#elif defined SRC_QUAD +typedef tf_float src_t; +typedef __uint128_t src_rep_t; +static const int srcBits = sizeof(src_t) * CHAR_BIT; +static const int srcSigFracBits = 112; +// -1 accounts for the sign bit. +// srcBits - srcSigFracBits - 1 +static const int srcExpBits = 15; + +#endif // end source precision + +#if defined DST_DOUBLE +typedef double dst_t; +typedef uint64_t dst_rep_t; +static const int dstBits = sizeof(dst_t) * CHAR_BIT; +static const int dstSigFracBits = 52; +// -1 accounts for the sign bit. +// dstBits - dstSigFracBits - 1 +static const int dstExpBits = 11; + +#elif defined DST_80 +typedef xf_float dst_t; +typedef __uint128_t dst_rep_t; +static const int dstBits = 80; +static const int dstSigFracBits = 63; +// -1 accounts for the sign bit. +// -1 accounts for the explicitly stored integer bit. +// dstBits - dstSigFracBits - 1 - 1 +static const int dstExpBits = 15; + +#elif defined DST_SINGLE +typedef float dst_t; +typedef uint32_t dst_rep_t; +static const int dstBits = sizeof(dst_t) * CHAR_BIT; +static const int dstSigFracBits = 23; +// -1 accounts for the sign bit. +// dstBits - dstSigFracBits - 1 +static const int dstExpBits = 8; + +#elif defined DST_HALF +#ifdef COMPILER_RT_HAS_FLOAT16 +typedef _Float16 dst_t; +#else +typedef uint16_t dst_t; +#endif +typedef uint16_t dst_rep_t; +static const int dstBits = sizeof(dst_t) * CHAR_BIT; +static const int dstSigFracBits = 10; +// -1 accounts for the sign bit. +// dstBits - dstSigFracBits - 1 +static const int dstExpBits = 5; + +#elif defined DST_BFLOAT +typedef __bf16 dst_t; +typedef uint16_t dst_rep_t; +static const int dstBits = sizeof(dst_t) * CHAR_BIT; +static const int dstSigFracBits = 7; +// -1 accounts for the sign bit. +// dstBits - dstSigFracBits - 1 +static const int dstExpBits = 8; + +#endif // end destination precision + +// TODO: These helper routines should be placed into fp_lib.h +// Currently they depend on macros/constants defined above. + +static inline src_rep_t extract_sign_from_src(src_rep_t x) { + const src_rep_t srcSignMask = SRC_REP_C(1) << (srcBits - 1); + return (x & srcSignMask) >> (srcBits - 1); +} + +static inline src_rep_t extract_exp_from_src(src_rep_t x) { + const int srcSigBits = srcBits - 1 - srcExpBits; + const src_rep_t srcExpMask = ((SRC_REP_C(1) << srcExpBits) - 1) << srcSigBits; + return (x & srcExpMask) >> srcSigBits; +} + +static inline src_rep_t extract_sig_frac_from_src(src_rep_t x) { + const src_rep_t srcSigFracMask = (SRC_REP_C(1) << srcSigFracBits) - 1; + return x & srcSigFracMask; +} + +static inline dst_rep_t construct_dst_rep(dst_rep_t sign, dst_rep_t exp, dst_rep_t sigFrac) { + dst_rep_t result = (sign << (dstBits - 1)) | (exp << (dstBits - 1 - dstExpBits)) | sigFrac; + // Set the explicit integer bit in F80 if present. + if (dstBits == 80 && exp) { + result |= (DST_REP_C(1) << dstSigFracBits); + } + return result; +} + +// End of specialization parameters. Two helper routines for conversion to and +// from the representation of floating-point data as integer values follow. + +static inline src_rep_t srcToRep(src_t x) { + const union { + src_t f; + src_rep_t i; + } rep = {.f = x}; + return rep.i; +} + +static inline dst_t dstFromRep(dst_rep_t x) { + const union { + dst_t f; + dst_rep_t i; + } rep = {.i = x}; + return rep.f; +} + +#endif // _FP_TRUNC_EMIT #define __truncXfYf2__ _FP_TRUNC_PAIR(__truncXfYf2__) diff --git a/lib/impl/int_to_fp.h b/lib/impl/int_to_fp.h @@ -1,174 +0,0 @@ -//===-- int_to_fp.h - integer to floating point conversion ----------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Source/destination type setup for int → fp conversions. Caller defines -// SRC_<I64/U64/I128/U128> and DST_<SINGLE/DOUBLE/QUAD> before each -// inclusion. -// -// Re-includable. Names depending on the (src, dst) pair are emitted with -// a `_<src><dst>` suffix exactly once per (TU, pair); bare-name #define -// aliases are set every inclusion. Use the umbrella `fp_lib_undef.h` to -// clear the bare-name aliases between sections in one TU. -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Self-clean any prior inclusion's per-(src, dst) state. May coexist with -// fp_extend.h / fp_trunc.h which define overlapping bare-name aliases. -#undef _INT_TO_FP_SRC_SUF -#undef _INT_TO_FP_DST_SUF -#undef SRC_REP_C -#undef DST_REP_C -#undef src_t -#undef usrc_t -#undef dst_t -#undef dst_rep_t -#undef clzSrcT -#undef dstFromRep -#undef dstSigBits - -#if defined SRC_I64 -#define _INT_TO_FP_SRC_SUF i64 -#elif defined SRC_U64 -#define _INT_TO_FP_SRC_SUF u64 -#elif defined SRC_I128 -#define _INT_TO_FP_SRC_SUF i128 -#elif defined SRC_U128 -#define _INT_TO_FP_SRC_SUF u128 -#else -#error Source should be a handled integer type. -#endif - -#if defined DST_SINGLE -#define _INT_TO_FP_DST_SUF sf -#elif defined DST_DOUBLE -#define _INT_TO_FP_DST_SUF df -#elif defined DST_QUAD -#define _INT_TO_FP_DST_SUF tf -#else -#error Destination should be a handled floating point type -#endif - -#define _INT_TO_FP_PASTE4_(a, b, c, d) a##b##c##d -#define _INT_TO_FP_PASTE4(a, b, c, d) _INT_TO_FP_PASTE4_(a, b, c, d) -#define _INT_TO_FP_PAIR(stem) _INT_TO_FP_PASTE4(stem, _, _INT_TO_FP_SRC_SUF, _INT_TO_FP_DST_SUF) - -// ---- Bare-name aliases (re-set every inclusion). ------------------------ - -#define src_t _INT_TO_FP_PAIR(src_t) -#define usrc_t _INT_TO_FP_PAIR(usrc_t) -#define dst_t _INT_TO_FP_PAIR(dst_t) -#define dst_rep_t _INT_TO_FP_PAIR(dst_rep_t) -#define clzSrcT _INT_TO_FP_PAIR(clzSrcT) -#define dstFromRep _INT_TO_FP_PAIR(dstFromRep) -#define dstSigBits _INT_TO_FP_PAIR(dstSigBits) - -// DST_REP_C: simple textual macro per dst. -#if defined DST_SINGLE -#define DST_REP_C UINT32_C -#elif defined DST_DOUBLE -#define DST_REP_C UINT64_C -#elif defined DST_QUAD -#define DST_REP_C (__uint128_t) -#endif - -// ---- One-time emission per (TU, src+dst pair). -------------------------- -// Pairs cfree uses: (i64,u64) × (sf,df) and (i128,u128) × (sf,df,tf). - -#if defined SRC_I64 && defined DST_SINGLE && !defined INT_TO_FP_I64SF_EMITTED -#define INT_TO_FP_I64SF_EMITTED -#define _INT_TO_FP_EMIT 1 -#elif defined SRC_I64 && defined DST_DOUBLE && !defined INT_TO_FP_I64DF_EMITTED -#define INT_TO_FP_I64DF_EMITTED -#define _INT_TO_FP_EMIT 1 -#elif defined SRC_U64 && defined DST_SINGLE && !defined INT_TO_FP_U64SF_EMITTED -#define INT_TO_FP_U64SF_EMITTED -#define _INT_TO_FP_EMIT 1 -#elif defined SRC_U64 && defined DST_DOUBLE && !defined INT_TO_FP_U64DF_EMITTED -#define INT_TO_FP_U64DF_EMITTED -#define _INT_TO_FP_EMIT 1 -#elif defined SRC_I128 && defined DST_SINGLE && !defined INT_TO_FP_I128SF_EMITTED -#define INT_TO_FP_I128SF_EMITTED -#define _INT_TO_FP_EMIT 1 -#elif defined SRC_I128 && defined DST_DOUBLE && !defined INT_TO_FP_I128DF_EMITTED -#define INT_TO_FP_I128DF_EMITTED -#define _INT_TO_FP_EMIT 1 -#elif defined SRC_I128 && defined DST_QUAD && !defined INT_TO_FP_I128TF_EMITTED -#define INT_TO_FP_I128TF_EMITTED -#define _INT_TO_FP_EMIT 1 -#elif defined SRC_U128 && defined DST_SINGLE && !defined INT_TO_FP_U128SF_EMITTED -#define INT_TO_FP_U128SF_EMITTED -#define _INT_TO_FP_EMIT 1 -#elif defined SRC_U128 && defined DST_DOUBLE && !defined INT_TO_FP_U128DF_EMITTED -#define INT_TO_FP_U128DF_EMITTED -#define _INT_TO_FP_EMIT 1 -#elif defined SRC_U128 && defined DST_QUAD && !defined INT_TO_FP_U128TF_EMITTED -#define INT_TO_FP_U128TF_EMITTED -#define _INT_TO_FP_EMIT 1 -#endif - -#ifdef _INT_TO_FP_EMIT -#undef _INT_TO_FP_EMIT - -#if defined SRC_I64 -typedef int64_t src_t; -typedef uint64_t usrc_t; -static __inline int clzSrcT(usrc_t x) { return __builtin_clzll(x); } - -#elif defined SRC_U64 -typedef uint64_t src_t; -typedef uint64_t usrc_t; -static __inline int clzSrcT(usrc_t x) { return __builtin_clzll(x); } - -#elif defined SRC_I128 -typedef __int128_t src_t; -typedef __uint128_t usrc_t; -static __inline int clzSrcT(usrc_t x) { return __clzti2(x); } - -#elif defined SRC_U128 -typedef __uint128_t src_t; -typedef __uint128_t usrc_t; -static __inline int clzSrcT(usrc_t x) { return __clzti2(x); } - -#endif - -#if defined DST_SINGLE -typedef float dst_t; -typedef uint32_t dst_rep_t; - -enum { - dstSigBits = 23, -}; - -#elif defined DST_DOUBLE -typedef double dst_t; -typedef uint64_t dst_rep_t; - -enum { - dstSigBits = 52, -}; - -#elif defined DST_QUAD -typedef tf_float dst_t; -typedef __uint128_t dst_rep_t; - -enum { - dstSigBits = 112, -}; - -#endif - -static __inline dst_t dstFromRep(dst_rep_t x) { - const union { - dst_t f; - dst_rep_t i; - } rep = {.i = x}; - return rep.f; -} - -#endif // _INT_TO_FP_EMIT diff --git a/lib/impl/int_to_fp_impl.inc b/lib/impl/int_to_fp_impl.inc @@ -12,7 +12,163 @@ // //===----------------------------------------------------------------------===// -#include "int_to_fp.h" +// ---- int_to_fp.h (was a separate header; merged) ---- +#include "int_lib.h" + +// Self-clean any prior inclusion's per-(src, dst) state. May coexist with +// fp_extend.h / fp_trunc.h which define overlapping bare-name aliases. +#undef _INT_TO_FP_SRC_SUF +#undef _INT_TO_FP_DST_SUF +#undef SRC_REP_C +#undef DST_REP_C +#undef src_t +#undef usrc_t +#undef dst_t +#undef dst_rep_t +#undef clzSrcT +#undef dstFromRep +#undef dstSigBits + +#if defined SRC_I64 +#define _INT_TO_FP_SRC_SUF i64 +#elif defined SRC_U64 +#define _INT_TO_FP_SRC_SUF u64 +#elif defined SRC_I128 +#define _INT_TO_FP_SRC_SUF i128 +#elif defined SRC_U128 +#define _INT_TO_FP_SRC_SUF u128 +#else +#error Source should be a handled integer type. +#endif + +#if defined DST_SINGLE +#define _INT_TO_FP_DST_SUF sf +#elif defined DST_DOUBLE +#define _INT_TO_FP_DST_SUF df +#elif defined DST_QUAD +#define _INT_TO_FP_DST_SUF tf +#else +#error Destination should be a handled floating point type +#endif + +#define _INT_TO_FP_PASTE4_(a, b, c, d) a##b##c##d +#define _INT_TO_FP_PASTE4(a, b, c, d) _INT_TO_FP_PASTE4_(a, b, c, d) +#define _INT_TO_FP_PAIR(stem) _INT_TO_FP_PASTE4(stem, _, _INT_TO_FP_SRC_SUF, _INT_TO_FP_DST_SUF) + +// ---- Bare-name aliases (re-set every inclusion). ------------------------ + +#define src_t _INT_TO_FP_PAIR(src_t) +#define usrc_t _INT_TO_FP_PAIR(usrc_t) +#define dst_t _INT_TO_FP_PAIR(dst_t) +#define dst_rep_t _INT_TO_FP_PAIR(dst_rep_t) +#define clzSrcT _INT_TO_FP_PAIR(clzSrcT) +#define dstFromRep _INT_TO_FP_PAIR(dstFromRep) +#define dstSigBits _INT_TO_FP_PAIR(dstSigBits) + +// DST_REP_C: simple textual macro per dst. +#if defined DST_SINGLE +#define DST_REP_C UINT32_C +#elif defined DST_DOUBLE +#define DST_REP_C UINT64_C +#elif defined DST_QUAD +#define DST_REP_C (__uint128_t) +#endif + +// ---- One-time emission per (TU, src+dst pair). -------------------------- +// Pairs cfree uses: (i64,u64) × (sf,df) and (i128,u128) × (sf,df,tf). + +#if defined SRC_I64 && defined DST_SINGLE && !defined INT_TO_FP_I64SF_EMITTED +#define INT_TO_FP_I64SF_EMITTED +#define _INT_TO_FP_EMIT 1 +#elif defined SRC_I64 && defined DST_DOUBLE && !defined INT_TO_FP_I64DF_EMITTED +#define INT_TO_FP_I64DF_EMITTED +#define _INT_TO_FP_EMIT 1 +#elif defined SRC_U64 && defined DST_SINGLE && !defined INT_TO_FP_U64SF_EMITTED +#define INT_TO_FP_U64SF_EMITTED +#define _INT_TO_FP_EMIT 1 +#elif defined SRC_U64 && defined DST_DOUBLE && !defined INT_TO_FP_U64DF_EMITTED +#define INT_TO_FP_U64DF_EMITTED +#define _INT_TO_FP_EMIT 1 +#elif defined SRC_I128 && defined DST_SINGLE && !defined INT_TO_FP_I128SF_EMITTED +#define INT_TO_FP_I128SF_EMITTED +#define _INT_TO_FP_EMIT 1 +#elif defined SRC_I128 && defined DST_DOUBLE && !defined INT_TO_FP_I128DF_EMITTED +#define INT_TO_FP_I128DF_EMITTED +#define _INT_TO_FP_EMIT 1 +#elif defined SRC_I128 && defined DST_QUAD && !defined INT_TO_FP_I128TF_EMITTED +#define INT_TO_FP_I128TF_EMITTED +#define _INT_TO_FP_EMIT 1 +#elif defined SRC_U128 && defined DST_SINGLE && !defined INT_TO_FP_U128SF_EMITTED +#define INT_TO_FP_U128SF_EMITTED +#define _INT_TO_FP_EMIT 1 +#elif defined SRC_U128 && defined DST_DOUBLE && !defined INT_TO_FP_U128DF_EMITTED +#define INT_TO_FP_U128DF_EMITTED +#define _INT_TO_FP_EMIT 1 +#elif defined SRC_U128 && defined DST_QUAD && !defined INT_TO_FP_U128TF_EMITTED +#define INT_TO_FP_U128TF_EMITTED +#define _INT_TO_FP_EMIT 1 +#endif + +#ifdef _INT_TO_FP_EMIT +#undef _INT_TO_FP_EMIT + +#if defined SRC_I64 +typedef int64_t src_t; +typedef uint64_t usrc_t; +static __inline int clzSrcT(usrc_t x) { return __builtin_clzll(x); } + +#elif defined SRC_U64 +typedef uint64_t src_t; +typedef uint64_t usrc_t; +static __inline int clzSrcT(usrc_t x) { return __builtin_clzll(x); } + +#elif defined SRC_I128 +typedef __int128_t src_t; +typedef __uint128_t usrc_t; +static __inline int clzSrcT(usrc_t x) { return __clzti2(x); } + +#elif defined SRC_U128 +typedef __uint128_t src_t; +typedef __uint128_t usrc_t; +static __inline int clzSrcT(usrc_t x) { return __clzti2(x); } + +#endif + +#if defined DST_SINGLE +typedef float dst_t; +typedef uint32_t dst_rep_t; + +enum { + dstSigBits = 23, +}; + +#elif defined DST_DOUBLE +typedef double dst_t; +typedef uint64_t dst_rep_t; + +enum { + dstSigBits = 52, +}; + +#elif defined DST_QUAD +typedef tf_float dst_t; +typedef __uint128_t dst_rep_t; + +enum { + dstSigBits = 112, +}; + +#endif + +static __inline dst_t dstFromRep(dst_rep_t x) { + const union { + dst_t f; + dst_rep_t i; + } rep = {.i = x}; + return rep.f; +} + +#endif // _INT_TO_FP_EMIT #define __floatXiYf__ _INT_TO_FP_PAIR(__floatXiYf__) diff --git a/lib/include/common/fp_lib.h b/lib/include/common/fp_lib.h @@ -26,7 +26,6 @@ #include "int_lib.h" #include "int_math.h" -#include "int_types.h" #include <limits.h> #include <stdbool.h> #include <stdint.h> diff --git a/lib/include/ilp32_le/int_endianness.h b/lib/include/ilp32_le/int_endianness.h @@ -1,13 +0,0 @@ -//===-- int_endianness.h - LP64 little-endian ----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -//===----------------------------------------------------------------------===// -#ifndef INT_ENDIANNESS_H -#define INT_ENDIANNESS_H - -#define _YUGA_LITTLE_ENDIAN 1 -#define _YUGA_BIG_ENDIAN 0 - -#endif diff --git a/lib/include/ilp32_le/int_lib.h b/lib/include/ilp32_le/int_lib.h @@ -29,7 +29,48 @@ #include <stdbool.h> #include <stdint.h> -#include "int_types.h" +// ---- int_types.h (merged) ---- +#ifndef INT_TYPES_H +#define INT_TYPES_H + +// (was int_endianness.h — only defined the markers below) +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 + +#ifdef si_int +#undef si_int +#endif +typedef int32_t si_int; +typedef uint32_t su_int; +#define clzsi __builtin_clz +#define ctzsi __builtin_ctz + +typedef int64_t di_int; +typedef uint64_t du_int; + +typedef union { + di_int all; + struct { su_int low; si_int high; } s; +} dwords; + +typedef union { + du_int all; + struct { su_int low; su_int high; } s; +} udwords; + +#define CRT_HAS_FLOATING_POINT 1 + +typedef union { su_int u; float f; } float_bits; +typedef union { udwords u; double f; } double_bits; +typedef struct { udwords low; udwords high; } uqwords; + +typedef float _Complex Fcomplex; +typedef double _Complex Dcomplex; +typedef long double _Complex Lcomplex; +#define COMPLEX_REAL(x) __real__(x) +#define COMPLEX_IMAGINARY(x) __imag__(x) + +#endif // INT_TYPES_H #include "int_util.h" COMPILER_RT_ABI int __paritysi2(si_int a); diff --git a/lib/include/ilp32_le/int_types.h b/lib/include/ilp32_le/int_types.h @@ -1,48 +0,0 @@ -//===-- int_types.h - ILP32 little-endian --------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// cfree-tailored: ILP32 little-endian. No 128-bit integer support. -//===----------------------------------------------------------------------===// - -#ifndef INT_TYPES_H -#define INT_TYPES_H - -#include "int_endianness.h" - -#ifdef si_int -#undef si_int -#endif -typedef int32_t si_int; -typedef uint32_t su_int; -#define clzsi __builtin_clz -#define ctzsi __builtin_ctz - -typedef int64_t di_int; -typedef uint64_t du_int; - -typedef union { - di_int all; - struct { su_int low; si_int high; } s; -} dwords; - -typedef union { - du_int all; - struct { su_int low; su_int high; } s; -} udwords; - -#define CRT_HAS_FLOATING_POINT 1 - -typedef union { su_int u; float f; } float_bits; -typedef union { udwords u; double f; } double_bits; -typedef struct { udwords low; udwords high; } uqwords; - -typedef float _Complex Fcomplex; -typedef double _Complex Dcomplex; -typedef long double _Complex Lcomplex; -#define COMPLEX_REAL(x) __real__(x) -#define COMPLEX_IMAGINARY(x) __imag__(x) - -#endif // INT_TYPES_H diff --git a/lib/include/llp64_le/int_endianness.h b/lib/include/llp64_le/int_endianness.h @@ -1,13 +0,0 @@ -//===-- int_endianness.h - LP64 little-endian ----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -//===----------------------------------------------------------------------===// -#ifndef INT_ENDIANNESS_H -#define INT_ENDIANNESS_H - -#define _YUGA_LITTLE_ENDIAN 1 -#define _YUGA_BIG_ENDIAN 0 - -#endif diff --git a/lib/include/llp64_le/int_lib.h b/lib/include/llp64_le/int_lib.h @@ -23,7 +23,69 @@ #include <stdbool.h> #include <stdint.h> -#include "int_types.h" +// ---- int_types.h (merged) ---- +#ifndef INT_TYPES_H +#define INT_TYPES_H + +// (was int_endianness.h — only defined the markers below) +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 + +#ifdef si_int +#undef si_int +#endif +typedef int32_t si_int; +typedef uint32_t su_int; +#define clzsi __builtin_clz +#define ctzsi __builtin_ctz + +typedef int64_t di_int; +typedef uint64_t du_int; + +typedef union { + di_int all; + struct { su_int low; si_int high; } s; +} dwords; + +typedef union { + du_int all; + struct { su_int low; su_int high; } s; +} udwords; + +#define CRT_HAS_128BIT +typedef int ti_int __attribute__((mode(TI))); +typedef unsigned tu_int __attribute__((mode(TI))); + +typedef union { + ti_int all; + struct { du_int low; di_int high; } s; +} twords; + +typedef union { + tu_int all; + struct { du_int low; du_int high; } s; +} utwords; + +static __inline ti_int make_ti(di_int h, di_int l) { + twords r; r.s.high = h; r.s.low = l; return r.all; +} +static __inline tu_int make_tu(du_int h, du_int l) { + utwords r; r.s.high = h; r.s.low = l; return r.all; +} + +#define CRT_HAS_FLOATING_POINT 1 + +typedef union { su_int u; float f; } float_bits; +typedef union { udwords u; double f; } double_bits; +typedef struct { udwords low; udwords high; } uqwords; + +typedef float _Complex Fcomplex; +typedef double _Complex Dcomplex; +typedef long double _Complex Lcomplex; +#define COMPLEX_REAL(x) __real__(x) +#define COMPLEX_IMAGINARY(x) __imag__(x) + +#endif // INT_TYPES_H #include "int_util.h" COMPILER_RT_ABI int __paritysi2(si_int a); diff --git a/lib/include/llp64_le/int_types.h b/lib/include/llp64_le/int_types.h @@ -1,69 +0,0 @@ -//===-- int_types.h - LLP64 little-endian --------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// cfree-tailored: LLP64 little-endian. Has 128-bit integer (__int128) support. -//===----------------------------------------------------------------------===// - -#ifndef INT_TYPES_H -#define INT_TYPES_H - -#include "int_endianness.h" - -#ifdef si_int -#undef si_int -#endif -typedef int32_t si_int; -typedef uint32_t su_int; -#define clzsi __builtin_clz -#define ctzsi __builtin_ctz - -typedef int64_t di_int; -typedef uint64_t du_int; - -typedef union { - di_int all; - struct { su_int low; si_int high; } s; -} dwords; - -typedef union { - du_int all; - struct { su_int low; su_int high; } s; -} udwords; - -#define CRT_HAS_128BIT -typedef int ti_int __attribute__((mode(TI))); -typedef unsigned tu_int __attribute__((mode(TI))); - -typedef union { - ti_int all; - struct { du_int low; di_int high; } s; -} twords; - -typedef union { - tu_int all; - struct { du_int low; du_int high; } s; -} utwords; - -static __inline ti_int make_ti(di_int h, di_int l) { - twords r; r.s.high = h; r.s.low = l; return r.all; -} -static __inline tu_int make_tu(du_int h, du_int l) { - utwords r; r.s.high = h; r.s.low = l; return r.all; -} - -#define CRT_HAS_FLOATING_POINT 1 - -typedef union { su_int u; float f; } float_bits; -typedef union { udwords u; double f; } double_bits; -typedef struct { udwords low; udwords high; } uqwords; - -typedef float _Complex Fcomplex; -typedef double _Complex Dcomplex; -typedef long double _Complex Lcomplex; -#define COMPLEX_REAL(x) __real__(x) -#define COMPLEX_IMAGINARY(x) __imag__(x) - -#endif // INT_TYPES_H diff --git a/lib/include/lp64_le/int_endianness.h b/lib/include/lp64_le/int_endianness.h @@ -1,13 +0,0 @@ -//===-- int_endianness.h - LP64 little-endian ----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -//===----------------------------------------------------------------------===// -#ifndef INT_ENDIANNESS_H -#define INT_ENDIANNESS_H - -#define _YUGA_LITTLE_ENDIAN 1 -#define _YUGA_BIG_ENDIAN 0 - -#endif diff --git a/lib/include/lp64_le/int_lib.h b/lib/include/lp64_le/int_lib.h @@ -25,7 +25,74 @@ #include <stdbool.h> #include <stdint.h> -#include "int_types.h" +// ---- int_types.h (merged) ---- +#ifndef INT_TYPES_H +#define INT_TYPES_H + +// (was int_endianness.h — only defined the markers below) +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 + +#ifdef si_int +#undef si_int +#endif +typedef int32_t si_int; +typedef uint32_t su_int; +#define clzsi __builtin_clz +#define ctzsi __builtin_ctz + +typedef int64_t di_int; +typedef uint64_t du_int; + +typedef union { + di_int all; + struct { su_int low; si_int high; } s; +} dwords; + +typedef union { + du_int all; + struct { su_int low; su_int high; } s; +} udwords; + +#define CRT_HAS_128BIT +typedef int ti_int __attribute__((mode(TI))); +typedef unsigned tu_int __attribute__((mode(TI))); + +typedef union { + ti_int all; + struct { du_int low; di_int high; } s; +} twords; + +typedef union { + tu_int all; + struct { du_int low; du_int high; } s; +} utwords; + +static __inline ti_int make_ti(di_int h, di_int l) { + twords r; r.s.high = h; r.s.low = l; return r.all; +} +static __inline tu_int make_tu(du_int h, du_int l) { + utwords r; r.s.high = h; r.s.low = l; return r.all; +} + +#define CRT_HAS_FLOATING_POINT 1 + +typedef union { su_int u; float f; } float_bits; +typedef union { udwords u; double f; } double_bits; + +typedef struct { udwords low; udwords high; } uqwords; + +// IEEE binary128 (tf_float / CRT_HAS_TF_MODE) is supplied via +// include/lp64_le_ldbl128/tf_supplement.h when compiling lib/fp_tf/. Not +// available in this base header to keep it free of feature ifdefs. + +typedef float _Complex Fcomplex; +typedef double _Complex Dcomplex; +typedef long double _Complex Lcomplex; +#define COMPLEX_REAL(x) __real__(x) +#define COMPLEX_IMAGINARY(x) __imag__(x) + +#endif // INT_TYPES_H #include "int_util.h" COMPILER_RT_ABI int __paritysi2(si_int a); diff --git a/lib/include/lp64_le/int_types.h b/lib/include/lp64_le/int_types.h @@ -1,74 +0,0 @@ -//===-- int_types.h - LP64 little-endian ---------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// cfree-tailored: LP64 little-endian. Has 128-bit integer (__int128) support. -//===----------------------------------------------------------------------===// - -#ifndef INT_TYPES_H -#define INT_TYPES_H - -#include "int_endianness.h" - -#ifdef si_int -#undef si_int -#endif -typedef int32_t si_int; -typedef uint32_t su_int; -#define clzsi __builtin_clz -#define ctzsi __builtin_ctz - -typedef int64_t di_int; -typedef uint64_t du_int; - -typedef union { - di_int all; - struct { su_int low; si_int high; } s; -} dwords; - -typedef union { - du_int all; - struct { su_int low; su_int high; } s; -} udwords; - -#define CRT_HAS_128BIT -typedef int ti_int __attribute__((mode(TI))); -typedef unsigned tu_int __attribute__((mode(TI))); - -typedef union { - ti_int all; - struct { du_int low; di_int high; } s; -} twords; - -typedef union { - tu_int all; - struct { du_int low; du_int high; } s; -} utwords; - -static __inline ti_int make_ti(di_int h, di_int l) { - twords r; r.s.high = h; r.s.low = l; return r.all; -} -static __inline tu_int make_tu(du_int h, du_int l) { - utwords r; r.s.high = h; r.s.low = l; return r.all; -} - -#define CRT_HAS_FLOATING_POINT 1 - -typedef union { su_int u; float f; } float_bits; -typedef union { udwords u; double f; } double_bits; - -typedef struct { udwords low; udwords high; } uqwords; - -// IEEE binary128 (tf_float / CRT_HAS_TF_MODE) is supplied via -// include/lp64_le_ldbl128/tf_supplement.h when compiling lib/fp_tf/. Not -// available in this base header to keep it free of feature ifdefs. - -typedef float _Complex Fcomplex; -typedef double _Complex Dcomplex; -typedef long double _Complex Lcomplex; -#define COMPLEX_REAL(x) __real__(x) -#define COMPLEX_IMAGINARY(x) __imag__(x) - -#endif // INT_TYPES_H diff --git a/lib/include/lp64_le_ldbl128/tf_supplement.h b/lib/include/lp64_le_ldbl128/tf_supplement.h @@ -8,11 +8,11 @@ #ifndef TF_SUPPLEMENT_H #define TF_SUPPLEMENT_H -// Pre-included before the translation unit, so the int_types.h pull happens -// before stdint.h has been brought in by int_lib.h. Bring it in directly. +// Pre-included before the translation unit; bring int_lib.h in directly so +// the per-target typedefs (uqwords, Lcomplex) it defines are available below. #include <stdint.h> -#include "int_types.h" +#include "int_lib.h" typedef long double tf_float; #define CRT_LDBL_128BIT diff --git a/lib/int/absvdi2.c b/lib/int/absvdi2.c @@ -1,25 +0,0 @@ -//===-- absvdi2.c - Implement __absvdi2 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __absvdi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: absolute value - -// Effects: aborts if abs(x) < 0 - -COMPILER_RT_ABI di_int __absvdi2(di_int a) { - const int N = (int)(sizeof(di_int) * CHAR_BIT); - if (a == ((di_int)((du_int)1 << (N - 1)))) - compilerrt_abort(); - const di_int t = a >> (N - 1); - return (a ^ t) - t; -} diff --git a/lib/int/bswapdi2.c b/lib/int/bswapdi2.c @@ -1,25 +0,0 @@ -//===-- bswapdi2.c - Implement __bswapdi2 ---------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __bswapdi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -COMPILER_RT_ABI uint64_t __bswapdi2(uint64_t u) { - return ( - (((u)&0xff00000000000000ULL) >> 56) | - (((u)&0x00ff000000000000ULL) >> 40) | - (((u)&0x0000ff0000000000ULL) >> 24) | - (((u)&0x000000ff00000000ULL) >> 8) | - (((u)&0x00000000ff000000ULL) << 8) | - (((u)&0x0000000000ff0000ULL) << 24) | - (((u)&0x000000000000ff00ULL) << 40) | - (((u)&0x00000000000000ffULL) << 56)); -} diff --git a/lib/int/bswapsi2.c b/lib/int/bswapsi2.c @@ -1,20 +0,0 @@ -//===-- bswapsi2.c - Implement __bswapsi2 ---------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __bswapsi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -COMPILER_RT_ABI uint32_t __bswapsi2(uint32_t u) { - return ((((u)&0xff000000) >> 24) | - (((u)&0x00ff0000) >> 8) | - (((u)&0x0000ff00) << 8) | - (((u)&0x000000ff) << 24)); -} diff --git a/lib/int/clzdi2.c b/lib/int/clzdi2.c @@ -1,25 +0,0 @@ -//===-- clzdi2.c - Implement __clzdi2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __clzdi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: the number of leading 0-bits - -// Precondition: a != 0 - -COMPILER_RT_ABI int __clzdi2(di_int a) { - dwords x; - x.all = a; - const si_int f = -(x.s.high == 0); - return clzsi((x.s.high & ~f) | (x.s.low & f)) + - (f & ((si_int)(sizeof(si_int) * CHAR_BIT))); -} diff --git a/lib/int/clzsi2.c b/lib/int/clzsi2.c @@ -1,48 +0,0 @@ -//===-- clzsi2.c - Implement __clzsi2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __clzsi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: the number of leading 0-bits - -// Precondition: a != 0 - -COMPILER_RT_ABI int __clzsi2(si_int a) { - su_int x = (su_int)a; - si_int t = ((x & 0xFFFF0000) == 0) << 4; // if (x is small) t = 16 else 0 - x >>= 16 - t; // x = [0 - 0xFFFF] - su_int r = t; // r = [0, 16] - // return r + clz(x) - t = ((x & 0xFF00) == 0) << 3; - x >>= 8 - t; // x = [0 - 0xFF] - r += t; // r = [0, 8, 16, 24] - // return r + clz(x) - t = ((x & 0xF0) == 0) << 2; - x >>= 4 - t; // x = [0 - 0xF] - r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28] - // return r + clz(x) - t = ((x & 0xC) == 0) << 1; - x >>= 2 - t; // x = [0 - 3] - r += t; // r = [0 - 30] and is even - // return r + clz(x) - // switch (x) - // { - // case 0: - // return r + 2; - // case 1: - // return r + 1; - // case 2: - // case 3: - // return r; - // } - return r + ((2 - x) & -((x & 2) == 0)); -} diff --git a/lib/int/cmpdi2.c b/lib/int/cmpdi2.c @@ -1,34 +0,0 @@ -//===-- cmpdi2.c - Implement __cmpdi2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __cmpdi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: if (a < b) returns 0 -// if (a == b) returns 1 -// if (a > b) returns 2 - -COMPILER_RT_ABI si_int __cmpdi2(di_int a, di_int b) { - dwords x; - x.all = a; - dwords y; - y.all = b; - if (x.s.high < y.s.high) - return 0; - if (x.s.high > y.s.high) - return 2; - if (x.s.low < y.s.low) - return 0; - if (x.s.low > y.s.low) - return 2; - return 1; -} - diff --git a/lib/int/ctzdi2.c b/lib/int/ctzdi2.c @@ -1,25 +0,0 @@ -//===-- ctzdi2.c - Implement __ctzdi2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __ctzdi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: the number of trailing 0-bits - -// Precondition: a != 0 - -COMPILER_RT_ABI int __ctzdi2(di_int a) { - dwords x; - x.all = a; - const si_int f = -(x.s.low == 0); - return ctzsi((x.s.high & f) | (x.s.low & ~f)) + - (f & ((si_int)(sizeof(si_int) * CHAR_BIT))); -} diff --git a/lib/int/ctzsi2.c b/lib/int/ctzsi2.c @@ -1,53 +0,0 @@ -//===-- ctzsi2.c - Implement __ctzsi2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __ctzsi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: the number of trailing 0-bits - -// Precondition: a != 0 - -COMPILER_RT_ABI int __ctzsi2(si_int a) { - su_int x = (su_int)a; - si_int t = ((x & 0x0000FFFF) == 0) - << 4; // if (x has no small bits) t = 16 else 0 - x >>= t; // x = [0 - 0xFFFF] + higher garbage bits - su_int r = t; // r = [0, 16] - // return r + ctz(x) - t = ((x & 0x00FF) == 0) << 3; - x >>= t; // x = [0 - 0xFF] + higher garbage bits - r += t; // r = [0, 8, 16, 24] - // return r + ctz(x) - t = ((x & 0x0F) == 0) << 2; - x >>= t; // x = [0 - 0xF] + higher garbage bits - r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28] - // return r + ctz(x) - t = ((x & 0x3) == 0) << 1; - x >>= t; - x &= 3; // x = [0 - 3] - r += t; // r = [0 - 30] and is even - // return r + ctz(x) - - // The branch-less return statement below is equivalent - // to the following switch statement: - // switch (x) - // { - // case 0: - // return r + 2; - // case 2: - // return r + 1; - // case 1: - // case 3: - // return r; - // } - return r + ((2 - (x >> 1)) & -((x & 1) == 0)); -} diff --git a/lib/int/divdi3.c b/lib/int/divdi3.c @@ -1,25 +0,0 @@ -//===-- divdi3.c - Implement __divdi3 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __divdi3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: a / b - -#define fixint_t di_int -#define fixuint_t du_int -#define INT_DIV_SUFFIX divdi3 -#define COMPUTE_UDIV(a, b) __udivmoddi4((a), (b), (du_int *)0) -#include "int_div_impl.inc" - -COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b) { - return __divXi3_divdi3(a, b); -} diff --git a/lib/int/divmoddi4.c b/lib/int/divmoddi4.c @@ -1,28 +0,0 @@ -//===-- divmoddi4.c - Implement __divmoddi4 -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __divmoddi4 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: a / b, *rem = a % b - -COMPILER_RT_ABI di_int __divmoddi4(di_int a, di_int b, di_int *rem) { - const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1; - di_int s_a = a >> bits_in_dword_m1; // s_a = a < 0 ? -1 : 0 - di_int s_b = b >> bits_in_dword_m1; // s_b = b < 0 ? -1 : 0 - a = (du_int)(a ^ s_a) - s_a; // negate if s_a == -1 - b = (du_int)(b ^ s_b) - s_b; // negate if s_b == -1 - s_b ^= s_a; // sign of quotient - du_int r; - di_int q = (__udivmoddi4(a, b, &r) ^ s_b) - s_b; // negate if s_b == -1 - *rem = (r ^ s_a) - s_a; // negate if s_a == -1 - return q; -} diff --git a/lib/int/ffsdi2.c b/lib/int/ffsdi2.c @@ -1,27 +0,0 @@ -//===-- ffsdi2.c - Implement __ffsdi2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __ffsdi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: the index of the least significant 1-bit in a, or -// the value zero if a is zero. The least significant bit is index one. - -COMPILER_RT_ABI int __ffsdi2(di_int a) { - dwords x; - x.all = a; - if (x.s.low == 0) { - if (x.s.high == 0) - return 0; - return ctzsi(x.s.high) + (1 + sizeof(si_int) * CHAR_BIT); - } - return ctzsi(x.s.low) + 1; -} diff --git a/lib/int/int.c b/lib/int/int.c @@ -0,0 +1,558 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Consolidated per-op runtime helpers for cfree's libcfree_rt.a. +// The build compiles only this one file per directory; the per-op .c files +// are #included as snippets and not directly compiled. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// int_util.c first: defines __compilerrt_abort_impl used by other helpers. +// ---- int_util.c ---- +#include "int_lib.h" + +__attribute__((weak)) +__attribute__((visibility("hidden"))) +void __compilerrt_abort_impl(const char *file, int line, const char *function) { + (void)file; + (void)line; + (void)function; + __builtin_trap(); +} + +// udivmoddi4.c next: __udivmoddi4 is called by divdi3, moddi3, divmoddi4, +// udivdi3, umoddi3 — must be defined before those callers. +// ---- udivmoddi4.c ---- +#include "int_lib.h" + +// Effects: if rem != 0, *rem = a % b +// Returns: a / b + +// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide + + +COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) { + const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT; + const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; + udwords n; + n.all = a; + udwords d; + d.all = b; + udwords q; + udwords r; + unsigned sr; + // special cases, X is unknown, K != 0 + if (n.s.high == 0) { + if (d.s.high == 0) { + // 0 X + // --- + // 0 X + if (rem) + *rem = n.s.low % d.s.low; + return n.s.low / d.s.low; + } + // 0 X + // --- + // K X + if (rem) + *rem = n.s.low; + return 0; + } + // n.s.high != 0 + if (d.s.low == 0) { + if (d.s.high == 0) { + // K X + // --- + // 0 0 + if (rem) + *rem = n.s.high % d.s.low; + return n.s.high / d.s.low; + } + // d.s.high != 0 + if (n.s.low == 0) { + // K 0 + // --- + // K 0 + if (rem) { + r.s.high = n.s.high % d.s.high; + r.s.low = 0; + *rem = r.all; + } + return n.s.high / d.s.high; + } + // K K + // --- + // K 0 + if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ { + if (rem) { + r.s.low = n.s.low; + r.s.high = n.s.high & (d.s.high - 1); + *rem = r.all; + } + return n.s.high >> ctzsi(d.s.high); + } + // K K + // --- + // K 0 + sr = clzsi(d.s.high) - clzsi(n.s.high); + // 0 <= sr <= n_uword_bits - 2 or sr large + if (sr > n_uword_bits - 2) { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + // 1 <= sr <= n_uword_bits - 1 + // q.all = n.all << (n_udword_bits - sr); + q.s.low = 0; + q.s.high = n.s.low << (n_uword_bits - sr); + // r.all = n.all >> sr; + r.s.high = n.s.high >> sr; + r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + } else /* d.s.low != 0 */ { + if (d.s.high == 0) { + // K X + // --- + // 0 K + if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ { + if (rem) + *rem = n.s.low & (d.s.low - 1); + if (d.s.low == 1) + return n.all; + sr = ctzsi(d.s.low); + q.s.high = n.s.high >> sr; + q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + return q.all; + } + // K X + // --- + // 0 K + sr = 1 + n_uword_bits + clzsi(d.s.low) - clzsi(n.s.high); + // 2 <= sr <= n_udword_bits - 1 + // q.all = n.all << (n_udword_bits - sr); + // r.all = n.all >> sr; + if (sr == n_uword_bits) { + q.s.low = 0; + q.s.high = n.s.low; + r.s.high = 0; + r.s.low = n.s.high; + } else if (sr < n_uword_bits) /* 2 <= sr <= n_uword_bits - 1 */ { + q.s.low = 0; + q.s.high = n.s.low << (n_uword_bits - sr); + r.s.high = n.s.high >> sr; + r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + } else /* n_uword_bits + 1 <= sr <= n_udword_bits - 1 */ { + q.s.low = n.s.low << (n_udword_bits - sr); + q.s.high = (n.s.high << (n_udword_bits - sr)) | + (n.s.low >> (sr - n_uword_bits)); + r.s.high = 0; + r.s.low = n.s.high >> (sr - n_uword_bits); + } + } else { + // K X + // --- + // K K + sr = clzsi(d.s.high) - clzsi(n.s.high); + // 0 <= sr <= n_uword_bits - 1 or sr large + if (sr > n_uword_bits - 1) { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + // 1 <= sr <= n_uword_bits + // q.all = n.all << (n_udword_bits - sr); + q.s.low = 0; + if (sr == n_uword_bits) { + q.s.high = n.s.low; + r.s.high = 0; + r.s.low = n.s.high; + } else { + q.s.high = n.s.low << (n_uword_bits - sr); + r.s.high = n.s.high >> sr; + r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + } + } + } + // Not a special case + // q and r are initialized with: + // q.all = n.all << (n_udword_bits - sr); + // r.all = n.all >> sr; + // 1 <= sr <= n_udword_bits - 1 + su_int carry = 0; + for (; sr > 0; --sr) { + // r:q = ((r:q) << 1) | carry + r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1)); + r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1)); + q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1)); + q.s.low = (q.s.low << 1) | carry; + // carry = 0; + // if (r.all >= d.all) + // { + // r.all -= d.all; + // carry = 1; + // } + const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1); + carry = s & 1; + r.all -= d.all & s; + } + q.all = (q.all << 1) | carry; + if (rem) + *rem = r.all; + return q.all; +} + + +// Leaf ops (no intra-directory dependencies): +// ---- absvdi2.c ---- +#include "int_lib.h" + +// Returns: absolute value + +// Effects: aborts if abs(x) < 0 + +COMPILER_RT_ABI di_int __absvdi2(di_int a) { + const int N = (int)(sizeof(di_int) * CHAR_BIT); + if (a == ((di_int)((du_int)1 << (N - 1)))) + compilerrt_abort(); + const di_int t = a >> (N - 1); + return (a ^ t) - t; +} +// ---- bswapdi2.c ---- +#include "int_lib.h" + +COMPILER_RT_ABI uint64_t __bswapdi2(uint64_t u) { + return ( + (((u)&0xff00000000000000ULL) >> 56) | + (((u)&0x00ff000000000000ULL) >> 40) | + (((u)&0x0000ff0000000000ULL) >> 24) | + (((u)&0x000000ff00000000ULL) >> 8) | + (((u)&0x00000000ff000000ULL) << 8) | + (((u)&0x0000000000ff0000ULL) << 24) | + (((u)&0x000000000000ff00ULL) << 40) | + (((u)&0x00000000000000ffULL) << 56)); +} +// ---- bswapsi2.c ---- +#include "int_lib.h" + +COMPILER_RT_ABI uint32_t __bswapsi2(uint32_t u) { + return ((((u)&0xff000000) >> 24) | + (((u)&0x00ff0000) >> 8) | + (((u)&0x0000ff00) << 8) | + (((u)&0x000000ff) << 24)); +} +// ---- clzdi2.c ---- +#include "int_lib.h" + +// Returns: the number of leading 0-bits + +// Precondition: a != 0 + +COMPILER_RT_ABI int __clzdi2(di_int a) { + dwords x; + x.all = a; + const si_int f = -(x.s.high == 0); + return clzsi((x.s.high & ~f) | (x.s.low & f)) + + (f & ((si_int)(sizeof(si_int) * CHAR_BIT))); +} +// ---- clzsi2.c ---- +#include "int_lib.h" + +// Returns: the number of leading 0-bits + +// Precondition: a != 0 + +COMPILER_RT_ABI int __clzsi2(si_int a) { + su_int x = (su_int)a; + si_int t = ((x & 0xFFFF0000) == 0) << 4; // if (x is small) t = 16 else 0 + x >>= 16 - t; // x = [0 - 0xFFFF] + su_int r = t; // r = [0, 16] + // return r + clz(x) + t = ((x & 0xFF00) == 0) << 3; + x >>= 8 - t; // x = [0 - 0xFF] + r += t; // r = [0, 8, 16, 24] + // return r + clz(x) + t = ((x & 0xF0) == 0) << 2; + x >>= 4 - t; // x = [0 - 0xF] + r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28] + // return r + clz(x) + t = ((x & 0xC) == 0) << 1; + x >>= 2 - t; // x = [0 - 3] + r += t; // r = [0 - 30] and is even + // return r + clz(x) + // switch (x) + // { + // case 0: + // return r + 2; + // case 1: + // return r + 1; + // case 2: + // case 3: + // return r; + // } + return r + ((2 - x) & -((x & 2) == 0)); +} +// ---- cmpdi2.c ---- +#include "int_lib.h" + +// Returns: if (a < b) returns 0 +// if (a == b) returns 1 +// if (a > b) returns 2 + +COMPILER_RT_ABI si_int __cmpdi2(di_int a, di_int b) { + dwords x; + x.all = a; + dwords y; + y.all = b; + if (x.s.high < y.s.high) + return 0; + if (x.s.high > y.s.high) + return 2; + if (x.s.low < y.s.low) + return 0; + if (x.s.low > y.s.low) + return 2; + return 1; +} + +// ---- ctzdi2.c ---- +#include "int_lib.h" + +// Returns: the number of trailing 0-bits + +// Precondition: a != 0 + +COMPILER_RT_ABI int __ctzdi2(di_int a) { + dwords x; + x.all = a; + const si_int f = -(x.s.low == 0); + return ctzsi((x.s.high & f) | (x.s.low & ~f)) + + (f & ((si_int)(sizeof(si_int) * CHAR_BIT))); +} +// ---- ctzsi2.c ---- +#include "int_lib.h" + +// Returns: the number of trailing 0-bits + +// Precondition: a != 0 + +COMPILER_RT_ABI int __ctzsi2(si_int a) { + su_int x = (su_int)a; + si_int t = ((x & 0x0000FFFF) == 0) + << 4; // if (x has no small bits) t = 16 else 0 + x >>= t; // x = [0 - 0xFFFF] + higher garbage bits + su_int r = t; // r = [0, 16] + // return r + ctz(x) + t = ((x & 0x00FF) == 0) << 3; + x >>= t; // x = [0 - 0xFF] + higher garbage bits + r += t; // r = [0, 8, 16, 24] + // return r + ctz(x) + t = ((x & 0x0F) == 0) << 2; + x >>= t; // x = [0 - 0xF] + higher garbage bits + r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28] + // return r + ctz(x) + t = ((x & 0x3) == 0) << 1; + x >>= t; + x &= 3; // x = [0 - 3] + r += t; // r = [0 - 30] and is even + // return r + ctz(x) + + // The branch-less return statement below is equivalent + // to the following switch statement: + // switch (x) + // { + // case 0: + // return r + 2; + // case 2: + // return r + 1; + // case 1: + // case 3: + // return r; + // } + return r + ((2 - (x >> 1)) & -((x & 1) == 0)); +} +// ---- ffsdi2.c ---- +#include "int_lib.h" + +// Returns: the index of the least significant 1-bit in a, or +// the value zero if a is zero. The least significant bit is index one. + +COMPILER_RT_ABI int __ffsdi2(di_int a) { + dwords x; + x.all = a; + if (x.s.low == 0) { + if (x.s.high == 0) + return 0; + return ctzsi(x.s.high) + (1 + sizeof(si_int) * CHAR_BIT); + } + return ctzsi(x.s.low) + 1; +} +// ---- negdi2.c ---- +#include "int_lib.h" + +// Returns: -a + +COMPILER_RT_ABI di_int __negdi2(di_int a) { + // Note: this routine is here for API compatibility; any sane compiler + // should expand it inline. + return -(du_int)a; +} +// ---- paritydi2.c ---- +#include "int_lib.h" + +// Returns: 1 if number of bits is odd else returns 0 + +COMPILER_RT_ABI int __paritydi2(di_int a) { + dwords x; + x.all = a; + su_int x2 = x.s.high ^ x.s.low; + x2 ^= x2 >> 16; + x2 ^= x2 >> 8; + x2 ^= x2 >> 4; + return (0x6996 >> (x2 & 0xF)) & 1; +} +// ---- paritysi2.c ---- +#include "int_lib.h" + +// Returns: 1 if number of bits is odd else returns 0 + +COMPILER_RT_ABI int __paritysi2(si_int a) { + su_int x = (su_int)a; + x ^= x >> 16; + x ^= x >> 8; + x ^= x >> 4; + return (0x6996 >> (x & 0xF)) & 1; +} +// ---- popcountdi2.c ---- +#include "int_lib.h" + +// Returns: count of 1 bits + +COMPILER_RT_ABI int __popcountdi2(di_int a) { + du_int x2 = (du_int)a; + x2 = x2 - ((x2 >> 1) & 0x5555555555555555uLL); + // Every 2 bits holds the sum of every pair of bits (32) + x2 = ((x2 >> 2) & 0x3333333333333333uLL) + (x2 & 0x3333333333333333uLL); + // Every 4 bits holds the sum of every 4-set of bits (3 significant bits) (16) + x2 = (x2 + (x2 >> 4)) & 0x0F0F0F0F0F0F0F0FuLL; + // Every 8 bits holds the sum of every 8-set of bits (4 significant bits) (8) + su_int x = (su_int)(x2 + (x2 >> 32)); + // The lower 32 bits hold four 16 bit sums (5 significant bits). + // Upper 32 bits are garbage + x = x + (x >> 16); + // The lower 16 bits hold two 32 bit sums (6 significant bits). + // Upper 16 bits are garbage + return (x + (x >> 8)) & 0x0000007F; // (7 significant bits) +} +// ---- popcountsi2.c ---- +#include "int_lib.h" + +// Returns: count of 1 bits + +COMPILER_RT_ABI int __popcountsi2(si_int a) { + su_int x = (su_int)a; + x = x - ((x >> 1) & 0x55555555); + // Every 2 bits holds the sum of every pair of bits + x = ((x >> 2) & 0x33333333) + (x & 0x33333333); + // Every 4 bits holds the sum of every 4-set of bits (3 significant bits) + x = (x + (x >> 4)) & 0x0F0F0F0F; + // Every 8 bits holds the sum of every 8-set of bits (4 significant bits) + x = (x + (x >> 16)); + // The lower 16 bits hold two 8 bit sums (5 significant bits). + // Upper 16 bits are garbage + return (x + (x >> 8)) & 0x0000003F; // (6 significant bits) +} +// ---- ucmpdi2.c ---- +#include "int_lib.h" + +// Returns: if (a < b) returns 0 +// if (a == b) returns 1 +// if (a > b) returns 2 + +COMPILER_RT_ABI si_int __ucmpdi2(du_int a, du_int b) { + udwords x; + x.all = a; + udwords y; + y.all = b; + if (x.s.high < y.s.high) + return 0; + if (x.s.high > y.s.high) + return 2; + if (x.s.low < y.s.low) + return 0; + if (x.s.low > y.s.low) + return 2; + return 1; +} + + +// Callers of __udivmoddi4: +// ---- udivdi3.c ---- +#include "int_lib.h" + +// Returns: a / b + +#define fixint_t di_int +#define fixuint_t du_int +#define INT_DIV_SUFFIX udivdi3 +#include "int_div_impl.inc" + +COMPILER_RT_ABI du_int __udivdi3(du_int a, du_int b) { + return __udivXi3_udivdi3(a, b); +} +// ---- umoddi3.c ---- +#include "int_lib.h" + +// Returns: a % b + +#define fixint_t di_int +#define fixuint_t du_int +#define INT_DIV_SUFFIX umoddi3 +#include "int_div_impl.inc" + +COMPILER_RT_ABI du_int __umoddi3(du_int a, du_int b) { + return __umodXi3_umoddi3(a, b); +} +// ---- divdi3.c ---- +#include "int_lib.h" + +// Returns: a / b + +#define fixint_t di_int +#define fixuint_t du_int +#define INT_DIV_SUFFIX divdi3 +#define COMPUTE_UDIV(a, b) __udivmoddi4((a), (b), (du_int *)0) +#include "int_div_impl.inc" + +COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b) { + return __divXi3_divdi3(a, b); +} +// ---- moddi3.c ---- +#include "int_lib.h" + +// Returns: a % b + +#define fixint_t di_int +#define fixuint_t du_int +#define INT_DIV_SUFFIX moddi3 +#define ASSIGN_UMOD(res, a, b) __udivmoddi4((a), (b), &(res)) +#include "int_div_impl.inc" + +COMPILER_RT_ABI di_int __moddi3(di_int a, di_int b) { + return __modXi3_moddi3(a, b); +} +// ---- divmoddi4.c ---- +#include "int_lib.h" + +// Returns: a / b, *rem = a % b + +COMPILER_RT_ABI di_int __divmoddi4(di_int a, di_int b, di_int *rem) { + const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1; + di_int s_a = a >> bits_in_dword_m1; // s_a = a < 0 ? -1 : 0 + di_int s_b = b >> bits_in_dword_m1; // s_b = b < 0 ? -1 : 0 + a = (du_int)(a ^ s_a) - s_a; // negate if s_a == -1 + b = (du_int)(b ^ s_b) - s_b; // negate if s_b == -1 + s_b ^= s_a; // sign of quotient + du_int r; + di_int q = (__udivmoddi4(a, b, &r) ^ s_b) - s_b; // negate if s_b == -1 + *rem = (r ^ s_a) - s_a; // negate if s_a == -1 + return q; +} diff --git a/lib/int/int_util.c b/lib/int/int_util.c @@ -1,20 +0,0 @@ -//===-- int_util.c - Internal utilities for compiler-rt ------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// cfree-tailored: freestanding only (cfree predefines __STDC_HOSTED__ == 0). -// Aborts via __builtin_trap() with no libc dependency. -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -__attribute__((weak)) -__attribute__((visibility("hidden"))) -void __compilerrt_abort_impl(const char *file, int line, const char *function) { - (void)file; - (void)line; - (void)function; - __builtin_trap(); -} diff --git a/lib/int/moddi3.c b/lib/int/moddi3.c @@ -1,25 +0,0 @@ -//===-- moddi3.c - Implement __moddi3 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __moddi3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: a % b - -#define fixint_t di_int -#define fixuint_t du_int -#define INT_DIV_SUFFIX moddi3 -#define ASSIGN_UMOD(res, a, b) __udivmoddi4((a), (b), &(res)) -#include "int_div_impl.inc" - -COMPILER_RT_ABI di_int __moddi3(di_int a, di_int b) { - return __modXi3_moddi3(a, b); -} diff --git a/lib/int/negdi2.c b/lib/int/negdi2.c @@ -1,21 +0,0 @@ -//===-- negdi2.c - Implement __negdi2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __negdi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: -a - -COMPILER_RT_ABI di_int __negdi2(di_int a) { - // Note: this routine is here for API compatibility; any sane compiler - // should expand it inline. - return -(du_int)a; -} diff --git a/lib/int/paritydi2.c b/lib/int/paritydi2.c @@ -1,25 +0,0 @@ -//===-- paritydi2.c - Implement __paritydi2 -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __paritydi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: 1 if number of bits is odd else returns 0 - -COMPILER_RT_ABI int __paritydi2(di_int a) { - dwords x; - x.all = a; - su_int x2 = x.s.high ^ x.s.low; - x2 ^= x2 >> 16; - x2 ^= x2 >> 8; - x2 ^= x2 >> 4; - return (0x6996 >> (x2 & 0xF)) & 1; -} diff --git a/lib/int/paritysi2.c b/lib/int/paritysi2.c @@ -1,23 +0,0 @@ -//===-- paritysi2.c - Implement __paritysi2 -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __paritysi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: 1 if number of bits is odd else returns 0 - -COMPILER_RT_ABI int __paritysi2(si_int a) { - su_int x = (su_int)a; - x ^= x >> 16; - x ^= x >> 8; - x ^= x >> 4; - return (0x6996 >> (x & 0xF)) & 1; -} diff --git a/lib/int/popcountdi2.c b/lib/int/popcountdi2.c @@ -1,32 +0,0 @@ -//===-- popcountdi2.c - Implement __popcountdi2 ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __popcountdi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: count of 1 bits - -COMPILER_RT_ABI int __popcountdi2(di_int a) { - du_int x2 = (du_int)a; - x2 = x2 - ((x2 >> 1) & 0x5555555555555555uLL); - // Every 2 bits holds the sum of every pair of bits (32) - x2 = ((x2 >> 2) & 0x3333333333333333uLL) + (x2 & 0x3333333333333333uLL); - // Every 4 bits holds the sum of every 4-set of bits (3 significant bits) (16) - x2 = (x2 + (x2 >> 4)) & 0x0F0F0F0F0F0F0F0FuLL; - // Every 8 bits holds the sum of every 8-set of bits (4 significant bits) (8) - su_int x = (su_int)(x2 + (x2 >> 32)); - // The lower 32 bits hold four 16 bit sums (5 significant bits). - // Upper 32 bits are garbage - x = x + (x >> 16); - // The lower 16 bits hold two 32 bit sums (6 significant bits). - // Upper 16 bits are garbage - return (x + (x >> 8)) & 0x0000007F; // (7 significant bits) -} diff --git a/lib/int/popcountsi2.c b/lib/int/popcountsi2.c @@ -1,29 +0,0 @@ -//===-- popcountsi2.c - Implement __popcountsi2 ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __popcountsi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: count of 1 bits - -COMPILER_RT_ABI int __popcountsi2(si_int a) { - su_int x = (su_int)a; - x = x - ((x >> 1) & 0x55555555); - // Every 2 bits holds the sum of every pair of bits - x = ((x >> 2) & 0x33333333) + (x & 0x33333333); - // Every 4 bits holds the sum of every 4-set of bits (3 significant bits) - x = (x + (x >> 4)) & 0x0F0F0F0F; - // Every 8 bits holds the sum of every 8-set of bits (4 significant bits) - x = (x + (x >> 16)); - // The lower 16 bits hold two 8 bit sums (5 significant bits). - // Upper 16 bits are garbage - return (x + (x >> 8)) & 0x0000003F; // (6 significant bits) -} diff --git a/lib/int/ucmpdi2.c b/lib/int/ucmpdi2.c @@ -1,34 +0,0 @@ -//===-- ucmpdi2.c - Implement __ucmpdi2 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __ucmpdi2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: if (a < b) returns 0 -// if (a == b) returns 1 -// if (a > b) returns 2 - -COMPILER_RT_ABI si_int __ucmpdi2(du_int a, du_int b) { - udwords x; - x.all = a; - udwords y; - y.all = b; - if (x.s.high < y.s.high) - return 0; - if (x.s.high > y.s.high) - return 2; - if (x.s.low < y.s.low) - return 0; - if (x.s.low > y.s.low) - return 2; - return 1; -} - diff --git a/lib/int/udivdi3.c b/lib/int/udivdi3.c @@ -1,24 +0,0 @@ -//===-- udivdi3.c - Implement __udivdi3 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __udivdi3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: a / b - -#define fixint_t di_int -#define fixuint_t du_int -#define INT_DIV_SUFFIX udivdi3 -#include "int_div_impl.inc" - -COMPILER_RT_ABI du_int __udivdi3(du_int a, du_int b) { - return __udivXi3_udivdi3(a, b); -} diff --git a/lib/int/udivmoddi4.c b/lib/int/udivmoddi4.c @@ -1,191 +0,0 @@ -//===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __udivmoddi4 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Effects: if rem != 0, *rem = a % b -// Returns: a / b - -// Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide - - -COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) { - const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT; - const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; - udwords n; - n.all = a; - udwords d; - d.all = b; - udwords q; - udwords r; - unsigned sr; - // special cases, X is unknown, K != 0 - if (n.s.high == 0) { - if (d.s.high == 0) { - // 0 X - // --- - // 0 X - if (rem) - *rem = n.s.low % d.s.low; - return n.s.low / d.s.low; - } - // 0 X - // --- - // K X - if (rem) - *rem = n.s.low; - return 0; - } - // n.s.high != 0 - if (d.s.low == 0) { - if (d.s.high == 0) { - // K X - // --- - // 0 0 - if (rem) - *rem = n.s.high % d.s.low; - return n.s.high / d.s.low; - } - // d.s.high != 0 - if (n.s.low == 0) { - // K 0 - // --- - // K 0 - if (rem) { - r.s.high = n.s.high % d.s.high; - r.s.low = 0; - *rem = r.all; - } - return n.s.high / d.s.high; - } - // K K - // --- - // K 0 - if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ { - if (rem) { - r.s.low = n.s.low; - r.s.high = n.s.high & (d.s.high - 1); - *rem = r.all; - } - return n.s.high >> ctzsi(d.s.high); - } - // K K - // --- - // K 0 - sr = clzsi(d.s.high) - clzsi(n.s.high); - // 0 <= sr <= n_uword_bits - 2 or sr large - if (sr > n_uword_bits - 2) { - if (rem) - *rem = n.all; - return 0; - } - ++sr; - // 1 <= sr <= n_uword_bits - 1 - // q.all = n.all << (n_udword_bits - sr); - q.s.low = 0; - q.s.high = n.s.low << (n_uword_bits - sr); - // r.all = n.all >> sr; - r.s.high = n.s.high >> sr; - r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); - } else /* d.s.low != 0 */ { - if (d.s.high == 0) { - // K X - // --- - // 0 K - if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ { - if (rem) - *rem = n.s.low & (d.s.low - 1); - if (d.s.low == 1) - return n.all; - sr = ctzsi(d.s.low); - q.s.high = n.s.high >> sr; - q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); - return q.all; - } - // K X - // --- - // 0 K - sr = 1 + n_uword_bits + clzsi(d.s.low) - clzsi(n.s.high); - // 2 <= sr <= n_udword_bits - 1 - // q.all = n.all << (n_udword_bits - sr); - // r.all = n.all >> sr; - if (sr == n_uword_bits) { - q.s.low = 0; - q.s.high = n.s.low; - r.s.high = 0; - r.s.low = n.s.high; - } else if (sr < n_uword_bits) /* 2 <= sr <= n_uword_bits - 1 */ { - q.s.low = 0; - q.s.high = n.s.low << (n_uword_bits - sr); - r.s.high = n.s.high >> sr; - r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); - } else /* n_uword_bits + 1 <= sr <= n_udword_bits - 1 */ { - q.s.low = n.s.low << (n_udword_bits - sr); - q.s.high = (n.s.high << (n_udword_bits - sr)) | - (n.s.low >> (sr - n_uword_bits)); - r.s.high = 0; - r.s.low = n.s.high >> (sr - n_uword_bits); - } - } else { - // K X - // --- - // K K - sr = clzsi(d.s.high) - clzsi(n.s.high); - // 0 <= sr <= n_uword_bits - 1 or sr large - if (sr > n_uword_bits - 1) { - if (rem) - *rem = n.all; - return 0; - } - ++sr; - // 1 <= sr <= n_uword_bits - // q.all = n.all << (n_udword_bits - sr); - q.s.low = 0; - if (sr == n_uword_bits) { - q.s.high = n.s.low; - r.s.high = 0; - r.s.low = n.s.high; - } else { - q.s.high = n.s.low << (n_uword_bits - sr); - r.s.high = n.s.high >> sr; - r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); - } - } - } - // Not a special case - // q and r are initialized with: - // q.all = n.all << (n_udword_bits - sr); - // r.all = n.all >> sr; - // 1 <= sr <= n_udword_bits - 1 - su_int carry = 0; - for (; sr > 0; --sr) { - // r:q = ((r:q) << 1) | carry - r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1)); - r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1)); - q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1)); - q.s.low = (q.s.low << 1) | carry; - // carry = 0; - // if (r.all >= d.all) - // { - // r.all -= d.all; - // carry = 1; - // } - const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1); - carry = s & 1; - r.all -= d.all & s; - } - q.all = (q.all << 1) | carry; - if (rem) - *rem = r.all; - return q.all; -} - diff --git a/lib/int/umoddi3.c b/lib/int/umoddi3.c @@ -1,24 +0,0 @@ -//===-- umoddi3.c - Implement __umoddi3 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __umoddi3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: a % b - -#define fixint_t di_int -#define fixuint_t du_int -#define INT_DIV_SUFFIX umoddi3 -#include "int_div_impl.inc" - -COMPILER_RT_ABI du_int __umoddi3(du_int a, du_int b) { - return __umodXi3_umoddi3(a, b); -} diff --git a/lib/int32/ashldi3.c b/lib/int32/ashldi3.c @@ -1,36 +0,0 @@ -// ====-- ashldi3.c - Implement __ashldi3 ---------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __ashldi3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: a << b - -// Precondition: 0 <= b < bits_in_dword - -COMPILER_RT_ABI di_int __ashldi3(di_int a, int b) { - const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT); - dwords input; - dwords result; - input.all = a; - if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ { - result.s.low = 0; - result.s.high = input.s.low << (b - bits_in_word); - } else /* 0 <= b < bits_in_word */ { - if (b == 0) - return a; - result.s.low = input.s.low << b; - result.s.high = - ((su_int)input.s.high << b) | (input.s.low >> (bits_in_word - b)); - } - return result.all; -} - diff --git a/lib/int32/ashrdi3.c b/lib/int32/ashrdi3.c @@ -1,37 +0,0 @@ -//===-- ashrdi3.c - Implement __ashrdi3 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __ashrdi3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: arithmetic a >> b - -// Precondition: 0 <= b < bits_in_dword - -COMPILER_RT_ABI di_int __ashrdi3(di_int a, int b) { - const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT); - dwords input; - dwords result; - input.all = a; - if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ { - // result.s.high = input.s.high < 0 ? -1 : 0 - result.s.high = input.s.high >> (bits_in_word - 1); - result.s.low = input.s.high >> (b - bits_in_word); - } else /* 0 <= b < bits_in_word */ { - if (b == 0) - return a; - result.s.high = input.s.high >> b; - result.s.low = - ((su_int)input.s.high << (bits_in_word - b)) | (input.s.low >> b); - } - return result.all; -} - diff --git a/lib/int32/int32.c b/lib/int32/int32.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Consolidated per-op runtime helpers for cfree's libcfree_rt.a. +// The build compiles only this one file per directory; the per-op .c files +// are #included as snippets and not directly compiled. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// ---- ashldi3.c ---- +#include "int_lib.h" + +// Returns: a << b + +// Precondition: 0 <= b < bits_in_dword + +COMPILER_RT_ABI di_int __ashldi3(di_int a, int b) { + const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT); + dwords input; + dwords result; + input.all = a; + if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ { + result.s.low = 0; + result.s.high = input.s.low << (b - bits_in_word); + } else /* 0 <= b < bits_in_word */ { + if (b == 0) + return a; + result.s.low = input.s.low << b; + result.s.high = + ((su_int)input.s.high << b) | (input.s.low >> (bits_in_word - b)); + } + return result.all; +} + +// ---- ashrdi3.c ---- +#include "int_lib.h" + +// Returns: arithmetic a >> b + +// Precondition: 0 <= b < bits_in_dword + +COMPILER_RT_ABI di_int __ashrdi3(di_int a, int b) { + const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT); + dwords input; + dwords result; + input.all = a; + if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ { + // result.s.high = input.s.high < 0 ? -1 : 0 + result.s.high = input.s.high >> (bits_in_word - 1); + result.s.low = input.s.high >> (b - bits_in_word); + } else /* 0 <= b < bits_in_word */ { + if (b == 0) + return a; + result.s.high = input.s.high >> b; + result.s.low = + ((su_int)input.s.high << (bits_in_word - b)) | (input.s.low >> b); + } + return result.all; +} + +// ---- lshrdi3.c ---- +#include "int_lib.h" + +// Returns: logical a >> b + +// Precondition: 0 <= b < bits_in_dword + +COMPILER_RT_ABI di_int __lshrdi3(di_int a, int b) { + const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT); + udwords input; + udwords result; + input.all = a; + if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ { + result.s.high = 0; + result.s.low = input.s.high >> (b - bits_in_word); + } else /* 0 <= b < bits_in_word */ { + if (b == 0) + return a; + result.s.high = input.s.high >> b; + result.s.low = (input.s.high << (bits_in_word - b)) | (input.s.low >> b); + } + return result.all; +} + +// ---- muldi3.c ---- +#include "int_lib.h" + +// Returns: a * b + +static di_int __muldsi3(su_int a, su_int b) { + dwords r; + const int bits_in_word_2 = (int)(sizeof(si_int) * CHAR_BIT) / 2; + const su_int lower_mask = (su_int)~0 >> bits_in_word_2; + r.s.low = (a & lower_mask) * (b & lower_mask); + su_int t = r.s.low >> bits_in_word_2; + r.s.low &= lower_mask; + t += (a >> bits_in_word_2) * (b & lower_mask); + r.s.low += (t & lower_mask) << bits_in_word_2; + r.s.high = t >> bits_in_word_2; + t = r.s.low >> bits_in_word_2; + r.s.low &= lower_mask; + t += (b >> bits_in_word_2) * (a & lower_mask); + r.s.low += (t & lower_mask) << bits_in_word_2; + r.s.high += t >> bits_in_word_2; + r.s.high += (a >> bits_in_word_2) * (b >> bits_in_word_2); + return r.all; +} + +// Returns: a * b + +COMPILER_RT_ABI di_int __muldi3(di_int a, di_int b) { + dwords x; + x.all = a; + dwords y; + y.all = b; + dwords r; + r.all = __muldsi3(x.s.low, y.s.low); + r.s.high += x.s.high * y.s.low + x.s.low * y.s.high; + return r.all; +} + diff --git a/lib/int32/lshrdi3.c b/lib/int32/lshrdi3.c @@ -1,35 +0,0 @@ -//===-- lshrdi3.c - Implement __lshrdi3 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __lshrdi3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: logical a >> b - -// Precondition: 0 <= b < bits_in_dword - -COMPILER_RT_ABI di_int __lshrdi3(di_int a, int b) { - const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT); - udwords input; - udwords result; - input.all = a; - if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ { - result.s.high = 0; - result.s.low = input.s.high >> (b - bits_in_word); - } else /* 0 <= b < bits_in_word */ { - if (b == 0) - return a; - result.s.high = input.s.high >> b; - result.s.low = (input.s.high << (bits_in_word - b)) | (input.s.low >> b); - } - return result.all; -} - diff --git a/lib/int32/muldi3.c b/lib/int32/muldi3.c @@ -1,48 +0,0 @@ -//===-- muldi3.c - Implement __muldi3 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __muldi3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - -// Returns: a * b - -static di_int __muldsi3(su_int a, su_int b) { - dwords r; - const int bits_in_word_2 = (int)(sizeof(si_int) * CHAR_BIT) / 2; - const su_int lower_mask = (su_int)~0 >> bits_in_word_2; - r.s.low = (a & lower_mask) * (b & lower_mask); - su_int t = r.s.low >> bits_in_word_2; - r.s.low &= lower_mask; - t += (a >> bits_in_word_2) * (b & lower_mask); - r.s.low += (t & lower_mask) << bits_in_word_2; - r.s.high = t >> bits_in_word_2; - t = r.s.low >> bits_in_word_2; - r.s.low &= lower_mask; - t += (b >> bits_in_word_2) * (a & lower_mask); - r.s.low += (t & lower_mask) << bits_in_word_2; - r.s.high += t >> bits_in_word_2; - r.s.high += (a >> bits_in_word_2) * (b >> bits_in_word_2); - return r.all; -} - -// Returns: a * b - -COMPILER_RT_ABI di_int __muldi3(di_int a, di_int b) { - dwords x; - x.all = a; - dwords y; - y.all = b; - dwords r; - r.all = __muldsi3(x.s.low, y.s.low); - r.s.high += x.s.high * y.s.low + x.s.low * y.s.high; - return r.all; -} - diff --git a/lib/int64/ashlti3.c b/lib/int64/ashlti3.c @@ -1,37 +0,0 @@ -//===-- ashlti3.c - Implement __ashlti3 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __ashlti3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: a << b - -// Precondition: 0 <= b < bits_in_tword - -COMPILER_RT_ABI ti_int __ashlti3(ti_int a, int b) { - const int bits_in_dword = (int)(sizeof(di_int) * CHAR_BIT); - twords input; - twords result; - input.all = a; - if (b & bits_in_dword) /* bits_in_dword <= b < bits_in_tword */ { - result.s.low = 0; - result.s.high = input.s.low << (b - bits_in_dword); - } else /* 0 <= b < bits_in_dword */ { - if (b == 0) - return a; - result.s.low = input.s.low << b; - result.s.high = - ((du_int)input.s.high << b) | (input.s.low >> (bits_in_dword - b)); - } - return result.all; -} - diff --git a/lib/int64/ashrti3.c b/lib/int64/ashrti3.c @@ -1,38 +0,0 @@ -//===-- ashrti3.c - Implement __ashrti3 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __ashrti3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: arithmetic a >> b - -// Precondition: 0 <= b < bits_in_tword - -COMPILER_RT_ABI ti_int __ashrti3(ti_int a, int b) { - const int bits_in_dword = (int)(sizeof(di_int) * CHAR_BIT); - twords input; - twords result; - input.all = a; - if (b & bits_in_dword) /* bits_in_dword <= b < bits_in_tword */ { - // result.s.high = input.s.high < 0 ? -1 : 0 - result.s.high = input.s.high >> (bits_in_dword - 1); - result.s.low = input.s.high >> (b - bits_in_dword); - } else /* 0 <= b < bits_in_dword */ { - if (b == 0) - return a; - result.s.high = input.s.high >> b; - result.s.low = - ((du_int)input.s.high << (bits_in_dword - b)) | (input.s.low >> b); - } - return result.all; -} - diff --git a/lib/int64/clzti2.c b/lib/int64/clzti2.c @@ -1,27 +0,0 @@ -//===-- clzti2.c - Implement __clzti2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __clzti2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: the number of leading 0-bits - -// Precondition: a != 0 - -COMPILER_RT_ABI int __clzti2(ti_int a) { - twords x; - x.all = a; - const di_int f = -(x.s.high == 0); - return __builtin_clzll((x.s.high & ~f) | (x.s.low & f)) + - ((si_int)f & ((si_int)(sizeof(di_int) * CHAR_BIT))); -} - diff --git a/lib/int64/ctzti2.c b/lib/int64/ctzti2.c @@ -1,27 +0,0 @@ -//===-- ctzti2.c - Implement __ctzti2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __ctzti2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: the number of trailing 0-bits - -// Precondition: a != 0 - -COMPILER_RT_ABI int __ctzti2(ti_int a) { - twords x; - x.all = a; - const di_int f = -(x.s.low == 0); - return __builtin_ctzll((x.s.high & f) | (x.s.low & ~f)) + - ((si_int)f & ((si_int)(sizeof(di_int) * CHAR_BIT))); -} - diff --git a/lib/int64/divmodti4.c b/lib/int64/divmodti4.c @@ -1,30 +0,0 @@ -//===-- divmodti4.c - Implement __divmodti4 -------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __divmodti4 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: a / b, *rem = a % b - -COMPILER_RT_ABI ti_int __divmodti4(ti_int a, ti_int b, ti_int *rem) { - const int bits_in_tword_m1 = (int)(sizeof(ti_int) * CHAR_BIT) - 1; - ti_int s_a = a >> bits_in_tword_m1; // s_a = a < 0 ? -1 : 0 - ti_int s_b = b >> bits_in_tword_m1; // s_b = b < 0 ? -1 : 0 - a = (tu_int)(a ^ s_a) - s_a; // negate if s_a == -1 - b = (tu_int)(b ^ s_b) - s_b; // negate if s_b == -1 - s_b ^= s_a; // sign of quotient - tu_int r; - ti_int q = (__udivmodti4(a, b, &r) ^ s_b) - s_b; // negate if s_b == -1 - *rem = (r ^ s_a) - s_a; // negate if s_a == -1 - return q; -} - diff --git a/lib/int64/divti3.c b/lib/int64/divti3.c @@ -1,27 +0,0 @@ -//===-- divti3.c - Implement __divti3 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __divti3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: a / b - -#define fixint_t ti_int -#define fixuint_t tu_int -#define INT_DIV_SUFFIX divti3 -#define COMPUTE_UDIV(a, b) __udivmodti4((a), (b), (tu_int *)0) -#include "int_div_impl.inc" - -COMPILER_RT_ABI ti_int __divti3(ti_int a, ti_int b) { - return __divXi3_divti3(a, b); -} - diff --git a/lib/int64/int64.c b/lib/int64/int64.c @@ -0,0 +1,383 @@ +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Consolidated per-op runtime helpers for cfree's libcfree_rt.a. +// The build compiles only this one file per directory; the per-op .c files +// are #included as snippets and not directly compiled. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// udivmodti4.c first: __udivmodti4 is called by divmodti4, divti3, modti3, +// udivti3, and umodti3 — must be defined before those callers. +// ---- udivmodti4.c ---- +#include "int_lib.h" + + +// Returns the 128 bit division result by 64 bit. Result must fit in 64 bits. +// Remainder stored in r. +// Taken and adjusted from libdivide libdivide_128_div_64_to_64 division +// fallback. For a correctness proof see the reference for this algorithm +// in Knuth, Volume 2, section 4.3.1, Algorithm D. +UNUSED +static inline du_int udiv128by64to64default(du_int u1, du_int u0, du_int v, + du_int *r) { + const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; + const du_int b = (1ULL << (n_udword_bits / 2)); // Number base (32 bits) + du_int un1, un0; // Norm. dividend LSD's + du_int vn1, vn0; // Norm. divisor digits + du_int q1, q0; // Quotient digits + du_int un64, un21, un10; // Dividend digit pairs + du_int rhat; // A remainder + si_int s; // Shift amount for normalization + + s = __builtin_clzll(v); + if (s > 0) { + // Normalize the divisor. + v = v << s; + un64 = (u1 << s) | (u0 >> (n_udword_bits - s)); + un10 = u0 << s; // Shift dividend left + } else { + // Avoid undefined behavior of (u0 >> 64). + un64 = u1; + un10 = u0; + } + + // Break divisor up into two 32-bit digits. + vn1 = v >> (n_udword_bits / 2); + vn0 = v & 0xFFFFFFFF; + + // Break right half of dividend into two digits. + un1 = un10 >> (n_udword_bits / 2); + un0 = un10 & 0xFFFFFFFF; + + // Compute the first quotient digit, q1. + q1 = un64 / vn1; + rhat = un64 - q1 * vn1; + + // q1 has at most error 2. No more than 2 iterations. + while (q1 >= b || q1 * vn0 > b * rhat + un1) { + q1 = q1 - 1; + rhat = rhat + vn1; + if (rhat >= b) + break; + } + + un21 = un64 * b + un1 - q1 * v; + + // Compute the second quotient digit. + q0 = un21 / vn1; + rhat = un21 - q0 * vn1; + + // q0 has at most error 2. No more than 2 iterations. + while (q0 >= b || q0 * vn0 > b * rhat + un0) { + q0 = q0 - 1; + rhat = rhat + vn1; + if (rhat >= b) + break; + } + + *r = (un21 * b + un0 - q0 * v) >> s; + return q1 * b + q0; +} + +static inline du_int udiv128by64to64(du_int u1, du_int u0, du_int v, + du_int *r) { + return udiv128by64to64default(u1, u0, v, r); +} + +// Effects: if rem != 0, *rem = a % b +// Returns: a / b + +COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int *rem) { + const unsigned n_utword_bits = sizeof(tu_int) * CHAR_BIT; + utwords dividend; + dividend.all = a; + utwords divisor; + divisor.all = b; + utwords quotient; + utwords remainder; + if (divisor.all > dividend.all) { + if (rem) + *rem = dividend.all; + return 0; + } + // When the divisor fits in 64 bits, we can use an optimized path. + if (divisor.s.high == 0) { + remainder.s.high = 0; + if (dividend.s.high < divisor.s.low) { + // The result fits in 64 bits. + quotient.s.low = udiv128by64to64(dividend.s.high, dividend.s.low, + divisor.s.low, &remainder.s.low); + quotient.s.high = 0; + } else { + // First, divide with the high part to get the remainder in dividend.s.high. + // After that dividend.s.high < divisor.s.low. + quotient.s.high = dividend.s.high / divisor.s.low; + dividend.s.high = dividend.s.high % divisor.s.low; + quotient.s.low = udiv128by64to64(dividend.s.high, dividend.s.low, + divisor.s.low, &remainder.s.low); + } + if (rem) + *rem = remainder.all; + return quotient.all; + } + // 0 <= shift <= 63. + si_int shift = + __builtin_clzll(divisor.s.high) - __builtin_clzll(dividend.s.high); + divisor.all <<= shift; + quotient.s.high = 0; + quotient.s.low = 0; + for (; shift >= 0; --shift) { + quotient.s.low <<= 1; + // Branch free version of. + // if (dividend.all >= divisor.all) + // { + // dividend.all -= divisor.all; + // carry = 1; + // } + const ti_int s = + (ti_int)(divisor.all - dividend.all - 1) >> (n_utword_bits - 1); + quotient.s.low |= s & 1; + dividend.all -= divisor.all & s; + divisor.all >>= 1; + } + if (rem) + *rem = dividend.all; + return quotient.all; +} + + +// Leaf ops (no intra-directory dependencies): +// ---- ashlti3.c ---- +#include "int_lib.h" + + +// Returns: a << b + +// Precondition: 0 <= b < bits_in_tword + +COMPILER_RT_ABI ti_int __ashlti3(ti_int a, int b) { + const int bits_in_dword = (int)(sizeof(di_int) * CHAR_BIT); + twords input; + twords result; + input.all = a; + if (b & bits_in_dword) /* bits_in_dword <= b < bits_in_tword */ { + result.s.low = 0; + result.s.high = input.s.low << (b - bits_in_dword); + } else /* 0 <= b < bits_in_dword */ { + if (b == 0) + return a; + result.s.low = input.s.low << b; + result.s.high = + ((du_int)input.s.high << b) | (input.s.low >> (bits_in_dword - b)); + } + return result.all; +} + +// ---- ashrti3.c ---- +#include "int_lib.h" + + +// Returns: arithmetic a >> b + +// Precondition: 0 <= b < bits_in_tword + +COMPILER_RT_ABI ti_int __ashrti3(ti_int a, int b) { + const int bits_in_dword = (int)(sizeof(di_int) * CHAR_BIT); + twords input; + twords result; + input.all = a; + if (b & bits_in_dword) /* bits_in_dword <= b < bits_in_tword */ { + // result.s.high = input.s.high < 0 ? -1 : 0 + result.s.high = input.s.high >> (bits_in_dword - 1); + result.s.low = input.s.high >> (b - bits_in_dword); + } else /* 0 <= b < bits_in_dword */ { + if (b == 0) + return a; + result.s.high = input.s.high >> b; + result.s.low = + ((du_int)input.s.high << (bits_in_dword - b)) | (input.s.low >> b); + } + return result.all; +} + +// ---- clzti2.c ---- +#include "int_lib.h" + + +// Returns: the number of leading 0-bits + +// Precondition: a != 0 + +COMPILER_RT_ABI int __clzti2(ti_int a) { + twords x; + x.all = a; + const di_int f = -(x.s.high == 0); + return __builtin_clzll((x.s.high & ~f) | (x.s.low & f)) + + ((si_int)f & ((si_int)(sizeof(di_int) * CHAR_BIT))); +} + +// ---- ctzti2.c ---- +#include "int_lib.h" + + +// Returns: the number of trailing 0-bits + +// Precondition: a != 0 + +COMPILER_RT_ABI int __ctzti2(ti_int a) { + twords x; + x.all = a; + const di_int f = -(x.s.low == 0); + return __builtin_ctzll((x.s.high & f) | (x.s.low & ~f)) + + ((si_int)f & ((si_int)(sizeof(di_int) * CHAR_BIT))); +} + +// ---- lshrti3.c ---- +#include "int_lib.h" + + +// Returns: logical a >> b + +// Precondition: 0 <= b < bits_in_tword + +COMPILER_RT_ABI ti_int __lshrti3(ti_int a, int b) { + const int bits_in_dword = (int)(sizeof(di_int) * CHAR_BIT); + utwords input; + utwords result; + input.all = a; + if (b & bits_in_dword) /* bits_in_dword <= b < bits_in_tword */ { + result.s.high = 0; + result.s.low = input.s.high >> (b - bits_in_dword); + } else /* 0 <= b < bits_in_dword */ { + if (b == 0) + return a; + result.s.high = input.s.high >> b; + result.s.low = (input.s.high << (bits_in_dword - b)) | (input.s.low >> b); + } + return result.all; +} + +// ---- multi3.c ---- +#include "int_lib.h" + + +// Returns: a * b + +static ti_int __mulddi3(du_int a, du_int b) { + twords r; + const int bits_in_dword_2 = (int)(sizeof(di_int) * CHAR_BIT) / 2; + const du_int lower_mask = (du_int)~0 >> bits_in_dword_2; + r.s.low = (a & lower_mask) * (b & lower_mask); + du_int t = r.s.low >> bits_in_dword_2; + r.s.low &= lower_mask; + t += (a >> bits_in_dword_2) * (b & lower_mask); + r.s.low += (t & lower_mask) << bits_in_dword_2; + r.s.high = t >> bits_in_dword_2; + t = r.s.low >> bits_in_dword_2; + r.s.low &= lower_mask; + t += (b >> bits_in_dword_2) * (a & lower_mask); + r.s.low += (t & lower_mask) << bits_in_dword_2; + r.s.high += t >> bits_in_dword_2; + r.s.high += (a >> bits_in_dword_2) * (b >> bits_in_dword_2); + return r.all; +} + +// Returns: a * b + +COMPILER_RT_ABI ti_int __multi3(ti_int a, ti_int b) { + twords x; + x.all = a; + twords y; + y.all = b; + twords r; + r.all = __mulddi3(x.s.low, y.s.low); + r.s.high += x.s.high * y.s.low + x.s.low * y.s.high; + return r.all; +} + +// ---- negti2.c ---- +#include "int_lib.h" + + +// Returns: -a + +COMPILER_RT_ABI ti_int __negti2(ti_int a) { + // Note: this routine is here for API compatibility; any sane compiler + // should expand it inline. + return -(tu_int)a; +} + + +// Callers of __udivmodti4: +// ---- udivti3.c ---- +#include "int_lib.h" + + +// Returns: a / b + +COMPILER_RT_ABI tu_int __udivti3(tu_int a, tu_int b) { + return __udivmodti4(a, b, 0); +} + +// ---- umodti3.c ---- +#include "int_lib.h" + + +// Returns: a % b + +COMPILER_RT_ABI tu_int __umodti3(tu_int a, tu_int b) { + tu_int r; + __udivmodti4(a, b, &r); + return r; +} + +// ---- divmodti4.c ---- +#include "int_lib.h" + + +// Returns: a / b, *rem = a % b + +COMPILER_RT_ABI ti_int __divmodti4(ti_int a, ti_int b, ti_int *rem) { + const int bits_in_tword_m1 = (int)(sizeof(ti_int) * CHAR_BIT) - 1; + ti_int s_a = a >> bits_in_tword_m1; // s_a = a < 0 ? -1 : 0 + ti_int s_b = b >> bits_in_tword_m1; // s_b = b < 0 ? -1 : 0 + a = (tu_int)(a ^ s_a) - s_a; // negate if s_a == -1 + b = (tu_int)(b ^ s_b) - s_b; // negate if s_b == -1 + s_b ^= s_a; // sign of quotient + tu_int r; + ti_int q = (__udivmodti4(a, b, &r) ^ s_b) - s_b; // negate if s_b == -1 + *rem = (r ^ s_a) - s_a; // negate if s_a == -1 + return q; +} + +// ---- divti3.c ---- +#include "int_lib.h" + + +// Returns: a / b + +#define fixint_t ti_int +#define fixuint_t tu_int +#define INT_DIV_SUFFIX divti3 +#define COMPUTE_UDIV(a, b) __udivmodti4((a), (b), (tu_int *)0) +#include "int_div_impl.inc" + +COMPILER_RT_ABI ti_int __divti3(ti_int a, ti_int b) { + return __divXi3_divti3(a, b); +} + +// ---- modti3.c ---- +#include "int_lib.h" + + +// Returns: a % b + +#define fixint_t ti_int +#define fixuint_t tu_int +#define INT_DIV_SUFFIX modti3 +#define ASSIGN_UMOD(res, a, b) __udivmodti4((a), (b), &(res)) +#include "int_div_impl.inc" + +COMPILER_RT_ABI ti_int __modti3(ti_int a, ti_int b) { + return __modXi3_modti3(a, b); +} + diff --git a/lib/int64/lshrti3.c b/lib/int64/lshrti3.c @@ -1,36 +0,0 @@ -//===-- lshrti3.c - Implement __lshrti3 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __lshrti3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: logical a >> b - -// Precondition: 0 <= b < bits_in_tword - -COMPILER_RT_ABI ti_int __lshrti3(ti_int a, int b) { - const int bits_in_dword = (int)(sizeof(di_int) * CHAR_BIT); - utwords input; - utwords result; - input.all = a; - if (b & bits_in_dword) /* bits_in_dword <= b < bits_in_tword */ { - result.s.high = 0; - result.s.low = input.s.high >> (b - bits_in_dword); - } else /* 0 <= b < bits_in_dword */ { - if (b == 0) - return a; - result.s.high = input.s.high >> b; - result.s.low = (input.s.high << (bits_in_dword - b)) | (input.s.low >> b); - } - return result.all; -} - diff --git a/lib/int64/modti3.c b/lib/int64/modti3.c @@ -1,27 +0,0 @@ -//===-- modti3.c - Implement __modti3 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __modti3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: a % b - -#define fixint_t ti_int -#define fixuint_t tu_int -#define INT_DIV_SUFFIX modti3 -#define ASSIGN_UMOD(res, a, b) __udivmodti4((a), (b), &(res)) -#include "int_div_impl.inc" - -COMPILER_RT_ABI ti_int __modti3(ti_int a, ti_int b) { - return __modXi3_modti3(a, b); -} - diff --git a/lib/int64/multi3.c b/lib/int64/multi3.c @@ -1,49 +0,0 @@ -//===-- multi3.c - Implement __multi3 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __multi3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: a * b - -static ti_int __mulddi3(du_int a, du_int b) { - twords r; - const int bits_in_dword_2 = (int)(sizeof(di_int) * CHAR_BIT) / 2; - const du_int lower_mask = (du_int)~0 >> bits_in_dword_2; - r.s.low = (a & lower_mask) * (b & lower_mask); - du_int t = r.s.low >> bits_in_dword_2; - r.s.low &= lower_mask; - t += (a >> bits_in_dword_2) * (b & lower_mask); - r.s.low += (t & lower_mask) << bits_in_dword_2; - r.s.high = t >> bits_in_dword_2; - t = r.s.low >> bits_in_dword_2; - r.s.low &= lower_mask; - t += (b >> bits_in_dword_2) * (a & lower_mask); - r.s.low += (t & lower_mask) << bits_in_dword_2; - r.s.high += t >> bits_in_dword_2; - r.s.high += (a >> bits_in_dword_2) * (b >> bits_in_dword_2); - return r.all; -} - -// Returns: a * b - -COMPILER_RT_ABI ti_int __multi3(ti_int a, ti_int b) { - twords x; - x.all = a; - twords y; - y.all = b; - twords r; - r.all = __mulddi3(x.s.low, y.s.low); - r.s.high += x.s.high * y.s.low + x.s.low * y.s.high; - return r.all; -} - diff --git a/lib/int64/negti2.c b/lib/int64/negti2.c @@ -1,23 +0,0 @@ -//===-- negti2.c - Implement __negti2 -------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __negti2 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: -a - -COMPILER_RT_ABI ti_int __negti2(ti_int a) { - // Note: this routine is here for API compatibility; any sane compiler - // should expand it inline. - return -(tu_int)a; -} - diff --git a/lib/int64/udivmodti4.c b/lib/int64/udivmodti4.c @@ -1,148 +0,0 @@ -//===-- udivmodti4.c - Implement __udivmodti4 -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __udivmodti4 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns the 128 bit division result by 64 bit. Result must fit in 64 bits. -// Remainder stored in r. -// Taken and adjusted from libdivide libdivide_128_div_64_to_64 division -// fallback. For a correctness proof see the reference for this algorithm -// in Knuth, Volume 2, section 4.3.1, Algorithm D. -UNUSED -static inline du_int udiv128by64to64default(du_int u1, du_int u0, du_int v, - du_int *r) { - const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; - const du_int b = (1ULL << (n_udword_bits / 2)); // Number base (32 bits) - du_int un1, un0; // Norm. dividend LSD's - du_int vn1, vn0; // Norm. divisor digits - du_int q1, q0; // Quotient digits - du_int un64, un21, un10; // Dividend digit pairs - du_int rhat; // A remainder - si_int s; // Shift amount for normalization - - s = __builtin_clzll(v); - if (s > 0) { - // Normalize the divisor. - v = v << s; - un64 = (u1 << s) | (u0 >> (n_udword_bits - s)); - un10 = u0 << s; // Shift dividend left - } else { - // Avoid undefined behavior of (u0 >> 64). - un64 = u1; - un10 = u0; - } - - // Break divisor up into two 32-bit digits. - vn1 = v >> (n_udword_bits / 2); - vn0 = v & 0xFFFFFFFF; - - // Break right half of dividend into two digits. - un1 = un10 >> (n_udword_bits / 2); - un0 = un10 & 0xFFFFFFFF; - - // Compute the first quotient digit, q1. - q1 = un64 / vn1; - rhat = un64 - q1 * vn1; - - // q1 has at most error 2. No more than 2 iterations. - while (q1 >= b || q1 * vn0 > b * rhat + un1) { - q1 = q1 - 1; - rhat = rhat + vn1; - if (rhat >= b) - break; - } - - un21 = un64 * b + un1 - q1 * v; - - // Compute the second quotient digit. - q0 = un21 / vn1; - rhat = un21 - q0 * vn1; - - // q0 has at most error 2. No more than 2 iterations. - while (q0 >= b || q0 * vn0 > b * rhat + un0) { - q0 = q0 - 1; - rhat = rhat + vn1; - if (rhat >= b) - break; - } - - *r = (un21 * b + un0 - q0 * v) >> s; - return q1 * b + q0; -} - -static inline du_int udiv128by64to64(du_int u1, du_int u0, du_int v, - du_int *r) { - return udiv128by64to64default(u1, u0, v, r); -} - -// Effects: if rem != 0, *rem = a % b -// Returns: a / b - -COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int *rem) { - const unsigned n_utword_bits = sizeof(tu_int) * CHAR_BIT; - utwords dividend; - dividend.all = a; - utwords divisor; - divisor.all = b; - utwords quotient; - utwords remainder; - if (divisor.all > dividend.all) { - if (rem) - *rem = dividend.all; - return 0; - } - // When the divisor fits in 64 bits, we can use an optimized path. - if (divisor.s.high == 0) { - remainder.s.high = 0; - if (dividend.s.high < divisor.s.low) { - // The result fits in 64 bits. - quotient.s.low = udiv128by64to64(dividend.s.high, dividend.s.low, - divisor.s.low, &remainder.s.low); - quotient.s.high = 0; - } else { - // First, divide with the high part to get the remainder in dividend.s.high. - // After that dividend.s.high < divisor.s.low. - quotient.s.high = dividend.s.high / divisor.s.low; - dividend.s.high = dividend.s.high % divisor.s.low; - quotient.s.low = udiv128by64to64(dividend.s.high, dividend.s.low, - divisor.s.low, &remainder.s.low); - } - if (rem) - *rem = remainder.all; - return quotient.all; - } - // 0 <= shift <= 63. - si_int shift = - __builtin_clzll(divisor.s.high) - __builtin_clzll(dividend.s.high); - divisor.all <<= shift; - quotient.s.high = 0; - quotient.s.low = 0; - for (; shift >= 0; --shift) { - quotient.s.low <<= 1; - // Branch free version of. - // if (dividend.all >= divisor.all) - // { - // dividend.all -= divisor.all; - // carry = 1; - // } - const ti_int s = - (ti_int)(divisor.all - dividend.all - 1) >> (n_utword_bits - 1); - quotient.s.low |= s & 1; - dividend.all -= divisor.all & s; - divisor.all >>= 1; - } - if (rem) - *rem = dividend.all; - return quotient.all; -} - diff --git a/lib/int64/udivti3.c b/lib/int64/udivti3.c @@ -1,21 +0,0 @@ -//===-- udivti3.c - Implement __udivti3 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __udivti3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: a / b - -COMPILER_RT_ABI tu_int __udivti3(tu_int a, tu_int b) { - return __udivmodti4(a, b, 0); -} - diff --git a/lib/int64/umodti3.c b/lib/int64/umodti3.c @@ -1,23 +0,0 @@ -//===-- umodti3.c - Implement __umodti3 -----------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements __umodti3 for the compiler_rt library. -// -//===----------------------------------------------------------------------===// - -#include "int_lib.h" - - -// Returns: a % b - -COMPILER_RT_ABI tu_int __umodti3(tu_int a, tu_int b) { - tu_int r; - __udivmodti4(a, b, &r); - return r; -} - diff --git a/lib/riscv/restore_rv32.S b/lib/riscv/restore_rv32.S @@ -1,73 +0,0 @@ -//===-- restore_rv32.S - restore up to 12 callee-save registers (RV32) ---===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - - .text - - .globl __riscv_restore_12 - .type __riscv_restore_12,@function -__riscv_restore_12: - lw s11, 12(sp) - addi sp, sp, 16 - // fallthrough into __riscv_restore_11/10/9/8 - - .globl __riscv_restore_11 - .type __riscv_restore_11,@function - .globl __riscv_restore_10 - .type __riscv_restore_10,@function - .globl __riscv_restore_9 - .type __riscv_restore_9,@function - .globl __riscv_restore_8 - .type __riscv_restore_8,@function -__riscv_restore_11: -__riscv_restore_10: -__riscv_restore_9: -__riscv_restore_8: - lw s10, 0(sp) - lw s9, 4(sp) - lw s8, 8(sp) - lw s7, 12(sp) - addi sp, sp, 16 - // fallthrough into __riscv_restore_7/6/5/4 - - .globl __riscv_restore_7 - .type __riscv_restore_7,@function - .globl __riscv_restore_6 - .type __riscv_restore_6,@function - .globl __riscv_restore_5 - .type __riscv_restore_5,@function - .globl __riscv_restore_4 - .type __riscv_restore_4,@function -__riscv_restore_7: -__riscv_restore_6: -__riscv_restore_5: -__riscv_restore_4: - lw s6, 0(sp) - lw s5, 4(sp) - lw s4, 8(sp) - lw s3, 12(sp) - addi sp, sp, 16 - // fallthrough into __riscv_restore_3/2/1/0 - - .globl __riscv_restore_3 - .type __riscv_restore_3,@function - .globl __riscv_restore_2 - .type __riscv_restore_2,@function - .globl __riscv_restore_1 - .type __riscv_restore_1,@function - .globl __riscv_restore_0 - .type __riscv_restore_0,@function -__riscv_restore_3: -__riscv_restore_2: -__riscv_restore_1: -__riscv_restore_0: - lw s2, 0(sp) - lw s1, 4(sp) - lw s0, 8(sp) - lw ra, 12(sp) - addi sp, sp, 16 - ret diff --git a/lib/riscv/restore_rv64.S b/lib/riscv/restore_rv64.S @@ -1,82 +0,0 @@ -//===-- restore_rv64.S - restore up to 12 callee-save registers (RV64) ---===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - - .text - - .globl __riscv_restore_12 - .type __riscv_restore_12,@function -__riscv_restore_12: - ld s11, 8(sp) - addi sp, sp, 16 - // fallthrough into __riscv_restore_11/10 - - .globl __riscv_restore_11 - .type __riscv_restore_11,@function - .globl __riscv_restore_10 - .type __riscv_restore_10,@function -__riscv_restore_11: -__riscv_restore_10: - ld s10, 0(sp) - ld s9, 8(sp) - addi sp, sp, 16 - // fallthrough into __riscv_restore_9/8 - - .globl __riscv_restore_9 - .type __riscv_restore_9,@function - .globl __riscv_restore_8 - .type __riscv_restore_8,@function -__riscv_restore_9: -__riscv_restore_8: - ld s8, 0(sp) - ld s7, 8(sp) - addi sp, sp, 16 - // fallthrough into __riscv_restore_7/6 - - .globl __riscv_restore_7 - .type __riscv_restore_7,@function - .globl __riscv_restore_6 - .type __riscv_restore_6,@function -__riscv_restore_7: -__riscv_restore_6: - ld s6, 0(sp) - ld s5, 8(sp) - addi sp, sp, 16 - // fallthrough into __riscv_restore_5/4 - - .globl __riscv_restore_5 - .type __riscv_restore_5,@function - .globl __riscv_restore_4 - .type __riscv_restore_4,@function -__riscv_restore_5: -__riscv_restore_4: - ld s4, 0(sp) - ld s3, 8(sp) - addi sp, sp, 16 - // fallthrough into __riscv_restore_3/2 - - .globl __riscv_restore_3 - .type __riscv_restore_3,@function - .globl __riscv_restore_2 - .type __riscv_restore_2,@function -__riscv_restore_3: -__riscv_restore_2: - ld s2, 0(sp) - ld s1, 8(sp) - addi sp, sp, 16 - // fallthrough into __riscv_restore_1/0 - - .globl __riscv_restore_1 - .type __riscv_restore_1,@function - .globl __riscv_restore_0 - .type __riscv_restore_0,@function -__riscv_restore_1: -__riscv_restore_0: - ld s0, 0(sp) - ld ra, 8(sp) - addi sp, sp, 16 - ret diff --git a/lib/riscv/rv32.S b/lib/riscv/rv32.S @@ -0,0 +1,147 @@ +// Consolidated save/restore helpers for cfree's libcfree_rt.a (RISC-V rv32). +// The build assembles only this one file for rv32; the per-op files are +// #included as snippets and not directly built. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// ---- save_rv32.S ---- + .text + + .globl __riscv_save_12 + .type __riscv_save_12,@function +__riscv_save_12: + addi sp, sp, -64 + mv t1, zero + sw s11, 12(sp) + j .Lriscv_save_11_8 + + .globl __riscv_save_11 + .type __riscv_save_11,@function + .globl __riscv_save_10 + .type __riscv_save_10,@function + .globl __riscv_save_9 + .type __riscv_save_9,@function + .globl __riscv_save_8 + .type __riscv_save_8,@function +__riscv_save_11: +__riscv_save_10: +__riscv_save_9: +__riscv_save_8: + addi sp, sp, -64 + li t1, 16 +.Lriscv_save_11_8: + sw s10, 16(sp) + sw s9, 20(sp) + sw s8, 24(sp) + sw s7, 28(sp) + j .Lriscv_save_7_4 + + .globl __riscv_save_7 + .type __riscv_save_7,@function + .globl __riscv_save_6 + .type __riscv_save_6,@function + .globl __riscv_save_5 + .type __riscv_save_5,@function + .globl __riscv_save_4 + .type __riscv_save_4,@function +__riscv_save_7: +__riscv_save_6: +__riscv_save_5: +__riscv_save_4: + addi sp, sp, -64 + li t1, 32 +.Lriscv_save_7_4: + sw s6, 32(sp) + sw s5, 36(sp) + sw s4, 40(sp) + sw s3, 44(sp) + sw s2, 48(sp) + sw s1, 52(sp) + sw s0, 56(sp) + sw ra, 60(sp) + add sp, sp, t1 + jr t0 + + .globl __riscv_save_3 + .type __riscv_save_3,@function + .globl __riscv_save_2 + .type __riscv_save_2,@function + .globl __riscv_save_1 + .type __riscv_save_1,@function + .globl __riscv_save_0 + .type __riscv_save_0,@function +__riscv_save_3: +__riscv_save_2: +__riscv_save_1: +__riscv_save_0: + addi sp, sp, -16 + sw s2, 0(sp) + sw s1, 4(sp) + sw s0, 8(sp) + sw ra, 12(sp) + jr t0 +// ---- restore_rv32.S ---- + .text + + .globl __riscv_restore_12 + .type __riscv_restore_12,@function +__riscv_restore_12: + lw s11, 12(sp) + addi sp, sp, 16 + // fallthrough into __riscv_restore_11/10/9/8 + + .globl __riscv_restore_11 + .type __riscv_restore_11,@function + .globl __riscv_restore_10 + .type __riscv_restore_10,@function + .globl __riscv_restore_9 + .type __riscv_restore_9,@function + .globl __riscv_restore_8 + .type __riscv_restore_8,@function +__riscv_restore_11: +__riscv_restore_10: +__riscv_restore_9: +__riscv_restore_8: + lw s10, 0(sp) + lw s9, 4(sp) + lw s8, 8(sp) + lw s7, 12(sp) + addi sp, sp, 16 + // fallthrough into __riscv_restore_7/6/5/4 + + .globl __riscv_restore_7 + .type __riscv_restore_7,@function + .globl __riscv_restore_6 + .type __riscv_restore_6,@function + .globl __riscv_restore_5 + .type __riscv_restore_5,@function + .globl __riscv_restore_4 + .type __riscv_restore_4,@function +__riscv_restore_7: +__riscv_restore_6: +__riscv_restore_5: +__riscv_restore_4: + lw s6, 0(sp) + lw s5, 4(sp) + lw s4, 8(sp) + lw s3, 12(sp) + addi sp, sp, 16 + // fallthrough into __riscv_restore_3/2/1/0 + + .globl __riscv_restore_3 + .type __riscv_restore_3,@function + .globl __riscv_restore_2 + .type __riscv_restore_2,@function + .globl __riscv_restore_1 + .type __riscv_restore_1,@function + .globl __riscv_restore_0 + .type __riscv_restore_0,@function +__riscv_restore_3: +__riscv_restore_2: +__riscv_restore_1: +__riscv_restore_0: + lw s2, 0(sp) + lw s1, 4(sp) + lw s0, 8(sp) + lw ra, 12(sp) + addi sp, sp, 16 + ret diff --git a/lib/riscv/rv64.S b/lib/riscv/rv64.S @@ -0,0 +1,169 @@ +// Consolidated save/restore helpers for cfree's libcfree_rt.a (RISC-V rv64). +// The build assembles only this one file for rv64; the per-op files are +// #included as snippets and not directly built. +// License: Apache-2.0 WITH LLVM-exception (see lib/LICENSE-compiler-rt.txt). + +// ---- save_rv64.S ---- + .text + + .globl __riscv_save_12 + .type __riscv_save_12,@function +__riscv_save_12: + addi sp, sp, -112 + mv t1, zero + sd s11, 8(sp) + j .Lriscv_save_11_10 + + .globl __riscv_save_11 + .type __riscv_save_11,@function + .globl __riscv_save_10 + .type __riscv_save_10,@function +__riscv_save_11: +__riscv_save_10: + addi sp, sp, -112 + li t1, 16 +.Lriscv_save_11_10: + sd s10, 16(sp) + sd s9, 24(sp) + j .Lriscv_save_9_8 + + .globl __riscv_save_9 + .type __riscv_save_9,@function + .globl __riscv_save_8 + .type __riscv_save_8,@function +__riscv_save_9: +__riscv_save_8: + addi sp, sp, -112 + li t1, 32 +.Lriscv_save_9_8: + sd s8, 32(sp) + sd s7, 40(sp) + j .Lriscv_save_7_6 + + .globl __riscv_save_7 + .type __riscv_save_7,@function + .globl __riscv_save_6 + .type __riscv_save_6,@function +__riscv_save_7: +__riscv_save_6: + addi sp, sp, -112 + li t1, 48 +.Lriscv_save_7_6: + sd s6, 48(sp) + sd s5, 56(sp) + j .Lriscv_save_5_4 + + .globl __riscv_save_5 + .type __riscv_save_5,@function + .globl __riscv_save_4 + .type __riscv_save_4,@function +__riscv_save_5: +__riscv_save_4: + addi sp, sp, -112 + li t1, 64 +.Lriscv_save_5_4: + sd s4, 64(sp) + sd s3, 72(sp) + j .Lriscv_save_3_2 + + .globl __riscv_save_3 + .type __riscv_save_3,@function + .globl __riscv_save_2 + .type __riscv_save_2,@function +__riscv_save_3: +__riscv_save_2: + addi sp, sp, -112 + li t1, 80 +.Lriscv_save_3_2: + sd s2, 80(sp) + sd s1, 88(sp) + sd s0, 96(sp) + sd ra, 104(sp) + add sp, sp, t1 + jr t0 + + .globl __riscv_save_1 + .type __riscv_save_1,@function + .globl __riscv_save_0 + .type __riscv_save_0,@function +__riscv_save_1: +__riscv_save_0: + addi sp, sp, -16 + sd s0, 0(sp) + sd ra, 8(sp) + jr t0 +// ---- restore_rv64.S ---- + .text + + .globl __riscv_restore_12 + .type __riscv_restore_12,@function +__riscv_restore_12: + ld s11, 8(sp) + addi sp, sp, 16 + // fallthrough into __riscv_restore_11/10 + + .globl __riscv_restore_11 + .type __riscv_restore_11,@function + .globl __riscv_restore_10 + .type __riscv_restore_10,@function +__riscv_restore_11: +__riscv_restore_10: + ld s10, 0(sp) + ld s9, 8(sp) + addi sp, sp, 16 + // fallthrough into __riscv_restore_9/8 + + .globl __riscv_restore_9 + .type __riscv_restore_9,@function + .globl __riscv_restore_8 + .type __riscv_restore_8,@function +__riscv_restore_9: +__riscv_restore_8: + ld s8, 0(sp) + ld s7, 8(sp) + addi sp, sp, 16 + // fallthrough into __riscv_restore_7/6 + + .globl __riscv_restore_7 + .type __riscv_restore_7,@function + .globl __riscv_restore_6 + .type __riscv_restore_6,@function +__riscv_restore_7: +__riscv_restore_6: + ld s6, 0(sp) + ld s5, 8(sp) + addi sp, sp, 16 + // fallthrough into __riscv_restore_5/4 + + .globl __riscv_restore_5 + .type __riscv_restore_5,@function + .globl __riscv_restore_4 + .type __riscv_restore_4,@function +__riscv_restore_5: +__riscv_restore_4: + ld s4, 0(sp) + ld s3, 8(sp) + addi sp, sp, 16 + // fallthrough into __riscv_restore_3/2 + + .globl __riscv_restore_3 + .type __riscv_restore_3,@function + .globl __riscv_restore_2 + .type __riscv_restore_2,@function +__riscv_restore_3: +__riscv_restore_2: + ld s2, 0(sp) + ld s1, 8(sp) + addi sp, sp, 16 + // fallthrough into __riscv_restore_1/0 + + .globl __riscv_restore_1 + .type __riscv_restore_1,@function + .globl __riscv_restore_0 + .type __riscv_restore_0,@function +__riscv_restore_1: +__riscv_restore_0: + ld s0, 0(sp) + ld ra, 8(sp) + addi sp, sp, 16 + ret diff --git a/lib/riscv/save_rv32.S b/lib/riscv/save_rv32.S @@ -1,88 +0,0 @@ -//===-- save_rv32.S - save up to 12 callee-saved registers (RV32) --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Multiple entry points depending on number of registers to save. -// Entry points are grouped in 4s for rv32 to maintain 16-byte stack alignment. -// -//===----------------------------------------------------------------------===// - - .text - - .globl __riscv_save_12 - .type __riscv_save_12,@function -__riscv_save_12: - addi sp, sp, -64 - mv t1, zero - sw s11, 12(sp) - j .Lriscv_save_11_8 - - .globl __riscv_save_11 - .type __riscv_save_11,@function - .globl __riscv_save_10 - .type __riscv_save_10,@function - .globl __riscv_save_9 - .type __riscv_save_9,@function - .globl __riscv_save_8 - .type __riscv_save_8,@function -__riscv_save_11: -__riscv_save_10: -__riscv_save_9: -__riscv_save_8: - addi sp, sp, -64 - li t1, 16 -.Lriscv_save_11_8: - sw s10, 16(sp) - sw s9, 20(sp) - sw s8, 24(sp) - sw s7, 28(sp) - j .Lriscv_save_7_4 - - .globl __riscv_save_7 - .type __riscv_save_7,@function - .globl __riscv_save_6 - .type __riscv_save_6,@function - .globl __riscv_save_5 - .type __riscv_save_5,@function - .globl __riscv_save_4 - .type __riscv_save_4,@function -__riscv_save_7: -__riscv_save_6: -__riscv_save_5: -__riscv_save_4: - addi sp, sp, -64 - li t1, 32 -.Lriscv_save_7_4: - sw s6, 32(sp) - sw s5, 36(sp) - sw s4, 40(sp) - sw s3, 44(sp) - sw s2, 48(sp) - sw s1, 52(sp) - sw s0, 56(sp) - sw ra, 60(sp) - add sp, sp, t1 - jr t0 - - .globl __riscv_save_3 - .type __riscv_save_3,@function - .globl __riscv_save_2 - .type __riscv_save_2,@function - .globl __riscv_save_1 - .type __riscv_save_1,@function - .globl __riscv_save_0 - .type __riscv_save_0,@function -__riscv_save_3: -__riscv_save_2: -__riscv_save_1: -__riscv_save_0: - addi sp, sp, -16 - sw s2, 0(sp) - sw s1, 4(sp) - sw s0, 8(sp) - sw ra, 12(sp) - jr t0 diff --git a/lib/riscv/save_rv64.S b/lib/riscv/save_rv64.S @@ -1,101 +0,0 @@ -//===-- save_rv64.S - save up to 12 callee-saved registers (RV64) --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Multiple entry points depending on number of registers to save. -// Entry points are grouped in 2s for rv64 to maintain 16-byte stack alignment. -// -//===----------------------------------------------------------------------===// - - .text - - .globl __riscv_save_12 - .type __riscv_save_12,@function -__riscv_save_12: - addi sp, sp, -112 - mv t1, zero - sd s11, 8(sp) - j .Lriscv_save_11_10 - - .globl __riscv_save_11 - .type __riscv_save_11,@function - .globl __riscv_save_10 - .type __riscv_save_10,@function -__riscv_save_11: -__riscv_save_10: - addi sp, sp, -112 - li t1, 16 -.Lriscv_save_11_10: - sd s10, 16(sp) - sd s9, 24(sp) - j .Lriscv_save_9_8 - - .globl __riscv_save_9 - .type __riscv_save_9,@function - .globl __riscv_save_8 - .type __riscv_save_8,@function -__riscv_save_9: -__riscv_save_8: - addi sp, sp, -112 - li t1, 32 -.Lriscv_save_9_8: - sd s8, 32(sp) - sd s7, 40(sp) - j .Lriscv_save_7_6 - - .globl __riscv_save_7 - .type __riscv_save_7,@function - .globl __riscv_save_6 - .type __riscv_save_6,@function -__riscv_save_7: -__riscv_save_6: - addi sp, sp, -112 - li t1, 48 -.Lriscv_save_7_6: - sd s6, 48(sp) - sd s5, 56(sp) - j .Lriscv_save_5_4 - - .globl __riscv_save_5 - .type __riscv_save_5,@function - .globl __riscv_save_4 - .type __riscv_save_4,@function -__riscv_save_5: -__riscv_save_4: - addi sp, sp, -112 - li t1, 64 -.Lriscv_save_5_4: - sd s4, 64(sp) - sd s3, 72(sp) - j .Lriscv_save_3_2 - - .globl __riscv_save_3 - .type __riscv_save_3,@function - .globl __riscv_save_2 - .type __riscv_save_2,@function -__riscv_save_3: -__riscv_save_2: - addi sp, sp, -112 - li t1, 80 -.Lriscv_save_3_2: - sd s2, 80(sp) - sd s1, 88(sp) - sd s0, 96(sp) - sd ra, 104(sp) - add sp, sp, t1 - jr t0 - - .globl __riscv_save_1 - .type __riscv_save_1,@function - .globl __riscv_save_0 - .type __riscv_save_0,@function -__riscv_save_1: -__riscv_save_0: - addi sp, sp, -16 - sd s0, 0(sp) - sd ra, 8(sp) - jr t0