cc-runtime/cc-runtime.c

3103 lines
98 KiB
C

#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
//===-- assembly.h - compiler-rt assembler support macros -----------------===//
//
// 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
//
// 2024/01/21 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file defines macros for use in compiler-rt assembler source.
// This file is not part of the interface of this library.
//
//===----------------------------------------------------------------------===//
#ifndef COMPILERRT_ASSEMBLY_H
#define COMPILERRT_ASSEMBLY_H
#define SEPARATOR ;
#define HIDDEN(name) .hidden name
#define LOCAL_LABEL(name) .L_##name
#define FILE_LEVEL_DIRECTIVE
#if defined(__arm__) || defined(__aarch64__)
#define SYMBOL_IS_FUNC(name) .type name,%function
#else
#define SYMBOL_IS_FUNC(name) .type name,@function
#endif
#define CONST_SECTION .section .rodata
#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits
#if defined(__arm__) || defined(__aarch64__)
#define FUNC_ALIGN \
.text SEPARATOR \
.balign 16 SEPARATOR
#else
#define FUNC_ALIGN
#endif
// BTI and PAC gnu property note
#define NT_GNU_PROPERTY_TYPE_0 5
#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1
#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2
#if defined(__ARM_FEATURE_BTI_DEFAULT)
#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
#else
#define BTI_FLAG 0
#endif
#if __ARM_FEATURE_PAC_DEFAULT & 3
#define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
#else
#define PAC_FLAG 0
#endif
#define GNU_PROPERTY(type, value) \
.pushsection .note.gnu.property, "a" SEPARATOR \
.p2align 3 SEPARATOR \
.word 4 SEPARATOR \
.word 16 SEPARATOR \
.word NT_GNU_PROPERTY_TYPE_0 SEPARATOR \
.asciz "GNU" SEPARATOR \
.word type SEPARATOR \
.word 4 SEPARATOR \
.word value SEPARATOR \
.word 0 SEPARATOR \
.popsection
#if BTI_FLAG != 0
#define BTI_C hint #34
#define BTI_J hint #36
#else
#define BTI_C
#define BTI_J
#endif
#if (BTI_FLAG | PAC_FLAG) != 0
#define GNU_PROPERTY_BTI_PAC \
GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG)
#else
#define GNU_PROPERTY_BTI_PAC
#endif
#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM)
#define CFI_START .cfi_startproc
#define CFI_END .cfi_endproc
#else
#define CFI_START
#define CFI_END
#endif
#if defined(__arm__)
// Determine actual [ARM][THUMB[1][2]] ISA using compiler predefined macros:
// - for '-mthumb -march=armv6' compiler defines '__thumb__'
// - for '-mthumb -march=armv7' compiler defines '__thumb__' and '__thumb2__'
#if defined(__thumb2__) || defined(__thumb__)
#define DEFINE_CODE_STATE .thumb SEPARATOR
#define DECLARE_FUNC_ENCODING .thumb_func SEPARATOR
#if defined(__thumb2__)
#define USE_THUMB_2
#define IT(cond) it cond
#define ITT(cond) itt cond
#define ITE(cond) ite cond
#else
#define USE_THUMB_1
#define IT(cond)
#define ITT(cond)
#define ITE(cond)
#endif // defined(__thumb__2)
#else // !defined(__thumb2__) && !defined(__thumb__)
#define DEFINE_CODE_STATE .arm SEPARATOR
#define DECLARE_FUNC_ENCODING
#define IT(cond)
#define ITT(cond)
#define ITE(cond)
#endif
#if defined(USE_THUMB_1) && defined(USE_THUMB_2)
#error "USE_THUMB_1 and USE_THUMB_2 can't be defined together."
#endif
#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5
#define ARM_HAS_BX
#endif
#if !defined(__ARM_FEATURE_CLZ) && !defined(USE_THUMB_1) && \
(__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__)))
#define __ARM_FEATURE_CLZ
#endif
#ifdef ARM_HAS_BX
#define JMP(r) bx r
#define JMPc(r, c) bx##c r
#else
#define JMP(r) mov pc, r
#define JMPc(r, c) mov##c pc, r
#endif
// pop {pc} can't switch Thumb mode on ARMv4T
#if __ARM_ARCH >= 5
#define POP_PC() pop {pc}
#else
#define POP_PC() \
pop {ip}; \
JMP(ip)
#endif
#if defined(USE_THUMB_2)
#define WIDE(op) op.w
#else
#define WIDE(op) op
#endif
#else // !defined(__arm)
#define DECLARE_FUNC_ENCODING
#define DEFINE_CODE_STATE
#endif
#define GLUE2_(a, b) a##b
#define GLUE(a, b) GLUE2_(a, b)
#define GLUE2(a, b) GLUE2_(a, b)
#define GLUE3_(a, b, c) a##b##c
#define GLUE3(a, b, c) GLUE3_(a, b, c)
#define GLUE4_(a, b, c, d) a##b##c##d
#define GLUE4(a, b, c, d) GLUE4_(a, b, c, d)
#ifndef SYMBOL_NAME
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
#endif
#ifdef VISIBILITY_HIDDEN
#define DECLARE_SYMBOL_VISIBILITY(name) \
HIDDEN(SYMBOL_NAME(name)) SEPARATOR
#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) \
HIDDEN(name) SEPARATOR
#else
#define DECLARE_SYMBOL_VISIBILITY(name)
#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name)
#endif
#define DEFINE_COMPILERRT_FUNCTION(name) \
DEFINE_CODE_STATE \
FILE_LEVEL_DIRECTIVE SEPARATOR \
.globl SYMBOL_NAME(name) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
DECLARE_SYMBOL_VISIBILITY(name) \
DECLARE_FUNC_ENCODING \
SYMBOL_NAME(name):
#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \
DEFINE_CODE_STATE \
FILE_LEVEL_DIRECTIVE SEPARATOR \
.globl SYMBOL_NAME(name) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
.thumb_func SEPARATOR \
SYMBOL_NAME(name):
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
DEFINE_CODE_STATE \
FILE_LEVEL_DIRECTIVE SEPARATOR \
.globl SYMBOL_NAME(name) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
HIDDEN(SYMBOL_NAME(name)) SEPARATOR \
DECLARE_FUNC_ENCODING \
SYMBOL_NAME(name):
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
DEFINE_CODE_STATE \
.globl name SEPARATOR \
SYMBOL_IS_FUNC(name) SEPARATOR \
HIDDEN(name) SEPARATOR \
DECLARE_FUNC_ENCODING \
name:
#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \
DEFINE_CODE_STATE \
FUNC_ALIGN \
.globl name SEPARATOR \
SYMBOL_IS_FUNC(name) SEPARATOR \
DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR \
DECLARE_FUNC_ENCODING \
name: \
SEPARATOR CFI_START \
SEPARATOR BTI_C
#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \
.globl SYMBOL_NAME(name) SEPARATOR \
SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \
DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \
.set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR
#if defined(__ARM_EABI__)
#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \
DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name)
#else
#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name)
#endif
#define END_COMPILERRT_FUNCTION(name) \
.size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
#define END_COMPILERRT_OUTLINE_FUNCTION(name) \
CFI_END SEPARATOR \
.size SYMBOL_NAME(name), . - SYMBOL_NAME(name)
#endif // COMPILERRT_ASSEMBLY_H
//===-- int_endianness.h - configuration header 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
//
// 2024/01/21 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file is a configuration header for compiler-rt.
// This file is not part of the interface of this library.
//
//===----------------------------------------------------------------------===//
#ifndef INT_ENDIANNESS_H
#define INT_ENDIANNESS_H
// Clang and GCC provide built-in endianness definitions.
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define _YUGA_LITTLE_ENDIAN 0
#define _YUGA_BIG_ENDIAN 1
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define _YUGA_LITTLE_ENDIAN 1
#define _YUGA_BIG_ENDIAN 0
#endif // __BYTE_ORDER__
#endif // INT_ENDIANNESS_H
//===-- int_lib.h - configuration header 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
//
// 2024/01/21 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file is not part of the interface of this library.
//
// This file defines various standard types, most importantly a number of unions
// used to access parts of larger types.
//
//===----------------------------------------------------------------------===//
#ifndef INT_TYPES_H
#define INT_TYPES_H
// si_int is defined in Linux sysroot's asm-generic/siginfo.h
#ifdef si_int
#undef si_int
#endif
typedef int32_t si_int;
typedef uint32_t su_int;
#if UINT_MAX == 0xFFFFFFFF
#define clzsi __builtin_clz
#define ctzsi __builtin_ctz
#elif ULONG_MAX == 0xFFFFFFFF
#define clzsi __builtin_clzl
#define ctzsi __builtin_ctzl
#else
#error could not determine appropriate clzsi macro for this system
#endif
typedef int64_t di_int;
typedef uint64_t du_int;
typedef union {
di_int all;
struct {
#if _YUGA_LITTLE_ENDIAN
su_int low;
si_int high;
#else
si_int high;
su_int low;
#endif // _YUGA_LITTLE_ENDIAN
} s;
} dwords;
typedef union {
du_int all;
struct {
#if _YUGA_LITTLE_ENDIAN
su_int low;
su_int high;
#else
su_int high;
su_int low;
#endif // _YUGA_LITTLE_ENDIAN
} s;
} udwords;
#if defined(__LP64__) || defined(__wasm__) || defined(__mips64) || \
defined(__SIZEOF_INT128__)
#define CRT_HAS_128BIT
#endif
#ifdef CRT_HAS_128BIT
typedef int ti_int __attribute__((mode(TI)));
typedef unsigned tu_int __attribute__((mode(TI)));
typedef union {
ti_int all;
struct {
#if _YUGA_LITTLE_ENDIAN
du_int low;
di_int high;
#else
di_int high;
du_int low;
#endif // _YUGA_LITTLE_ENDIAN
} s;
} twords;
typedef union {
tu_int all;
struct {
#if _YUGA_LITTLE_ENDIAN
du_int low;
du_int high;
#else
du_int high;
du_int low;
#endif // _YUGA_LITTLE_ENDIAN
} s;
} utwords;
#endif // CRT_HAS_128BIT
#endif // INT_TYPES_H
//===-- int_lib.h - configuration header 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
//
// 2024/01/21 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file is a configuration header for compiler-rt.
// This file is not part of the interface of this library.
//
//===----------------------------------------------------------------------===//
#ifndef INT_LIB_H
#define INT_LIB_H
// Assumption: Signed integral is 2's complement.
// Assumption: Right shift of signed negative is arithmetic shift.
// Assumption: Endianness is little or big (not mixed).
// ABI macro definitions
#if __ARM_EABI__
#ifdef COMPILER_RT_ARMHF_TARGET
#define COMPILER_RT_ABI
#else
#define COMPILER_RT_ABI __attribute__((__pcs__("aapcs")))
#endif
#else
#define COMPILER_RT_ABI
#endif
#define AEABI_RTABI __attribute__((__pcs__("aapcs")))
#define ALWAYS_INLINE __attribute__((always_inline))
#define NOINLINE __attribute__((noinline))
#define NORETURN __attribute__((noreturn))
#define UNUSED __attribute__((unused))
#ifndef SYMBOL_NAME
#define STR(a) #a
#define XSTR(a) STR(a)
#define SYMBOL_NAME(name) XSTR(__USER_LABEL_PREFIX__) #name
#endif
#define COMPILER_RT_ALIAS(name, aliasname) \
COMPILER_RT_ABI __typeof(name) aliasname __attribute__((__alias__(#name)));
// Include the standard compiler builtin headers we use functionality from.
// Include the commonly used internal type definitions.
// Include internal utility function declarations.
COMPILER_RT_ABI int __paritysi2(si_int a);
COMPILER_RT_ABI int __paritydi2(di_int a);
COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b);
COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b);
COMPILER_RT_ABI su_int __udivsi3(su_int n, su_int d);
COMPILER_RT_ABI su_int __udivmodsi4(su_int a, su_int b, su_int *rem);
COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem);
#ifdef CRT_HAS_128BIT
COMPILER_RT_ABI int __clzti2(ti_int a);
COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int *rem);
#endif
#endif // INT_LIB_H
//===-- int_util.h - internal utility functions ---------------------------===//
//
// 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 is not part of the interface of this library.
//
// This file defines non-inline utilities which are available for use in the
// library. The function definitions themselves are all contained in int_util.c
// which will always be compiled into any compiler-rt library.
//
//===----------------------------------------------------------------------===//
#ifndef INT_UTIL_H
#define INT_UTIL_H
/// \brief Trigger a program abort (or panic for kernel code).
#define compilerrt_abort() __compilerrt_abort_impl(__FILE__, __LINE__, __func__)
NORETURN void __compilerrt_abort_impl(const char *file, int line,
const char *function);
#define COMPILE_TIME_ASSERT(expr) COMPILE_TIME_ASSERT1(expr, __COUNTER__)
#define COMPILE_TIME_ASSERT1(expr, cnt) COMPILE_TIME_ASSERT2(expr, cnt)
#define COMPILE_TIME_ASSERT2(expr, cnt) \
typedef char ct_assert_##cnt[(expr) ? 1 : -1] UNUSED
// Force unrolling the code specified to be repeated N times.
#define REPEAT_0_TIMES(code_to_repeat) /* do nothing */
#define REPEAT_1_TIMES(code_to_repeat) code_to_repeat
#define REPEAT_2_TIMES(code_to_repeat) \
REPEAT_1_TIMES(code_to_repeat) \
code_to_repeat
#define REPEAT_3_TIMES(code_to_repeat) \
REPEAT_2_TIMES(code_to_repeat) \
code_to_repeat
#define REPEAT_4_TIMES(code_to_repeat) \
REPEAT_3_TIMES(code_to_repeat) \
code_to_repeat
#define REPEAT_N_TIMES_(N, code_to_repeat) REPEAT_##N##_TIMES(code_to_repeat)
#define REPEAT_N_TIMES(N, code_to_repeat) REPEAT_N_TIMES_(N, code_to_repeat)
#endif // INT_UTIL_H
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
//===-- absvsi2.c - Implement __absvsi2 -----------------------------------===//
//
// 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 __absvsi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: absolute value
// Effects: aborts if abs(x) < 0
COMPILER_RT_ABI si_int __absvsi2(si_int a) {
const int N = (int)(sizeof(si_int) * CHAR_BIT);
if (a == ((si_int)((su_int)1 << (N - 1))))
compilerrt_abort();
const si_int t = a >> (N - 1);
return (a ^ t) - t;
}
//===-- absvti2.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 __absvti2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: absolute value
// Effects: aborts if abs(x) < 0
COMPILER_RT_ABI ti_int __absvti2(ti_int a) {
const int N = (int)(sizeof(ti_int) * CHAR_BIT);
if (a == (ti_int)((tu_int)1 << (N - 1)))
compilerrt_abort();
const ti_int s = a >> (N - 1);
return (a ^ s) - s;
}
#endif // CRT_HAS_128BIT
//===-- addvdi3.c - Implement __addvdi3 -----------------------------------===//
//
// 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 __addvdi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a + b
// Effects: aborts if a + b overflows
COMPILER_RT_ABI di_int __addvdi3(di_int a, di_int b) {
di_int s = (du_int)a + (du_int)b;
if (b >= 0) {
if (s < a)
compilerrt_abort();
} else {
if (s >= a)
compilerrt_abort();
}
return s;
}
//===-- addvsi3.c - Implement __addvsi3 -----------------------------------===//
//
// 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 __addvsi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a + b
// Effects: aborts if a + b overflows
COMPILER_RT_ABI si_int __addvsi3(si_int a, si_int b) {
si_int s = (su_int)a + (su_int)b;
if (b >= 0) {
if (s < a)
compilerrt_abort();
} else {
if (s >= a)
compilerrt_abort();
}
return s;
}
//===-- addvti3.c - Implement __addvti3 -----------------------------------===//
//
// 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 __addvti3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: a + b
// Effects: aborts if a + b overflows
COMPILER_RT_ABI ti_int __addvti3(ti_int a, ti_int b) {
ti_int s = (tu_int)a + (tu_int)b;
if (b >= 0) {
if (s < a)
compilerrt_abort();
} else {
if (s >= a)
compilerrt_abort();
}
return s;
}
#endif // CRT_HAS_128BIT
// ====-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
#if defined(__ARM_EABI__)
COMPILER_RT_ALIAS(__ashldi3, __aeabi_llsl)
#endif
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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;
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
#if defined(__ARM_EABI__)
COMPILER_RT_ALIAS(__ashrdi3, __aeabi_lasr)
#endif
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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;
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
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 - 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.
//
//===----------------------------------------------------------------------===//
COMPILER_RT_ABI uint32_t __bswapsi2(uint32_t u) {
return ((((u)&0xff000000) >> 24) |
(((u)&0x00ff0000) >> 8) |
(((u)&0x0000ff00) << 8) |
(((u)&0x000000ff) << 24));
}
//===-- 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __clzdi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: the number of leading 0-bits
#if !defined(__clang__) && \
((defined(__sparc__) && defined(__arch64__)) || defined(__mips64) || \
(defined(__riscv) && __SIZEOF_POINTER__ >= 8))
// On 64-bit architectures with neither a native clz instruction nor a native
// ctz instruction, gcc resolves __builtin_clz to __clzdi2 rather than
// __clzsi2, leading to infinite recursion.
#ifdef __builtin_clz
#undef __builtin_clz
#endif
#define __builtin_clz(a) __clzsi2(a)
extern int __clzsi2(si_int);
#endif
// 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)));
}
#ifdef __builtin_clz
#undef __builtin_clz
#endif
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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));
}
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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)));
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
#ifdef __ARM_EABI__
// Returns: if (a < b) returns -1
// if (a == b) returns 0
// if (a > b) returns 1
COMPILER_RT_ABI si_int __aeabi_lcmp(di_int a, di_int b) {
return __cmpdi2(a, b) - 1;
}
#endif
//===-- cmpti2.c - Implement __cmpti2 -------------------------------------===//
//
// 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 __cmpti2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: if (a < b) returns 0
// if (a == b) returns 1
// if (a > b) returns 2
COMPILER_RT_ABI si_int __cmpti2(ti_int a, ti_int b) {
twords x;
x.all = a;
twords 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;
}
#endif // CRT_HAS_128BIT
//===-- 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __ctzdi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: the number of trailing 0-bits
#if !defined(__clang__) && \
((defined(__sparc__) && defined(__arch64__)) || defined(__mips64) || \
(defined(__riscv) && __SIZEOF_POINTER__ >= 8))
// On 64-bit architectures with neither a native clz instruction nor a native
// ctz instruction, gcc resolves __builtin_ctz to __ctzdi2 rather than
// __ctzsi2, leading to infinite recursion.
#ifdef __builtin_ctz
#undef __builtin_ctz
#endif
#define __builtin_ctz(a) __ctzsi2(a)
extern int __ctzsi2(si_int);
#endif
// 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)));
}
#ifdef __builtin_ctz
#undef __builtin_ctz
#endif
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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));
}
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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)));
}
#endif // CRT_HAS_128BIT
//===-- 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __divdi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a / b
COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b) {
const int N = (int)(sizeof(di_int) * CHAR_BIT) - 1;
di_int s_a = a >> N; // s_a = a < 0 ? -1 : 0
di_int s_b = b >> N; // s_b = b < 0 ? -1 : 0
du_int a_u = (du_int)(a ^ s_a) + (-s_a); // negate if s_a == -1
du_int b_u = (du_int)(b ^ s_b) + (-s_b); // negate if s_b == -1
s_a ^= s_b; // sign of quotient
return (__udivmoddi4(a_u, b_u, (du_int *)0) ^ s_a) + (-s_a); // negate if s_a == -1
}
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
//===-- divmodsi4.c - Implement __divmodsi4
//--------------------------------===//
//
// 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 __divmodsi4 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a / b, *rem = a % b
COMPILER_RT_ABI si_int __divmodsi4(si_int a, si_int b, si_int *rem) {
const int bits_in_word_m1 = (int)(sizeof(si_int) * CHAR_BIT) - 1;
si_int s_a = a >> bits_in_word_m1; // s_a = a < 0 ? -1 : 0
si_int s_b = b >> bits_in_word_m1; // s_b = b < 0 ? -1 : 0
a = (su_int)(a ^ s_a) - s_a; // negate if s_a == -1
b = (su_int)(b ^ s_b) - s_b; // negate if s_b == -1
s_b ^= s_a; // sign of quotient
su_int r;
si_int q = (__udivmodsi4(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;
}
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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;
}
#endif // CRT_HAS_128BIT
//===-- divsi3.c - Implement __divsi3 -------------------------------------===//
//
// 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __divsi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a / b
// On CPUs without unsigned hardware division support,
// this calls __udivsi3 (notice the cast to su_int).
// On CPUs with unsigned hardware division support,
// this uses the unsigned division instruction.
COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b) {
const int N = (int)(sizeof(si_int) * CHAR_BIT) - 1;
si_int s_a = a >> N; // s_a = a < 0 ? -1 : 0
si_int s_b = b >> N; // s_b = b < 0 ? -1 : 0
su_int a_u = (su_int)(a ^ s_a) + (-s_a); // negate if s_a == -1
su_int b_u = (su_int)(b ^ s_b) + (-s_b); // negate if s_b == -1
s_a ^= s_b; // sign of quotient
return (((su_int)a_u / (su_int)b_u) ^ s_a) + (-s_a); // negate if s_a == -1
}
#if defined(__ARM_EABI__)
COMPILER_RT_ALIAS(__divsi3, __aeabi_idiv)
#endif
//===-- 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __divti3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: a / b
COMPILER_RT_ABI ti_int __divti3(ti_int a, ti_int b) {
const int N = (int)(sizeof(ti_int) * CHAR_BIT) - 1;
ti_int s_a = a >> N; // s_a = a < 0 ? -1 : 0
ti_int s_b = b >> N; // s_b = b < 0 ? -1 : 0
tu_int a_u = (tu_int)(a ^ s_a) + (-s_a); // negate if s_a == -1
tu_int b_u = (tu_int)(b ^ s_b) + (-s_b); // negate if s_b == -1
s_a ^= s_b; // sign of quotient
return (__udivmodti4(a_u, b_u, (tu_int *)0) ^ s_a) + (-s_a); // negate if s_a == -1
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
//===-- ffssi2.c - Implement __ffssi2 -------------------------------------===//
//
// 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 __ffssi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// 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 __ffssi2(si_int a) {
if (a == 0) {
return 0;
}
return ctzsi(a) + 1;
}
//===-- ffsti2.c - Implement __ffsti2 -------------------------------------===//
//
// 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 __ffsti2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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 __ffsti2(ti_int a) {
twords x;
x.all = a;
if (x.s.low == 0) {
if (x.s.high == 0)
return 0;
return __builtin_ctzll(x.s.high) + (1 + sizeof(di_int) * CHAR_BIT);
}
return __builtin_ctzll(x.s.low) + 1;
}
#endif // CRT_HAS_128BIT
//===-- int_util.c - Implement internal utilities -------------------------===//
//
// 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
//
// 2024/01/21 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
// NOTE: The definitions in this file are declared weak because we clients to be
// able to arbitrarily package individual functions into separate .a files. If
// we did not declare these weak, some link situations might end up seeing
// duplicate strong definitions of the same symbol.
//
// We can't use this solution for kernel use (which may not support weak), but
// currently expect that when built for kernel use all the functionality is
// packaged into a single library.
__attribute__((weak))
__attribute__((visibility("hidden")))
void __compilerrt_abort_impl(const char *file, int line, const char *function) {
(void)file; (void)line; (void)function;
#if !__STDC_HOSTED__
// Avoid depending on libc when compiling with -ffreestanding.
__builtin_trap();
#else
__builtin_abort();
#endif
}
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
#if defined(__ARM_EABI__)
COMPILER_RT_ALIAS(__lshrdi3, __aeabi_llsr)
#endif
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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;
}
#endif // CRT_HAS_128BIT
//===-- 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __moddi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a % b
COMPILER_RT_ABI di_int __moddi3(di_int a, di_int b) {
const int N = (int)(sizeof(di_int) * CHAR_BIT) - 1;
di_int s = b >> N; // s = b < 0 ? -1 : 0
du_int b_u = (du_int)(b ^ s) + (-s); // negate if s == -1
s = a >> N; // s = a < 0 ? -1 : 0
du_int a_u = (du_int)(a ^ s) + (-s); // negate if s == -1
du_int res;
__udivmoddi4(a_u, b_u, &res);
return (res ^ s) + (-s); // negate if s == -1
}
//===-- modsi3.c - Implement __modsi3 -------------------------------------===//
//
// 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 __modsi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a % b
COMPILER_RT_ABI si_int __modsi3(si_int a, si_int b) {
return a - __divsi3(a, b) * b;
}
//===-- 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __modti3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: a % b
COMPILER_RT_ABI ti_int __modti3(ti_int a, ti_int b) {
const int N = (int)(sizeof(ti_int) * CHAR_BIT) - 1;
ti_int s = b >> N; // s = b < 0 ? -1 : 0
tu_int b_u = (tu_int)(b ^ s) + (-s); // negate if s == -1
s = a >> N; // s = a < 0 ? -1 : 0
tu_int a_u = (tu_int)(a ^ s) + (-s); // negate if s == -1
tu_int res;
__udivmodti4(a_u, b_u, &res);
return (res ^ s) + (-s); // negate if s == -1
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
#if defined(__ARM_EABI__)
COMPILER_RT_ALIAS(__muldi3, __aeabi_lmul)
#endif
//===-- mulodi4.c - Implement __mulodi4 -----------------------------------===//
//
// 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __mulodi4 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a * b
// Effects: sets *overflow to 1 if a * b overflows
COMPILER_RT_ABI di_int __mulodi4(di_int a, di_int b, int *overflow) {
const int N = (int)(sizeof(di_int) * CHAR_BIT);
const di_int MIN = (di_int)((du_int)1 << (N - 1));
const di_int MAX = ~MIN;
*overflow = 0;
di_int result = (du_int)a * b;
if (a == MIN) {
if (b != 0 && b != 1)
*overflow = 1;
return result;
}
if (b == MIN) {
if (a != 0 && a != 1)
*overflow = 1;
return result;
}
di_int sa = a >> (N - 1);
di_int abs_a = (a ^ sa) - sa;
di_int sb = b >> (N - 1);
di_int abs_b = (b ^ sb) - sb;
if (abs_a < 2 || abs_b < 2)
return result;
if (sa == sb) {
if (abs_a > MAX / abs_b)
*overflow = 1;
} else {
if (abs_a > MIN / -abs_b)
*overflow = 1;
}
return result;
}
//===-- mulosi4.c - Implement __mulosi4 -----------------------------------===//
//
// 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __mulosi4 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a * b
// Effects: sets *overflow to 1 if a * b overflows
COMPILER_RT_ABI si_int __mulosi4(si_int a, si_int b, int *overflow) {
const int N = (int)(sizeof(si_int) * CHAR_BIT);
const si_int MIN = (si_int)((su_int)1 << (N - 1));
const si_int MAX = ~MIN;
*overflow = 0;
si_int result = (su_int)a * b;
if (a == MIN) {
if (b != 0 && b != 1)
*overflow = 1;
return result;
}
if (b == MIN) {
if (a != 0 && a != 1)
*overflow = 1;
return result;
}
si_int sa = a >> (N - 1);
si_int abs_a = (a ^ sa) - sa;
si_int sb = b >> (N - 1);
si_int abs_b = (b ^ sb) - sb;
if (abs_a < 2 || abs_b < 2)
return result;
if (sa == sb) {
if (abs_a > MAX / abs_b)
*overflow = 1;
} else {
if (abs_a > MIN / -abs_b)
*overflow = 1;
}
return result;
}
//===-- muloti4.c - Implement __muloti4 -----------------------------------===//
//
// 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __muloti4 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: a * b
// Effects: sets *overflow to 1 if a * b overflows
COMPILER_RT_ABI ti_int __muloti4(ti_int a, ti_int b, int *overflow) {
const int N = (int)(sizeof(ti_int) * CHAR_BIT);
const ti_int MIN = (ti_int)((tu_int)1 << (N - 1));
const ti_int MAX = ~MIN;
*overflow = 0;
ti_int result = (tu_int)a * b;
if (a == MIN) {
if (b != 0 && b != 1)
*overflow = 1;
return result;
}
if (b == MIN) {
if (a != 0 && a != 1)
*overflow = 1;
return result;
}
ti_int sa = a >> (N - 1);
ti_int abs_a = (a ^ sa) - sa;
ti_int sb = b >> (N - 1);
ti_int abs_b = (b ^ sb) - sb;
if (abs_a < 2 || abs_b < 2)
return result;
if (sa == sb) {
if (abs_a > MAX / abs_b)
*overflow = 1;
} else {
if (abs_a > MIN / -abs_b)
*overflow = 1;
}
return result;
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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;
}
#endif // CRT_HAS_128BIT
//===-- mulvdi3.c - Implement __mulvdi3 -----------------------------------===//
//
// 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __mulvdi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a * b
// Effects: aborts if a * b overflows
COMPILER_RT_ABI di_int __mulvdi3(di_int a, di_int b) {
const int N = (int)(sizeof(di_int) * CHAR_BIT);
const di_int MIN = (di_int)((du_int)1 << (N - 1));
const di_int MAX = ~MIN;
if (a == MIN) {
if (b == 0 || b == 1)
return a * b;
compilerrt_abort();
}
if (b == MIN) {
if (a == 0 || a == 1)
return a * b;
compilerrt_abort();
}
di_int sa = a >> (N - 1);
di_int abs_a = (a ^ sa) - sa;
di_int sb = b >> (N - 1);
di_int abs_b = (b ^ sb) - sb;
if (abs_a < 2 || abs_b < 2)
return a * b;
if (sa == sb) {
if (abs_a > MAX / abs_b)
compilerrt_abort();
} else {
if (abs_a > MIN / -abs_b)
compilerrt_abort();
}
return a * b;
}
//===-- mulvsi3.c - Implement __mulvsi3 -----------------------------------===//
//
// 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __mulvsi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a * b
// Effects: aborts if a * b overflows
COMPILER_RT_ABI si_int __mulvsi3(si_int a, si_int b) {
const int N = (int)(sizeof(si_int) * CHAR_BIT);
const si_int MIN = (si_int)((su_int)1 << (N - 1));
const si_int MAX = ~MIN;
if (a == MIN) {
if (b == 0 || b == 1)
return a * b;
compilerrt_abort();
}
if (b == MIN) {
if (a == 0 || a == 1)
return a * b;
compilerrt_abort();
}
si_int sa = a >> (N - 1);
si_int abs_a = (a ^ sa) - sa;
si_int sb = b >> (N - 1);
si_int abs_b = (b ^ sb) - sb;
if (abs_a < 2 || abs_b < 2)
return a * b;
if (sa == sb) {
if (abs_a > MAX / abs_b)
compilerrt_abort();
} else {
if (abs_a > MIN / -abs_b)
compilerrt_abort();
}
return a * b;
}
//===-- mulvti3.c - Implement __mulvti3 -----------------------------------===//
//
// 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __mulvti3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: a * b
// Effects: aborts if a * b overflows
COMPILER_RT_ABI ti_int __mulvti3(ti_int a, ti_int b) {
const int N = (int)(sizeof(ti_int) * CHAR_BIT);
const ti_int MIN = (ti_int)((tu_int)1 << (N - 1));
const ti_int MAX = ~MIN;
if (a == MIN) {
if (b == 0 || b == 1)
return a * b;
compilerrt_abort();
}
if (b == MIN) {
if (a == 0 || a == 1)
return a * b;
compilerrt_abort();
}
ti_int sa = a >> (N - 1);
ti_int abs_a = (a ^ sa) - sa;
ti_int sb = b >> (N - 1);
ti_int abs_b = (b ^ sb) - sb;
if (abs_a < 2 || abs_b < 2)
return a * b;
if (sa == sb) {
if (abs_a > MAX / abs_b)
compilerrt_abort();
} else {
if (abs_a > MIN / -abs_b)
compilerrt_abort();
}
return a * b;
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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;
}
#endif // CRT_HAS_128BIT
//===-- negvdi2.c - Implement __negvdi2 -----------------------------------===//
//
// 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 __negvdi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: -a
// Effects: aborts if -a overflows
COMPILER_RT_ABI di_int __negvdi2(di_int a) {
const di_int MIN =
(di_int)((du_int)1 << ((int)(sizeof(di_int) * CHAR_BIT) - 1));
if (a == MIN)
compilerrt_abort();
return -a;
}
//===-- negvsi2.c - Implement __negvsi2 -----------------------------------===//
//
// 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 __negvsi2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: -a
// Effects: aborts if -a overflows
COMPILER_RT_ABI si_int __negvsi2(si_int a) {
const si_int MIN =
(si_int)((su_int)1 << ((int)(sizeof(si_int) * CHAR_BIT) - 1));
if (a == MIN)
compilerrt_abort();
return -a;
}
//===-- negvti2.c - Implement __negvti2 -----------------------------------===//
//
// 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 __negvti2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: -a
// Effects: aborts if -a overflows
COMPILER_RT_ABI ti_int __negvti2(ti_int a) {
const ti_int MIN = (tu_int)1 << ((int)(sizeof(ti_int) * CHAR_BIT) - 1);
if (a == MIN)
compilerrt_abort();
return -a;
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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 - 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
//===-- parityti2.c - Implement __parityti2 -------------------------------===//
//
// 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 __parityti2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: 1 if number of bits is odd else returns 0
COMPILER_RT_ABI int __parityti2(ti_int a) {
twords x;
dwords x2;
x.all = a;
x2.all = x.s.high ^ x.s.low;
su_int x3 = x2.s.high ^ x2.s.low;
x3 ^= x3 >> 16;
x3 ^= x3 >> 8;
x3 ^= x3 >> 4;
return (0x6996 >> (x3 & 0xF)) & 1;
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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 - 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.
//
//===----------------------------------------------------------------------===//
// 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)
}
//===-- popcountti2.c - Implement __popcountti2
//----------------------------===//
//
// 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 __popcountti2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: count of 1 bits
COMPILER_RT_ABI int __popcountti2(ti_int a) {
tu_int x3 = (tu_int)a;
x3 = x3 - ((x3 >> 1) &
(((tu_int)0x5555555555555555uLL << 64) | 0x5555555555555555uLL));
// Every 2 bits holds the sum of every pair of bits (64)
x3 = ((x3 >> 2) &
(((tu_int)0x3333333333333333uLL << 64) | 0x3333333333333333uLL)) +
(x3 & (((tu_int)0x3333333333333333uLL << 64) | 0x3333333333333333uLL));
// Every 4 bits holds the sum of every 4-set of bits (3 significant bits) (32)
x3 = (x3 + (x3 >> 4)) &
(((tu_int)0x0F0F0F0F0F0F0F0FuLL << 64) | 0x0F0F0F0F0F0F0F0FuLL);
// Every 8 bits holds the sum of every 8-set of bits (4 significant bits) (16)
du_int x2 = (du_int)(x3 + (x3 >> 64));
// Every 8 bits holds the sum of every 8-set of bits (5 significant bits) (8)
su_int x = (su_int)(x2 + (x2 >> 32));
// Every 8 bits holds the sum of every 8-set of bits (6 significant bits) (4)
x = x + (x >> 16);
// Every 8 bits holds the sum of every 8-set of bits (7 significant bits) (2)
//
// Upper 16 bits are garbage
return (x + (x >> 8)) & 0xFF; // (8 significant bits)
}
#endif // CRT_HAS_128BIT
//===-- subvdi3.c - Implement __subvdi3 -----------------------------------===//
//
// 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 __subvdi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a - b
// Effects: aborts if a - b overflows
COMPILER_RT_ABI di_int __subvdi3(di_int a, di_int b) {
di_int s = (du_int)a - (du_int)b;
if (b >= 0) {
if (s > a)
compilerrt_abort();
} else {
if (s <= a)
compilerrt_abort();
}
return s;
}
//===-- subvsi3.c - Implement __subvsi3 -----------------------------------===//
//
// 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 __subvsi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a - b
// Effects: aborts if a - b overflows
COMPILER_RT_ABI si_int __subvsi3(si_int a, si_int b) {
si_int s = (su_int)a - (su_int)b;
if (b >= 0) {
if (s > a)
compilerrt_abort();
} else {
if (s <= a)
compilerrt_abort();
}
return s;
}
//===-- subvti3.c - Implement __subvti3 -----------------------------------===//
//
// 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 __subvti3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: a - b
// Effects: aborts if a - b overflows
COMPILER_RT_ABI ti_int __subvti3(ti_int a, ti_int b) {
ti_int s = (tu_int)a - (tu_int)b;
if (b >= 0) {
if (s > a)
compilerrt_abort();
} else {
if (s <= a)
compilerrt_abort();
}
return s;
}
#endif // CRT_HAS_128BIT
//===-- 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.
//
//===----------------------------------------------------------------------===//
// 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;
}
#ifdef __ARM_EABI__
// Returns: if (a < b) returns -1
// if (a == b) returns 0
// if (a > b) returns 1
COMPILER_RT_ABI si_int __aeabi_ulcmp(di_int a, di_int b) {
return __ucmpdi2(a, b) - 1;
}
#endif
//===-- ucmpti2.c - Implement __ucmpti2 -----------------------------------===//
//
// 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 __ucmpti2 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: if (a < b) returns 0
// if (a == b) returns 1
// if (a > b) returns 2
COMPILER_RT_ABI si_int __ucmpti2(tu_int a, tu_int b) {
utwords x;
x.all = a;
utwords 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;
}
#endif // CRT_HAS_128BIT
//===-- 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __udivdi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a / b
#ifdef clz
#undef clz
#endif
#define clz(a) (sizeof(a) == sizeof(unsigned long long) ? __builtin_clzll(a) : clzsi(a))
// Adapted from Figure 3-40 of The PowerPC Compiler Writer's Guide
COMPILER_RT_ABI du_int __udivdi3(du_int n, du_int d) {
const unsigned N = sizeof(du_int) * CHAR_BIT;
// d == 0 cases are unspecified.
unsigned sr = (d ? clz(d) : N) - (n ? clz(n) : N);
// 0 <= sr <= N - 1 or sr is very large.
if (sr > N - 1) // n < d
return 0;
if (sr == N - 1) // d == 1
return n;
++sr;
// 1 <= sr <= N - 1. Shifts do not trigger UB.
du_int r = n >> sr;
n <<= N - sr;
du_int carry = 0;
for (; sr > 0; --sr) {
r = (r << 1) | (n >> (N - 1));
n = (n << 1) | carry;
// Branch-less version of:
// carry = 0;
// if (r >= d) r -= d, carry = 1;
const di_int s = (di_int)(d - r - 1) >> (N - 1);
carry = s & 1;
r -= d & s;
}
n = (n << 1) | carry;
return n;
}
#undef clz
//===-- 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
//
// 2024/01/21 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __udivmoddi4 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// 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;
}
//===-- udivmodsi4.c - Implement __udivmodsi4 -----------------------------===//
//
// 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 __udivmodsi4 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a / b, *rem = a % b
COMPILER_RT_ABI su_int __udivmodsi4(su_int a, su_int b, su_int *rem) {
si_int d = __udivsi3(a, b);
*rem = a - (d * b);
return d;
}
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// 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) {
#if defined(__x86_64__)
du_int result;
__asm__("divq %[v]"
: "=a"(result), "=d"(*r)
: [ v ] "r"(v), "a"(u0), "d"(u1));
return result;
#else
return udiv128by64to64default(u1, u0, v, r);
#endif
}
// 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;
}
#endif // CRT_HAS_128BIT
//===-- udivsi3.c - Implement __udivsi3 -----------------------------------===//
//
// 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __udivsi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a / b
#ifdef clz
#undef clz
#endif
#define clz(a) (sizeof(a) == sizeof(unsigned long long) ? __builtin_clzll(a) : clzsi(a))
// Adapted from Figure 3-40 of The PowerPC Compiler Writer's Guide
COMPILER_RT_ABI su_int __udivsi3(su_int n, su_int d) {
const unsigned N = sizeof(su_int) * CHAR_BIT;
// d == 0 cases are unspecified.
unsigned sr = (d ? clz(d) : N) - (n ? clz(n) : N);
// 0 <= sr <= N - 1 or sr is very large.
if (sr > N - 1) // n < d
return 0;
if (sr == N - 1) // d == 1
return n;
++sr;
// 1 <= sr <= N - 1. Shifts do not trigger UB.
su_int r = n >> sr;
n <<= N - sr;
su_int carry = 0;
for (; sr > 0; --sr) {
r = (r << 1) | (n >> (N - 1));
n = (n << 1) | carry;
// Branch-less version of:
// carry = 0;
// if (r >= d) r -= d, carry = 1;
const si_int s = (si_int)(d - r - 1) >> (N - 1);
carry = s & 1;
r -= d & s;
}
n = (n << 1) | carry;
return n;
}
#undef clz
#if defined(__ARM_EABI__)
COMPILER_RT_ALIAS(__udivsi3, __aeabi_uidiv)
#endif
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: a / b
COMPILER_RT_ABI tu_int __udivti3(tu_int a, tu_int b) {
return __udivmodti4(a, b, 0);
}
#endif // CRT_HAS_128BIT
//===-- 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __umoddi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a % b
#ifdef clz
#undef clz
#endif
#define clz(a) (sizeof(a) == sizeof(unsigned long long) ? __builtin_clzll(a) : clzsi(a))
// Mostly identical to __udivdi3 but the return values are different.
COMPILER_RT_ABI du_int __umoddi3(du_int n, du_int d) {
const unsigned N = sizeof(du_int) * CHAR_BIT;
// d == 0 cases are unspecified.
unsigned sr = (d ? clz(d) : N) - (n ? clz(n) : N);
// 0 <= sr <= N - 1 or sr is very large.
if (sr > N - 1) // n < d
return n;
if (sr == N - 1) // d == 1
return 0;
++sr;
// 1 <= sr <= N - 1. Shifts do not trigger UB.
du_int r = n >> sr;
n <<= N - sr;
du_int carry = 0;
for (; sr > 0; --sr) {
r = (r << 1) | (n >> (N - 1));
n = (n << 1) | carry;
// Branch-less version of:
// carry = 0;
// if (r >= d) r -= d, carry = 1;
const di_int s = (di_int)(d - r - 1) >> (N - 1);
carry = s & 1;
r -= d & s;
}
return r;
}
#undef clz
//===-- umodsi3.c - Implement __umodsi3 -----------------------------------===//
//
// 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
//
// 2024/08/10 - Modified by mintsuki for use inside cc-runtime
//
//===----------------------------------------------------------------------===//
//
// This file implements __umodsi3 for the compiler_rt library.
//
//===----------------------------------------------------------------------===//
// Returns: a % b
#ifdef clz
#undef clz
#endif
#define clz(a) (sizeof(a) == sizeof(unsigned long long) ? __builtin_clzll(a) : clzsi(a))
// Mostly identical to __udivsi3 but the return values are different.
COMPILER_RT_ABI su_int __umodsi3(su_int n, su_int d) {
const unsigned N = sizeof(su_int) * CHAR_BIT;
// d == 0 cases are unspecified.
unsigned sr = (d ? clz(d) : N) - (n ? clz(n) : N);
// 0 <= sr <= N - 1 or sr is very large.
if (sr > N - 1) // n < d
return n;
if (sr == N - 1) // d == 1
return 0;
++sr;
// 1 <= sr <= N - 1. Shifts do not trigger UB.
su_int r = n >> sr;
n <<= N - sr;
su_int carry = 0;
for (; sr > 0; --sr) {
r = (r << 1) | (n >> (N - 1));
n = (n << 1) | carry;
// Branch-less version of:
// carry = 0;
// if (r >= d) r -= d, carry = 1;
const si_int s = (si_int)(d - r - 1) >> (N - 1);
carry = s & 1;
r -= d & s;
}
return r;
}
#undef clz
//===-- 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.
//
//===----------------------------------------------------------------------===//
#ifdef CRT_HAS_128BIT
// Returns: a % b
COMPILER_RT_ABI tu_int __umodti3(tu_int a, tu_int b) {
tu_int r;
__udivmodti4(a, b, &r);
return r;
}
#endif // CRT_HAS_128BIT