LLVM Minix changes
- import libcxx - reduce targets to the one when compiled as a tools Change-Id: Iabb8427f80ff8e89463559a28bcb8b4f2bdbc496
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
This file is a partial list of people who have contributed to the LLVM/CompilerRT
|
||||
project. If you have contributed a patch or made some other contribution to
|
||||
LLVM/CompilerRT, please submit a patch to this file to add yourself, and it will be
|
||||
done!
|
||||
|
||||
The list is sorted by surname and formatted to allow easy grepping and
|
||||
beautification by scripts. The fields are: name (N), email (E), web-address
|
||||
(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
|
||||
(S).
|
||||
|
||||
N: Craig van Vliet
|
||||
E: cvanvliet@auroraux.org
|
||||
W: http://www.auroraux.org
|
||||
D: Code style and Readability fixes.
|
||||
|
||||
N: Edward O'Callaghan
|
||||
E: eocallaghan@auroraux.org
|
||||
W: http://www.auroraux.org
|
||||
D: CMake'ify Compiler-RT build system
|
||||
D: Maintain Solaris & AuroraUX ports of Compiler-RT
|
||||
|
||||
N: Howard Hinnant
|
||||
E: hhinnant@apple.com
|
||||
D: Architect and primary author of compiler-rt
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
==============================================================================
|
||||
compiler_rt License
|
||||
==============================================================================
|
||||
|
||||
The compiler_rt library is dual licensed under both the University of Illinois
|
||||
"BSD-Like" license and the MIT license. As a user of this code you may choose
|
||||
to use it under either license. As a contributor, you agree to allow your code
|
||||
to be used under both.
|
||||
|
||||
Full text of the relevant licenses is included below.
|
||||
|
||||
==============================================================================
|
||||
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
||||
LLVM Team
|
||||
|
||||
University of Illinois at Urbana-Champaign
|
||||
|
||||
http://llvm.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal with
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimers in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the LLVM Team, University of Illinois at
|
||||
Urbana-Champaign, nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this Software without specific
|
||||
prior written permission.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
|
||||
Copyright (c) 2009-2013 by the contributors listed in CREDITS.TXT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
Copyrights and Licenses for Third Party Software Distributed with LLVM:
|
||||
==============================================================================
|
||||
The LLVM software contains code written by third parties. Such software will
|
||||
have its own individual LICENSE.TXT file in the directory in which it appears.
|
||||
This file will describe the copyrights, license, and restrictions which apply
|
||||
to that code.
|
||||
|
||||
The disclaimer of warranty in the University of Illinois Open Source License
|
||||
applies to all code in the LLVM Distribution, and nothing in any of the
|
||||
other licenses gives permission to use the names of the LLVM Team or the
|
||||
University of Illinois to endorse or promote products derived from this
|
||||
Software.
|
||||
|
||||
The following pieces of software have additional or alternate copyrights,
|
||||
licenses, and/or restrictions:
|
||||
|
||||
Program Directory
|
||||
------- ---------
|
||||
mach_override lib/interception/mach_override
|
||||
+343
@@ -0,0 +1,343 @@
|
||||
Compiler-RT
|
||||
================================
|
||||
|
||||
This directory and its subdirectories contain source code for the compiler
|
||||
support routines.
|
||||
|
||||
Compiler-RT is open source software. You may freely distribute it under the
|
||||
terms of the license agreement found in LICENSE.txt.
|
||||
|
||||
================================
|
||||
|
||||
This is a replacement library for libgcc. Each function is contained
|
||||
in its own file. Each function has a corresponding unit test under
|
||||
test/Unit.
|
||||
|
||||
A rudimentary script to test each file is in the file called
|
||||
test/Unit/test.
|
||||
|
||||
Here is the specification for this library:
|
||||
|
||||
http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc
|
||||
|
||||
Here is a synopsis of the contents of this library:
|
||||
|
||||
typedef int si_int;
|
||||
typedef unsigned su_int;
|
||||
|
||||
typedef long long di_int;
|
||||
typedef unsigned long long du_int;
|
||||
|
||||
// Integral bit manipulation
|
||||
|
||||
di_int __ashldi3(di_int a, si_int b); // a << b
|
||||
ti_int __ashlti3(ti_int a, si_int b); // a << b
|
||||
|
||||
di_int __ashrdi3(di_int a, si_int b); // a >> b arithmetic (sign fill)
|
||||
ti_int __ashrti3(ti_int a, si_int b); // a >> b arithmetic (sign fill)
|
||||
di_int __lshrdi3(di_int a, si_int b); // a >> b logical (zero fill)
|
||||
ti_int __lshrti3(ti_int a, si_int b); // a >> b logical (zero fill)
|
||||
|
||||
si_int __clzsi2(si_int a); // count leading zeros
|
||||
si_int __clzdi2(di_int a); // count leading zeros
|
||||
si_int __clzti2(ti_int a); // count leading zeros
|
||||
si_int __ctzsi2(si_int a); // count trailing zeros
|
||||
si_int __ctzdi2(di_int a); // count trailing zeros
|
||||
si_int __ctzti2(ti_int a); // count trailing zeros
|
||||
|
||||
si_int __ffsdi2(di_int a); // find least significant 1 bit
|
||||
si_int __ffsti2(ti_int a); // find least significant 1 bit
|
||||
|
||||
si_int __paritysi2(si_int a); // bit parity
|
||||
si_int __paritydi2(di_int a); // bit parity
|
||||
si_int __parityti2(ti_int a); // bit parity
|
||||
|
||||
si_int __popcountsi2(si_int a); // bit population
|
||||
si_int __popcountdi2(di_int a); // bit population
|
||||
si_int __popcountti2(ti_int a); // bit population
|
||||
|
||||
uint32_t __bswapsi2(uint32_t a); // a byteswapped, arm only
|
||||
uint64_t __bswapdi2(uint64_t a); // a byteswapped, arm only
|
||||
|
||||
// Integral arithmetic
|
||||
|
||||
di_int __negdi2 (di_int a); // -a
|
||||
ti_int __negti2 (ti_int a); // -a
|
||||
di_int __muldi3 (di_int a, di_int b); // a * b
|
||||
ti_int __multi3 (ti_int a, ti_int b); // a * b
|
||||
si_int __divsi3 (si_int a, si_int b); // a / b signed
|
||||
di_int __divdi3 (di_int a, di_int b); // a / b signed
|
||||
ti_int __divti3 (ti_int a, ti_int b); // a / b signed
|
||||
su_int __udivsi3 (su_int n, su_int d); // a / b unsigned
|
||||
du_int __udivdi3 (du_int a, du_int b); // a / b unsigned
|
||||
tu_int __udivti3 (tu_int a, tu_int b); // a / b unsigned
|
||||
si_int __modsi3 (si_int a, si_int b); // a % b signed
|
||||
di_int __moddi3 (di_int a, di_int b); // a % b signed
|
||||
ti_int __modti3 (ti_int a, ti_int b); // a % b signed
|
||||
su_int __umodsi3 (su_int a, su_int b); // a % b unsigned
|
||||
du_int __umoddi3 (du_int a, du_int b); // a % b unsigned
|
||||
tu_int __umodti3 (tu_int a, tu_int b); // a % b unsigned
|
||||
du_int __udivmoddi4(du_int a, du_int b, du_int* rem); // a / b, *rem = a % b unsigned
|
||||
tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); // a / b, *rem = a % b unsigned
|
||||
su_int __udivmodsi4(su_int a, su_int b, su_int* rem); // a / b, *rem = a % b unsigned
|
||||
si_int __divmodsi4(si_int a, si_int b, si_int* rem); // a / b, *rem = a % b signed
|
||||
|
||||
|
||||
|
||||
// Integral arithmetic with trapping overflow
|
||||
|
||||
si_int __absvsi2(si_int a); // abs(a)
|
||||
di_int __absvdi2(di_int a); // abs(a)
|
||||
ti_int __absvti2(ti_int a); // abs(a)
|
||||
|
||||
si_int __negvsi2(si_int a); // -a
|
||||
di_int __negvdi2(di_int a); // -a
|
||||
ti_int __negvti2(ti_int a); // -a
|
||||
|
||||
si_int __addvsi3(si_int a, si_int b); // a + b
|
||||
di_int __addvdi3(di_int a, di_int b); // a + b
|
||||
ti_int __addvti3(ti_int a, ti_int b); // a + b
|
||||
|
||||
si_int __subvsi3(si_int a, si_int b); // a - b
|
||||
di_int __subvdi3(di_int a, di_int b); // a - b
|
||||
ti_int __subvti3(ti_int a, ti_int b); // a - b
|
||||
|
||||
si_int __mulvsi3(si_int a, si_int b); // a * b
|
||||
di_int __mulvdi3(di_int a, di_int b); // a * b
|
||||
ti_int __mulvti3(ti_int a, ti_int b); // a * b
|
||||
|
||||
|
||||
// Integral arithmetic which returns if overflow
|
||||
|
||||
si_int __mulosi4(si_int a, si_int b, int* overflow); // a * b, overflow set to one if result not in signed range
|
||||
di_int __mulodi4(di_int a, di_int b, int* overflow); // a * b, overflow set to one if result not in signed range
|
||||
ti_int __muloti4(ti_int a, ti_int b, int* overflow); // a * b, overflow set to
|
||||
one if result not in signed range
|
||||
|
||||
|
||||
// Integral comparison: a < b -> 0
|
||||
// a == b -> 1
|
||||
// a > b -> 2
|
||||
|
||||
si_int __cmpdi2 (di_int a, di_int b);
|
||||
si_int __cmpti2 (ti_int a, ti_int b);
|
||||
si_int __ucmpdi2(du_int a, du_int b);
|
||||
si_int __ucmpti2(tu_int a, tu_int b);
|
||||
|
||||
// Integral / floating point conversion
|
||||
|
||||
di_int __fixsfdi( float a);
|
||||
di_int __fixdfdi( double a);
|
||||
di_int __fixxfdi(long double a);
|
||||
|
||||
ti_int __fixsfti( float a);
|
||||
ti_int __fixdfti( double a);
|
||||
ti_int __fixxfti(long double a);
|
||||
uint64_t __fixtfdi(long double input); // ppc only, doesn't match documentation
|
||||
|
||||
su_int __fixunssfsi( float a);
|
||||
su_int __fixunsdfsi( double a);
|
||||
su_int __fixunsxfsi(long double a);
|
||||
|
||||
du_int __fixunssfdi( float a);
|
||||
du_int __fixunsdfdi( double a);
|
||||
du_int __fixunsxfdi(long double a);
|
||||
|
||||
tu_int __fixunssfti( float a);
|
||||
tu_int __fixunsdfti( double a);
|
||||
tu_int __fixunsxfti(long double a);
|
||||
uint64_t __fixunstfdi(long double input); // ppc only
|
||||
|
||||
float __floatdisf(di_int a);
|
||||
double __floatdidf(di_int a);
|
||||
long double __floatdixf(di_int a);
|
||||
long double __floatditf(int64_t a); // ppc only
|
||||
|
||||
float __floattisf(ti_int a);
|
||||
double __floattidf(ti_int a);
|
||||
long double __floattixf(ti_int a);
|
||||
|
||||
float __floatundisf(du_int a);
|
||||
double __floatundidf(du_int a);
|
||||
long double __floatundixf(du_int a);
|
||||
long double __floatunditf(uint64_t a); // ppc only
|
||||
|
||||
float __floatuntisf(tu_int a);
|
||||
double __floatuntidf(tu_int a);
|
||||
long double __floatuntixf(tu_int a);
|
||||
|
||||
// Floating point raised to integer power
|
||||
|
||||
float __powisf2( float a, si_int b); // a ^ b
|
||||
double __powidf2( double a, si_int b); // a ^ b
|
||||
long double __powixf2(long double a, si_int b); // a ^ b
|
||||
long double __powitf2(long double a, si_int b); // ppc only, a ^ b
|
||||
|
||||
// Complex arithmetic
|
||||
|
||||
// (a + ib) * (c + id)
|
||||
|
||||
float _Complex __mulsc3( float a, float b, float c, float d);
|
||||
double _Complex __muldc3(double a, double b, double c, double d);
|
||||
long double _Complex __mulxc3(long double a, long double b,
|
||||
long double c, long double d);
|
||||
long double _Complex __multc3(long double a, long double b,
|
||||
long double c, long double d); // ppc only
|
||||
|
||||
// (a + ib) / (c + id)
|
||||
|
||||
float _Complex __divsc3( float a, float b, float c, float d);
|
||||
double _Complex __divdc3(double a, double b, double c, double d);
|
||||
long double _Complex __divxc3(long double a, long double b,
|
||||
long double c, long double d);
|
||||
long double _Complex __divtc3(long double a, long double b,
|
||||
long double c, long double d); // ppc only
|
||||
|
||||
|
||||
// Runtime support
|
||||
|
||||
// __clear_cache() is used to tell process that new instructions have been
|
||||
// written to an address range. Necessary on processors that do not have
|
||||
// a unified instuction and data cache.
|
||||
void __clear_cache(void* start, void* end);
|
||||
|
||||
// __enable_execute_stack() is used with nested functions when a trampoline
|
||||
// function is written onto the stack and that page range needs to be made
|
||||
// executable.
|
||||
void __enable_execute_stack(void* addr);
|
||||
|
||||
// __gcc_personality_v0() is normally only called by the system unwinder.
|
||||
// C code (as opposed to C++) normally does not need a personality function
|
||||
// because there are no catch clauses or destructors to be run. But there
|
||||
// is a C language extension __attribute__((cleanup(func))) which marks local
|
||||
// variables as needing the cleanup function "func" to be run when the
|
||||
// variable goes out of scope. That includes when an exception is thrown,
|
||||
// so a personality handler is needed.
|
||||
_Unwind_Reason_Code __gcc_personality_v0(int version, _Unwind_Action actions,
|
||||
uint64_t exceptionClass, struct _Unwind_Exception* exceptionObject,
|
||||
_Unwind_Context_t context);
|
||||
|
||||
// for use with some implementations of assert() in <assert.h>
|
||||
void __eprintf(const char* format, const char* assertion_expression,
|
||||
const char* line, const char* file);
|
||||
|
||||
|
||||
|
||||
// Power PC specific functions
|
||||
|
||||
// There is no C interface to the saveFP/restFP functions. They are helper
|
||||
// functions called by the prolog and epilog of functions that need to save
|
||||
// a number of non-volatile float point registers.
|
||||
saveFP
|
||||
restFP
|
||||
|
||||
// PowerPC has a standard template for trampoline functions. This function
|
||||
// generates a custom trampoline function with the specific realFunc
|
||||
// and localsPtr values.
|
||||
void __trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,
|
||||
const void* realFunc, void* localsPtr);
|
||||
|
||||
// adds two 128-bit double-double precision values ( x + y )
|
||||
long double __gcc_qadd(long double x, long double y);
|
||||
|
||||
// subtracts two 128-bit double-double precision values ( x - y )
|
||||
long double __gcc_qsub(long double x, long double y);
|
||||
|
||||
// multiples two 128-bit double-double precision values ( x * y )
|
||||
long double __gcc_qmul(long double x, long double y);
|
||||
|
||||
// divides two 128-bit double-double precision values ( x / y )
|
||||
long double __gcc_qdiv(long double a, long double b);
|
||||
|
||||
|
||||
// ARM specific functions
|
||||
|
||||
// There is no C interface to the switch* functions. These helper functions
|
||||
// are only needed by Thumb1 code for efficient switch table generation.
|
||||
switch16
|
||||
switch32
|
||||
switch8
|
||||
switchu8
|
||||
|
||||
// There is no C interface to the *_vfp_d8_d15_regs functions. There are
|
||||
// called in the prolog and epilog of Thumb1 functions. When the C++ ABI use
|
||||
// SJLJ for exceptions, each function with a catch clause or destuctors needs
|
||||
// to save and restore all registers in it prolog and epliog. But there is
|
||||
// no way to access vector and high float registers from thumb1 code, so the
|
||||
// compiler must add call outs to these helper functions in the prolog and
|
||||
// epilog.
|
||||
restore_vfp_d8_d15_regs
|
||||
save_vfp_d8_d15_regs
|
||||
|
||||
|
||||
// Note: long ago ARM processors did not have floating point hardware support.
|
||||
// Floating point was done in software and floating point parameters were
|
||||
// passed in integer registers. When hardware support was added for floating
|
||||
// point, new *vfp functions were added to do the same operations but with
|
||||
// floating point parameters in floating point registers.
|
||||
|
||||
// Undocumented functions
|
||||
|
||||
float __addsf3vfp(float a, float b); // Appears to return a + b
|
||||
double __adddf3vfp(double a, double b); // Appears to return a + b
|
||||
float __divsf3vfp(float a, float b); // Appears to return a / b
|
||||
double __divdf3vfp(double a, double b); // Appears to return a / b
|
||||
int __eqsf2vfp(float a, float b); // Appears to return one
|
||||
// iff a == b and neither is NaN.
|
||||
int __eqdf2vfp(double a, double b); // Appears to return one
|
||||
// iff a == b and neither is NaN.
|
||||
double __extendsfdf2vfp(float a); // Appears to convert from
|
||||
// float to double.
|
||||
int __fixdfsivfp(double a); // Appears to convert from
|
||||
// double to int.
|
||||
int __fixsfsivfp(float a); // Appears to convert from
|
||||
// float to int.
|
||||
unsigned int __fixunssfsivfp(float a); // Appears to convert from
|
||||
// float to unsigned int.
|
||||
unsigned int __fixunsdfsivfp(double a); // Appears to convert from
|
||||
// double to unsigned int.
|
||||
double __floatsidfvfp(int a); // Appears to convert from
|
||||
// int to double.
|
||||
float __floatsisfvfp(int a); // Appears to convert from
|
||||
// int to float.
|
||||
double __floatunssidfvfp(unsigned int a); // Appears to convert from
|
||||
// unisgned int to double.
|
||||
float __floatunssisfvfp(unsigned int a); // Appears to convert from
|
||||
// unisgned int to float.
|
||||
int __gedf2vfp(double a, double b); // Appears to return __gedf2
|
||||
// (a >= b)
|
||||
int __gesf2vfp(float a, float b); // Appears to return __gesf2
|
||||
// (a >= b)
|
||||
int __gtdf2vfp(double a, double b); // Appears to return __gtdf2
|
||||
// (a > b)
|
||||
int __gtsf2vfp(float a, float b); // Appears to return __gtsf2
|
||||
// (a > b)
|
||||
int __ledf2vfp(double a, double b); // Appears to return __ledf2
|
||||
// (a <= b)
|
||||
int __lesf2vfp(float a, float b); // Appears to return __lesf2
|
||||
// (a <= b)
|
||||
int __ltdf2vfp(double a, double b); // Appears to return __ltdf2
|
||||
// (a < b)
|
||||
int __ltsf2vfp(float a, float b); // Appears to return __ltsf2
|
||||
// (a < b)
|
||||
double __muldf3vfp(double a, double b); // Appears to return a * b
|
||||
float __mulsf3vfp(float a, float b); // Appears to return a * b
|
||||
int __nedf2vfp(double a, double b); // Appears to return __nedf2
|
||||
// (a != b)
|
||||
double __negdf2vfp(double a); // Appears to return -a
|
||||
float __negsf2vfp(float a); // Appears to return -a
|
||||
float __negsf2vfp(float a); // Appears to return -a
|
||||
double __subdf3vfp(double a, double b); // Appears to return a - b
|
||||
float __subsf3vfp(float a, float b); // Appears to return a - b
|
||||
float __truncdfsf2vfp(double a); // Appears to convert from
|
||||
// double to float.
|
||||
int __unorddf2vfp(double a, double b); // Appears to return __unorddf2
|
||||
int __unordsf2vfp(float a, float b); // Appears to return __unordsf2
|
||||
|
||||
|
||||
Preconditions are listed for each function at the definition when there are any.
|
||||
Any preconditions reflect the specification at
|
||||
http://gcc.gnu.org/onlinedocs/gccint/Libgcc.html#Libgcc.
|
||||
|
||||
Assumptions are listed in "int_lib.h", and in individual files. Where possible
|
||||
assumptions are checked at compile time.
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*===-- absvdi2.c - Implement __absvdi2 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===
|
||||
*
|
||||
* 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)1 << (N-1)))
|
||||
compilerrt_abort();
|
||||
const di_int t = a >> (N - 1);
|
||||
return (a ^ t) - t;
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/* ===-- absvsi2.c - Implement __absvsi2 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __absvsi2 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* 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 == (1 << (N-1)))
|
||||
compilerrt_abort();
|
||||
const si_int t = a >> (N - 1);
|
||||
return (a ^ t) - t;
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/* ===-- absvti2.c - Implement __absvdi2 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __absvti2 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if __x86_64
|
||||
|
||||
/* Returns: absolute value */
|
||||
|
||||
/* Effects: aborts if abs(x) < 0 */
|
||||
|
||||
ti_int
|
||||
__absvti2(ti_int a)
|
||||
{
|
||||
const int N = (int)(sizeof(ti_int) * CHAR_BIT);
|
||||
if (a == ((ti_int)1 << (N-1)))
|
||||
compilerrt_abort();
|
||||
const ti_int s = a >> (N - 1);
|
||||
return (a ^ s) - s;
|
||||
}
|
||||
|
||||
#endif
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
//===-- lib/adddf3.c - Double-precision addition ------------------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements double-precision soft-float addition with the IEEE-754
|
||||
// default rounding (to nearest, ties to even).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DOUBLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
ARM_EABI_FNALIAS(dadd, adddf3)
|
||||
|
||||
COMPILER_RT_ABI fp_t
|
||||
__adddf3(fp_t a, fp_t b) {
|
||||
|
||||
rep_t aRep = toRep(a);
|
||||
rep_t bRep = toRep(b);
|
||||
const rep_t aAbs = aRep & absMask;
|
||||
const rep_t bAbs = bRep & absMask;
|
||||
|
||||
// Detect if a or b is zero, infinity, or NaN.
|
||||
if (aAbs - 1U >= infRep - 1U || bAbs - 1U >= infRep - 1U) {
|
||||
|
||||
// NaN + anything = qNaN
|
||||
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
|
||||
// anything + NaN = qNaN
|
||||
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
|
||||
|
||||
if (aAbs == infRep) {
|
||||
// +/-infinity + -/+infinity = qNaN
|
||||
if ((toRep(a) ^ toRep(b)) == signBit) return fromRep(qnanRep);
|
||||
// +/-infinity + anything remaining = +/- infinity
|
||||
else return a;
|
||||
}
|
||||
|
||||
// anything remaining + +/-infinity = +/-infinity
|
||||
if (bAbs == infRep) return b;
|
||||
|
||||
// zero + anything = anything
|
||||
if (!aAbs) {
|
||||
// but we need to get the sign right for zero + zero
|
||||
if (!bAbs) return fromRep(toRep(a) & toRep(b));
|
||||
else return b;
|
||||
}
|
||||
|
||||
// anything + zero = anything
|
||||
if (!bAbs) return a;
|
||||
}
|
||||
|
||||
// Swap a and b if necessary so that a has the larger absolute value.
|
||||
if (bAbs > aAbs) {
|
||||
const rep_t temp = aRep;
|
||||
aRep = bRep;
|
||||
bRep = temp;
|
||||
}
|
||||
|
||||
// Extract the exponent and significand from the (possibly swapped) a and b.
|
||||
int aExponent = aRep >> significandBits & maxExponent;
|
||||
int bExponent = bRep >> significandBits & maxExponent;
|
||||
rep_t aSignificand = aRep & significandMask;
|
||||
rep_t bSignificand = bRep & significandMask;
|
||||
|
||||
// Normalize any denormals, and adjust the exponent accordingly.
|
||||
if (aExponent == 0) aExponent = normalize(&aSignificand);
|
||||
if (bExponent == 0) bExponent = normalize(&bSignificand);
|
||||
|
||||
// The sign of the result is the sign of the larger operand, a. If they
|
||||
// have opposite signs, we are performing a subtraction; otherwise addition.
|
||||
const rep_t resultSign = aRep & signBit;
|
||||
const bool subtraction = (aRep ^ bRep) & signBit;
|
||||
|
||||
// Shift the significands to give us round, guard and sticky, and or in the
|
||||
// implicit significand bit. (If we fell through from the denormal path it
|
||||
// was already set by normalize( ), but setting it twice won't hurt
|
||||
// anything.)
|
||||
aSignificand = (aSignificand | implicitBit) << 3;
|
||||
bSignificand = (bSignificand | implicitBit) << 3;
|
||||
|
||||
// Shift the significand of b by the difference in exponents, with a sticky
|
||||
// bottom bit to get rounding correct.
|
||||
const unsigned int align = aExponent - bExponent;
|
||||
if (align) {
|
||||
if (align < typeWidth) {
|
||||
const bool sticky = bSignificand << (typeWidth - align);
|
||||
bSignificand = bSignificand >> align | sticky;
|
||||
} else {
|
||||
bSignificand = 1; // sticky; b is known to be non-zero.
|
||||
}
|
||||
}
|
||||
|
||||
if (subtraction) {
|
||||
aSignificand -= bSignificand;
|
||||
|
||||
// If a == -b, return +zero.
|
||||
if (aSignificand == 0) return fromRep(0);
|
||||
|
||||
// If partial cancellation occured, we need to left-shift the result
|
||||
// and adjust the exponent:
|
||||
if (aSignificand < implicitBit << 3) {
|
||||
const int shift = rep_clz(aSignificand) - rep_clz(implicitBit << 3);
|
||||
aSignificand <<= shift;
|
||||
aExponent -= shift;
|
||||
}
|
||||
}
|
||||
|
||||
else /* addition */ {
|
||||
aSignificand += bSignificand;
|
||||
|
||||
// If the addition carried up, we need to right-shift the result and
|
||||
// adjust the exponent:
|
||||
if (aSignificand & implicitBit << 4) {
|
||||
const bool sticky = aSignificand & 1;
|
||||
aSignificand = aSignificand >> 1 | sticky;
|
||||
aExponent += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have overflowed the type, return +/- infinity:
|
||||
if (aExponent >= maxExponent) return fromRep(infRep | resultSign);
|
||||
|
||||
if (aExponent <= 0) {
|
||||
// Result is denormal before rounding; the exponent is zero and we
|
||||
// need to shift the significand.
|
||||
const int shift = 1 - aExponent;
|
||||
const bool sticky = aSignificand << (typeWidth - shift);
|
||||
aSignificand = aSignificand >> shift | sticky;
|
||||
aExponent = 0;
|
||||
}
|
||||
|
||||
// Low three bits are round, guard, and sticky.
|
||||
const int roundGuardSticky = aSignificand & 0x7;
|
||||
|
||||
// Shift the significand into place, and mask off the implicit bit.
|
||||
rep_t result = aSignificand >> 3 & significandMask;
|
||||
|
||||
// Insert the exponent and sign.
|
||||
result |= (rep_t)aExponent << significandBits;
|
||||
result |= resultSign;
|
||||
|
||||
// Final rounding. The result may overflow to infinity, but that is the
|
||||
// correct result in that case.
|
||||
if (roundGuardSticky > 0x4) result++;
|
||||
if (roundGuardSticky == 0x4) result += result & 1;
|
||||
return fromRep(result);
|
||||
}
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
//===-- lib/addsf3.c - Single-precision addition ------------------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements single-precision soft-float addition with the IEEE-754
|
||||
// default rounding (to nearest, ties to even).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
ARM_EABI_FNALIAS(fadd, addsf3)
|
||||
|
||||
fp_t __addsf3(fp_t a, fp_t b) {
|
||||
|
||||
rep_t aRep = toRep(a);
|
||||
rep_t bRep = toRep(b);
|
||||
const rep_t aAbs = aRep & absMask;
|
||||
const rep_t bAbs = bRep & absMask;
|
||||
|
||||
// Detect if a or b is zero, infinity, or NaN.
|
||||
if (aAbs - 1U >= infRep - 1U || bAbs - 1U >= infRep - 1U) {
|
||||
|
||||
// NaN + anything = qNaN
|
||||
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
|
||||
// anything + NaN = qNaN
|
||||
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
|
||||
|
||||
if (aAbs == infRep) {
|
||||
// +/-infinity + -/+infinity = qNaN
|
||||
if ((toRep(a) ^ toRep(b)) == signBit) return fromRep(qnanRep);
|
||||
// +/-infinity + anything remaining = +/- infinity
|
||||
else return a;
|
||||
}
|
||||
|
||||
// anything remaining + +/-infinity = +/-infinity
|
||||
if (bAbs == infRep) return b;
|
||||
|
||||
// zero + anything = anything
|
||||
if (!aAbs) {
|
||||
// but we need to get the sign right for zero + zero
|
||||
if (!bAbs) return fromRep(toRep(a) & toRep(b));
|
||||
else return b;
|
||||
}
|
||||
|
||||
// anything + zero = anything
|
||||
if (!bAbs) return a;
|
||||
}
|
||||
|
||||
// Swap a and b if necessary so that a has the larger absolute value.
|
||||
if (bAbs > aAbs) {
|
||||
const rep_t temp = aRep;
|
||||
aRep = bRep;
|
||||
bRep = temp;
|
||||
}
|
||||
|
||||
// Extract the exponent and significand from the (possibly swapped) a and b.
|
||||
int aExponent = aRep >> significandBits & maxExponent;
|
||||
int bExponent = bRep >> significandBits & maxExponent;
|
||||
rep_t aSignificand = aRep & significandMask;
|
||||
rep_t bSignificand = bRep & significandMask;
|
||||
|
||||
// Normalize any denormals, and adjust the exponent accordingly.
|
||||
if (aExponent == 0) aExponent = normalize(&aSignificand);
|
||||
if (bExponent == 0) bExponent = normalize(&bSignificand);
|
||||
|
||||
// The sign of the result is the sign of the larger operand, a. If they
|
||||
// have opposite signs, we are performing a subtraction; otherwise addition.
|
||||
const rep_t resultSign = aRep & signBit;
|
||||
const bool subtraction = (aRep ^ bRep) & signBit;
|
||||
|
||||
// Shift the significands to give us round, guard and sticky, and or in the
|
||||
// implicit significand bit. (If we fell through from the denormal path it
|
||||
// was already set by normalize( ), but setting it twice won't hurt
|
||||
// anything.)
|
||||
aSignificand = (aSignificand | implicitBit) << 3;
|
||||
bSignificand = (bSignificand | implicitBit) << 3;
|
||||
|
||||
// Shift the significand of b by the difference in exponents, with a sticky
|
||||
// bottom bit to get rounding correct.
|
||||
const unsigned int align = aExponent - bExponent;
|
||||
if (align) {
|
||||
if (align < typeWidth) {
|
||||
const bool sticky = bSignificand << (typeWidth - align);
|
||||
bSignificand = bSignificand >> align | sticky;
|
||||
} else {
|
||||
bSignificand = 1; // sticky; b is known to be non-zero.
|
||||
}
|
||||
}
|
||||
|
||||
if (subtraction) {
|
||||
aSignificand -= bSignificand;
|
||||
|
||||
// If a == -b, return +zero.
|
||||
if (aSignificand == 0) return fromRep(0);
|
||||
|
||||
// If partial cancellation occured, we need to left-shift the result
|
||||
// and adjust the exponent:
|
||||
if (aSignificand < implicitBit << 3) {
|
||||
const int shift = rep_clz(aSignificand) - rep_clz(implicitBit << 3);
|
||||
aSignificand <<= shift;
|
||||
aExponent -= shift;
|
||||
}
|
||||
}
|
||||
|
||||
else /* addition */ {
|
||||
aSignificand += bSignificand;
|
||||
|
||||
// If the addition carried up, we need to right-shift the result and
|
||||
// adjust the exponent:
|
||||
if (aSignificand & implicitBit << 4) {
|
||||
const bool sticky = aSignificand & 1;
|
||||
aSignificand = aSignificand >> 1 | sticky;
|
||||
aExponent += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have overflowed the type, return +/- infinity:
|
||||
if (aExponent >= maxExponent) return fromRep(infRep | resultSign);
|
||||
|
||||
if (aExponent <= 0) {
|
||||
// Result is denormal before rounding; the exponent is zero and we
|
||||
// need to shift the significand.
|
||||
const int shift = 1 - aExponent;
|
||||
const bool sticky = aSignificand << (typeWidth - shift);
|
||||
aSignificand = aSignificand >> shift | sticky;
|
||||
aExponent = 0;
|
||||
}
|
||||
|
||||
// Low three bits are round, guard, and sticky.
|
||||
const int roundGuardSticky = aSignificand & 0x7;
|
||||
|
||||
// Shift the significand into place, and mask off the implicit bit.
|
||||
rep_t result = aSignificand >> 3 & significandMask;
|
||||
|
||||
// Insert the exponent and sign.
|
||||
result |= (rep_t)aExponent << significandBits;
|
||||
result |= resultSign;
|
||||
|
||||
// Final rounding. The result may overflow to infinity, but that is the
|
||||
// correct result in that case.
|
||||
if (roundGuardSticky > 0x4) result++;
|
||||
if (roundGuardSticky == 0x4) result += result & 1;
|
||||
return fromRep(result);
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/* ===-- addvdi3.c - Implement __addvdi3 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __addvdi3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* Returns: a + b */
|
||||
|
||||
/* Effects: aborts if a + b overflows */
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__addvdi3(di_int a, di_int b)
|
||||
{
|
||||
di_int s = a + b;
|
||||
if (b >= 0)
|
||||
{
|
||||
if (s < a)
|
||||
compilerrt_abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s >= a)
|
||||
compilerrt_abort();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/* ===-- addvsi3.c - Implement __addvsi3 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __addvsi3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* Returns: a + b */
|
||||
|
||||
/* Effects: aborts if a + b overflows */
|
||||
|
||||
COMPILER_RT_ABI si_int
|
||||
__addvsi3(si_int a, si_int b)
|
||||
{
|
||||
si_int s = a + b;
|
||||
if (b >= 0)
|
||||
{
|
||||
if (s < a)
|
||||
compilerrt_abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s >= a)
|
||||
compilerrt_abort();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/* ===-- addvti3.c - Implement __addvti3 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __addvti3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if __x86_64
|
||||
|
||||
/* Returns: a + b */
|
||||
|
||||
/* Effects: aborts if a + b overflows */
|
||||
|
||||
ti_int
|
||||
__addvti3(ti_int a, ti_int b)
|
||||
{
|
||||
ti_int s = a + b;
|
||||
if (b >= 0)
|
||||
{
|
||||
if (s < a)
|
||||
compilerrt_abort();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s >= a)
|
||||
compilerrt_abort();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- adddf3vfp.S - Implement adddf3vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// double __adddf3vfp(double a, double b) { return a + b; }
|
||||
//
|
||||
// Adds two double precision floating point numbers using the Darwin
|
||||
// calling convention where double arguments are passsed in GPR pairs
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__adddf3vfp)
|
||||
vmov d6, r0, r1 // move first param from r0/r1 pair into d6
|
||||
vmov d7, r2, r3 // move second param from r2/r3 pair into d7
|
||||
vadd.f64 d6, d6, d7
|
||||
vmov r0, r1, d6 // move result back to r0/r1 pair
|
||||
bx lr
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- addsf3vfp.S - Implement addsf3vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern float __addsf3vfp(float a, float b);
|
||||
//
|
||||
// Adds two single precision floating point numbers using the Darwin
|
||||
// calling convention where single arguments are passsed in GPRs
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__addsf3vfp)
|
||||
vmov s14, r0 // move first param from r0 into float register
|
||||
vmov s15, r1 // move second param from r1 into float register
|
||||
vadd.f32 s14, s14, s15
|
||||
vmov r0, s14 // move result back to r0
|
||||
bx lr
|
||||
@@ -0,0 +1,39 @@
|
||||
//===-- aeabi_dcmp.S - EABI dcmp* implementation ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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 DEFINE_AEABI_DCMP(cond) \
|
||||
.syntax unified SEPARATOR \
|
||||
.align 2 SEPARATOR \
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_dcmp ## cond) \
|
||||
push { r4, lr } SEPARATOR \
|
||||
bl SYMBOL_NAME(__ ## cond ## df2) SEPARATOR \
|
||||
cmp r0, #0 SEPARATOR \
|
||||
b ## cond 1f SEPARATOR \
|
||||
mov r0, #0 SEPARATOR \
|
||||
pop { r4, pc } SEPARATOR \
|
||||
1: SEPARATOR \
|
||||
mov r0, #1 SEPARATOR \
|
||||
pop { r4, pc }
|
||||
|
||||
DEFINE_AEABI_DCMP(eq)
|
||||
DEFINE_AEABI_DCMP(lt)
|
||||
DEFINE_AEABI_DCMP(le)
|
||||
DEFINE_AEABI_DCMP(ge)
|
||||
DEFINE_AEABI_DCMP(gt)
|
||||
@@ -0,0 +1,39 @@
|
||||
//===-- aeabi_fcmp.S - EABI fcmp* implementation ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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 DEFINE_AEABI_FCMP(cond) \
|
||||
.syntax unified SEPARATOR \
|
||||
.align 2 SEPARATOR \
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_fcmp ## cond) \
|
||||
push { r4, lr } SEPARATOR \
|
||||
bl SYMBOL_NAME(__ ## cond ## sf2) SEPARATOR \
|
||||
cmp r0, #0 SEPARATOR \
|
||||
b ## cond 1f SEPARATOR \
|
||||
mov r0, #0 SEPARATOR \
|
||||
pop { r4, pc } SEPARATOR \
|
||||
1: SEPARATOR \
|
||||
mov r0, #1 SEPARATOR \
|
||||
pop { r4, pc }
|
||||
|
||||
DEFINE_AEABI_FCMP(eq)
|
||||
DEFINE_AEABI_FCMP(lt)
|
||||
DEFINE_AEABI_FCMP(le)
|
||||
DEFINE_AEABI_FCMP(ge)
|
||||
DEFINE_AEABI_FCMP(gt)
|
||||
@@ -0,0 +1,27 @@
|
||||
//===-- aeabi_idivmod.S - EABI idivmod implementation ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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
|
||||
.align 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 }
|
||||
@@ -0,0 +1,30 @@
|
||||
//===-- aeabi_ldivmod.S - EABI ldivmod implementation ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_ldivmod)
|
||||
push {r11, lr}
|
||||
sub sp, sp, #16
|
||||
add r12, sp, #8
|
||||
str r12, [sp]
|
||||
bl SYMBOL_NAME(__divmoddi4)
|
||||
ldr r2, [sp, #8]
|
||||
ldr r3, [sp, #12]
|
||||
add sp, sp, #16
|
||||
pop {r11, pc}
|
||||
@@ -0,0 +1,19 @@
|
||||
//===-- aeabi_memcmp.S - EABI memcmp implementation -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
// void __aeabi_memcmp(void *dest, void *src, size_t n) { memcmp(dest, src, n); }
|
||||
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_memcmp)
|
||||
b memcmp
|
||||
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp4, __aeabi_memcmp)
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcmp8, __aeabi_memcmp)
|
||||
@@ -0,0 +1,19 @@
|
||||
//===-- aeabi_memcpy.S - EABI memcpy implementation -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
// void __aeabi_memcpy(void *dest, void *src, size_t n) { memcpy(dest, src, n); }
|
||||
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_memcpy)
|
||||
b memcpy
|
||||
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy4, __aeabi_memcpy)
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memcpy8, __aeabi_memcpy)
|
||||
@@ -0,0 +1,19 @@
|
||||
//===-- aeabi_memmove.S - EABI memmove implementation --------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
// void __aeabi_memmove(void *dest, void *src, size_t n) { memmove(dest, src, n); }
|
||||
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_memmove)
|
||||
b memmove
|
||||
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove4, __aeabi_memmove)
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memmove8, __aeabi_memmove)
|
||||
@@ -0,0 +1,32 @@
|
||||
//===-- aeabi_memset.S - EABI memset implementation -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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); }
|
||||
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_memset)
|
||||
mov r3, r1
|
||||
mov r1, r2
|
||||
mov r2, r3
|
||||
b memset
|
||||
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset4, __aeabi_memset)
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memset8, __aeabi_memset)
|
||||
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_memclr)
|
||||
mov r2, r1
|
||||
mov r1, #0
|
||||
b memset
|
||||
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr4, __aeabi_memclr)
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_memclr8, __aeabi_memclr)
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//===-- aeabi_uidivmod.S - EABI uidivmod implementation -------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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
|
||||
.align 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 }
|
||||
@@ -0,0 +1,30 @@
|
||||
//===-- aeabi_uldivmod.S - EABI uldivmod implementation -------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod)
|
||||
push {r11, lr}
|
||||
sub sp, sp, #16
|
||||
add r12, sp, #8
|
||||
str r12, [sp]
|
||||
bl SYMBOL_NAME(__udivmoddi4)
|
||||
ldr r2, [sp, #8]
|
||||
ldr r3, [sp, #12]
|
||||
add sp, sp, #16
|
||||
pop {r11, pc}
|
||||
@@ -0,0 +1,36 @@
|
||||
//===------- bswapdi2 - Implement bswapdi2 --------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern uint64_t __bswapdi2(uint64_t);
|
||||
//
|
||||
// Reverse all the bytes in a 64-bit integer.
|
||||
//
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__bswapdi2)
|
||||
#if __ARM_ARCH_5TEJ__ || __ARM_ARCH_4T__
|
||||
// before armv6 does not have "rev" instruction
|
||||
// r2 = rev(r0)
|
||||
eor r2, r0, r0, ror #16
|
||||
bic r2, r2, #0xff0000
|
||||
mov r2, r2, lsr #8
|
||||
eor r2, r2, r0, ror #8
|
||||
// r0 = rev(r1)
|
||||
eor r0, r1, r1, ror #16
|
||||
bic r0, r0, #0xff0000
|
||||
mov r0, r0, lsr #8
|
||||
eor r0, r0, r1, ror #8
|
||||
#else
|
||||
rev r2, r0 // r2 = rev(r0)
|
||||
rev r0, r1 // r0 = rev(r1)
|
||||
#endif
|
||||
mov r1, r2 // r1 = r2 = rev(r0)
|
||||
bx lr
|
||||
@@ -0,0 +1,28 @@
|
||||
//===------- bswapsi2 - Implement bswapsi2 --------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern uint32_t __bswapsi2(uint32_t);
|
||||
//
|
||||
// Reverse all the bytes in a 32-bit integer.
|
||||
//
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__bswapsi2)
|
||||
#if __ARM_ARCH_5TEJ__ || __ARM_ARCH_4T__
|
||||
// before armv6 does not have "rev" instruction
|
||||
eor r1, r0, r0, ror #16
|
||||
bic r1, r1, #0xff0000
|
||||
mov r1, r1, lsr #8
|
||||
eor r0, r1, r0, ror #8
|
||||
#else
|
||||
rev r0, r0
|
||||
#endif
|
||||
bx lr
|
||||
@@ -0,0 +1,130 @@
|
||||
//===-- comparesf2.S - Implement single-precision soft-float comparisons --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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, with multiple names.
|
||||
//
|
||||
// The 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
.syntax unified
|
||||
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__eqsf2)
|
||||
DEFINE_COMPILERRT_FUNCTION(__lesf2)
|
||||
DEFINE_COMPILERRT_FUNCTION(__ltsf2)
|
||||
DEFINE_COMPILERRT_FUNCTION(__nesf2)
|
||||
// Make copies of a and b with the sign bit shifted off the top. These will
|
||||
// be used to detect zeros and NaNs.
|
||||
mov r2, r0, lsl #1
|
||||
mov r3, r1, lsl #1
|
||||
|
||||
// We do the comparison in three stages (ignoring NaN values for the time
|
||||
// being). First, we orr the absolute values of a and b; this sets the Z
|
||||
// flag if both a and b are zero (of either sign). The shift of r3 doesn't
|
||||
// effect this at all, but it *does* make sure that the C flag is clear for
|
||||
// the subsequent operations.
|
||||
orrs r12, r2, r3, lsr #1
|
||||
|
||||
// Next, we check if a and b have the same or different signs. If they have
|
||||
// opposite signs, this eor will set the N flag.
|
||||
eorsne r12, r0, r1
|
||||
|
||||
// If a and b are equal (either both zeros or bit identical; again, we're
|
||||
// ignoring NaNs for now), this subtract will zero out r0. If they have the
|
||||
// same sign, the flags are updated as they would be for a comparison of the
|
||||
// absolute values of a and b.
|
||||
subspl r0, r2, r3
|
||||
|
||||
// If a is smaller in magnitude than b and both have the same sign, place
|
||||
// the negation of the sign of b in r0. Thus, if both are negative and
|
||||
// a > b, this sets r0 to 0; if both are positive and a < b, this sets
|
||||
// r0 to -1.
|
||||
//
|
||||
// This is also done if a and b have opposite signs and are not both zero,
|
||||
// because in that case the subtract was not performed and the C flag is
|
||||
// still clear from the shift argument in orrs; if a is positive and b
|
||||
// negative, this places 0 in r0; if a is negative and b positive, -1 is
|
||||
// placed in r0.
|
||||
mvnlo r0, r1, asr #31
|
||||
|
||||
// If a is greater in magnitude than b and both have the same sign, place
|
||||
// the sign of b in r0. Thus, if both are negative and a < b, -1 is placed
|
||||
// in r0, which is the desired result. Conversely, if both are positive
|
||||
// and a > b, zero is placed in r0.
|
||||
movhi r0, r1, asr #31
|
||||
|
||||
// If you've been keeping track, at this point r0 contains -1 if a < b and
|
||||
// 0 if a >= b. All that remains to be done is to set it to 1 if a > b.
|
||||
// If a == b, then the Z flag is set, so we can get the correct final value
|
||||
// into r0 by simply or'ing with 1 if Z is clear.
|
||||
orrne r0, r0, #1
|
||||
|
||||
// Finally, we need to deal with NaNs. If either argument is NaN, replace
|
||||
// the value in r0 with 1.
|
||||
cmp r2, #0xff000000
|
||||
cmpls r3, #0xff000000
|
||||
movhi r0, #1
|
||||
bx lr
|
||||
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__gesf2)
|
||||
DEFINE_COMPILERRT_FUNCTION(__gtsf2)
|
||||
// Identical to the preceeding except in that we return -1 for NaN values.
|
||||
// Given that the two paths share so much code, one might be tempted to
|
||||
// unify them; however, the extra code needed to do so makes the code size
|
||||
// to performance tradeoff very hard to justify for such small functions.
|
||||
mov r2, r0, lsl #1
|
||||
mov r3, r1, lsl #1
|
||||
orrs r12, r2, r3, lsr #1
|
||||
eorsne r12, r0, r1
|
||||
subspl r0, r2, r3
|
||||
mvnlo r0, r1, asr #31
|
||||
movhi r0, r1, asr #31
|
||||
orrne r0, r0, #1
|
||||
cmp r2, #0xff000000
|
||||
cmpls r3, #0xff000000
|
||||
movhi r0, #-1
|
||||
bx lr
|
||||
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__unordsf2)
|
||||
// Return 1 for NaN values, 0 otherwise.
|
||||
mov r2, r0, lsl #1
|
||||
mov r3, r1, lsl #1
|
||||
mov r0, #0
|
||||
cmp r2, #0xff000000
|
||||
cmpls r3, #0xff000000
|
||||
movhi r0, #1
|
||||
bx lr
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- divdf3vfp.S - Implement divdf3vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __divdf3vfp(double a, double b);
|
||||
//
|
||||
// Divides two double precision floating point numbers using the Darwin
|
||||
// calling convention where double arguments are passsed in GPR pairs
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__divdf3vfp)
|
||||
vmov d6, r0, r1 // move first param from r0/r1 pair into d6
|
||||
vmov d7, r2, r3 // move second param from r2/r3 pair into d7
|
||||
vdiv.f64 d5, d6, d7
|
||||
vmov r0, r1, d5 // move result back to r0/r1 pair
|
||||
bx lr
|
||||
@@ -0,0 +1,60 @@
|
||||
/*===-- divmodsi4.S - 32-bit signed integer divide and modulus ------------===//
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===//
|
||||
*
|
||||
* This file implements the __divmodsi4 (32-bit signed integer divide and
|
||||
* modulus) function for the ARM architecture. A naive digit-by-digit
|
||||
* computation is employed for simplicity.
|
||||
*
|
||||
*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
#define ESTABLISH_FRAME \
|
||||
push {r4-r7, lr} ;\
|
||||
add r7, sp, #12
|
||||
#define CLEAR_FRAME_AND_RETURN \
|
||||
pop {r4-r7, pc}
|
||||
|
||||
.syntax unified
|
||||
.align 3
|
||||
DEFINE_COMPILERRT_FUNCTION(__divmodsi4)
|
||||
#if __ARM_ARCH_7S__
|
||||
tst r1, r1
|
||||
beq LOCAL_LABEL(divzero)
|
||||
mov r3, r0
|
||||
sdiv r0, r3, r1
|
||||
mls r1, r0, r1, r3
|
||||
str r1, [r2]
|
||||
bx lr
|
||||
LOCAL_LABEL(divzero):
|
||||
mov r0, #0
|
||||
bx lr
|
||||
#else
|
||||
ESTABLISH_FRAME
|
||||
// Set aside the sign of the quotient and modulus, and the address for the
|
||||
// modulus.
|
||||
eor r4, r0, r1
|
||||
mov r5, r0
|
||||
mov r6, r2
|
||||
// Take the absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
|
||||
eor ip, r0, r0, asr #31
|
||||
eor lr, r1, r1, asr #31
|
||||
sub r0, ip, r0, asr #31
|
||||
sub r1, lr, r1, asr #31
|
||||
// Unsigned divmod:
|
||||
bl SYMBOL_NAME(__udivmodsi4)
|
||||
// Apply the sign of quotient and modulus
|
||||
ldr r1, [r6]
|
||||
eor r0, r0, r4, asr #31
|
||||
eor r1, r1, r5, asr #31
|
||||
sub r0, r0, r4, asr #31
|
||||
sub r1, r1, r5, asr #31
|
||||
str r1, [r6]
|
||||
CLEAR_FRAME_AND_RETURN
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- divsf3vfp.S - Implement divsf3vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern float __divsf3vfp(float a, float b);
|
||||
//
|
||||
// Divides two single precision floating point numbers using the Darwin
|
||||
// calling convention where single arguments are passsed like 32-bit ints.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__divsf3vfp)
|
||||
vmov s14, r0 // move first param from r0 into float register
|
||||
vmov s15, r1 // move second param from r1 into float register
|
||||
vdiv.f32 s13, s14, s15
|
||||
vmov r0, s13 // move result back to r0
|
||||
bx lr
|
||||
@@ -0,0 +1,51 @@
|
||||
/*===-- divsi3.S - 32-bit signed integer divide ---------------------------===//
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===//
|
||||
*
|
||||
* This file implements the __divsi3 (32-bit signed integer divide) function
|
||||
* for the ARM architecture as a wrapper around the unsigned routine.
|
||||
*
|
||||
*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
#define ESTABLISH_FRAME \
|
||||
push {r4, r7, lr} ;\
|
||||
add r7, sp, #4
|
||||
#define CLEAR_FRAME_AND_RETURN \
|
||||
pop {r4, r7, pc}
|
||||
|
||||
.syntax unified
|
||||
.align 3
|
||||
// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_idiv, __divsi3)
|
||||
DEFINE_COMPILERRT_FUNCTION(__divsi3)
|
||||
#if __ARM_ARCH_7S__
|
||||
tst r1,r1
|
||||
beq LOCAL_LABEL(divzero)
|
||||
sdiv r0, r0, r1
|
||||
bx lr
|
||||
LOCAL_LABEL(divzero):
|
||||
mov r0,#0
|
||||
bx lr
|
||||
#else
|
||||
ESTABLISH_FRAME
|
||||
// Set aside the sign of the quotient.
|
||||
eor r4, r0, r1
|
||||
// Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
|
||||
eor r2, r0, r0, asr #31
|
||||
eor r3, r1, r1, asr #31
|
||||
sub r0, r2, r0, asr #31
|
||||
sub r1, r3, r1, asr #31
|
||||
// abs(a) / abs(b)
|
||||
bl SYMBOL_NAME(__udivsi3)
|
||||
// Apply sign of quotient to result and return.
|
||||
eor r0, r0, r4, asr #31
|
||||
sub r0, r0, r4, asr #31
|
||||
CLEAR_FRAME_AND_RETURN
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
//===-- eqdf2vfp.S - Implement eqdf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __eqdf2vfp(double a, double b);
|
||||
//
|
||||
// Returns one iff a == b and neither is NaN.
|
||||
// Uses Darwin calling convention where double precision arguments are passsed
|
||||
// like in GPR pairs.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__eqdf2vfp)
|
||||
vmov d6, r0, r1 // load r0/r1 pair in double register
|
||||
vmov d7, r2, r3 // load r2/r3 pair in double register
|
||||
vcmp.f64 d6, d7
|
||||
vmrs apsr_nzcv, fpscr
|
||||
moveq r0, #1 // set result register to 1 if equal
|
||||
movne r0, #0
|
||||
bx lr
|
||||
@@ -0,0 +1,29 @@
|
||||
//===-- eqsf2vfp.S - Implement eqsf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __eqsf2vfp(float a, float b);
|
||||
//
|
||||
// Returns one iff a == b and neither is NaN.
|
||||
// Uses Darwin calling convention where single precision arguments are passsed
|
||||
// like 32-bit ints
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__eqsf2vfp)
|
||||
vmov s14, r0 // move from GPR 0 to float register
|
||||
vmov s15, r1 // move from GPR 1 to float register
|
||||
vcmp.f32 s14, s15
|
||||
vmrs apsr_nzcv, fpscr
|
||||
moveq r0, #1 // set result register to 1 if equal
|
||||
movne r0, #0
|
||||
bx lr
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- extendsfdf2vfp.S - Implement extendsfdf2vfp -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __extendsfdf2vfp(float a);
|
||||
//
|
||||
// Converts single precision float to double precision result.
|
||||
// Uses Darwin calling convention where a single precision parameter is
|
||||
// passed in a GPR and a double precision result is returned in R0/R1 pair.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__extendsfdf2vfp)
|
||||
vmov s15, r0 // load float register from R0
|
||||
vcvt.f64.f32 d7, s15 // convert single to double
|
||||
vmov r0, r1, d7 // return result in r0/r1 pair
|
||||
bx lr
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- fixdfsivfp.S - Implement fixdfsivfp -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __fixdfsivfp(double a);
|
||||
//
|
||||
// Converts double precision float to a 32-bit int rounding towards zero.
|
||||
// Uses Darwin calling convention where a double precision parameter is
|
||||
// passed in GPR register pair.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__fixdfsivfp)
|
||||
vmov d7, r0, r1 // load double register from R0/R1
|
||||
vcvt.s32.f64 s15, d7 // convert double to 32-bit int into s15
|
||||
vmov r0, s15 // move s15 to result register
|
||||
bx lr
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- fixsfsivfp.S - Implement fixsfsivfp -----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __fixsfsivfp(float a);
|
||||
//
|
||||
// Converts single precision float to a 32-bit int rounding towards zero.
|
||||
// Uses Darwin calling convention where a single precision parameter is
|
||||
// passed in a GPR..
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__fixsfsivfp)
|
||||
vmov s15, r0 // load float register from R0
|
||||
vcvt.s32.f32 s15, s15 // convert single to 32-bit int into s15
|
||||
vmov r0, s15 // move s15 to result register
|
||||
bx lr
|
||||
@@ -0,0 +1,26 @@
|
||||
//===-- fixunsdfsivfp.S - Implement fixunsdfsivfp -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern unsigned int __fixunsdfsivfp(double a);
|
||||
//
|
||||
// Converts double precision float to a 32-bit unsigned int rounding towards
|
||||
// zero. All negative values become zero.
|
||||
// Uses Darwin calling convention where a double precision parameter is
|
||||
// passed in GPR register pair.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__fixunsdfsivfp)
|
||||
vmov d7, r0, r1 // load double register from R0/R1
|
||||
vcvt.u32.f64 s15, d7 // convert double to 32-bit int into s15
|
||||
vmov r0, s15 // move s15 to result register
|
||||
bx lr
|
||||
@@ -0,0 +1,26 @@
|
||||
//===-- fixunssfsivfp.S - Implement fixunssfsivfp -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern unsigned int __fixunssfsivfp(float a);
|
||||
//
|
||||
// Converts single precision float to a 32-bit unsigned int rounding towards
|
||||
// zero. All negative values become zero.
|
||||
// Uses Darwin calling convention where a single precision parameter is
|
||||
// passed in a GPR..
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__fixunssfsivfp)
|
||||
vmov s15, r0 // load float register from R0
|
||||
vcvt.u32.f32 s15, s15 // convert single to 32-bit unsigned into s15
|
||||
vmov r0, s15 // move s15 to result register
|
||||
bx lr
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- floatsidfvfp.S - Implement floatsidfvfp ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __floatsidfvfp(int a);
|
||||
//
|
||||
// Converts a 32-bit int to a double precision float.
|
||||
// Uses Darwin calling convention where a double precision result is
|
||||
// return in GPR register pair.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__floatsidfvfp)
|
||||
vmov s15, r0 // move int to float register s15
|
||||
vcvt.f64.s32 d7, s15 // convert 32-bit int in s15 to double in d7
|
||||
vmov r0, r1, d7 // move d7 to result register pair r0/r1
|
||||
bx lr
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- floatsisfvfp.S - Implement floatsisfvfp ---------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern float __floatsisfvfp(int a);
|
||||
//
|
||||
// Converts single precision float to a 32-bit int rounding towards zero.
|
||||
// Uses Darwin calling convention where a single precision result is
|
||||
// return in a GPR..
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__floatsisfvfp)
|
||||
vmov s15, r0 // move int to float register s15
|
||||
vcvt.f32.s32 s15, s15 // convert 32-bit int in s15 to float in s15
|
||||
vmov r0, s15 // move s15 to result register
|
||||
bx lr
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- floatunssidfvfp.S - Implement floatunssidfvfp ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __floatunssidfvfp(unsigned int a);
|
||||
//
|
||||
// Converts a 32-bit int to a double precision float.
|
||||
// Uses Darwin calling convention where a double precision result is
|
||||
// return in GPR register pair.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__floatunssidfvfp)
|
||||
vmov s15, r0 // move int to float register s15
|
||||
vcvt.f64.u32 d7, s15 // convert 32-bit int in s15 to double in d7
|
||||
vmov r0, r1, d7 // move d7 to result register pair r0/r1
|
||||
bx lr
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- floatunssisfvfp.S - Implement floatunssisfvfp ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern float __floatunssisfvfp(unsigned int a);
|
||||
//
|
||||
// Converts single precision float to a 32-bit int rounding towards zero.
|
||||
// Uses Darwin calling convention where a single precision result is
|
||||
// return in a GPR..
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__floatunssisfvfp)
|
||||
vmov s15, r0 // move int to float register s15
|
||||
vcvt.f32.u32 s15, s15 // convert 32-bit int in s15 to float in s15
|
||||
vmov r0, s15 // move s15 to result register
|
||||
bx lr
|
||||
@@ -0,0 +1,28 @@
|
||||
//===-- gedf2vfp.S - Implement gedf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __gedf2vfp(double a, double b);
|
||||
//
|
||||
// Returns one iff a >= b and neither is NaN.
|
||||
// Uses Darwin calling convention where double precision arguments are passsed
|
||||
// like in GPR pairs.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__gedf2vfp)
|
||||
vmov d6, r0, r1 // load r0/r1 pair in double register
|
||||
vmov d7, r2, r3 // load r2/r3 pair in double register
|
||||
vcmp.f64 d6, d7
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movge r0, #1 // set result register to 1 if greater than or equal
|
||||
movlt r0, #0
|
||||
bx lr
|
||||
@@ -0,0 +1,29 @@
|
||||
//===-- gesf2vfp.S - Implement gesf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __gesf2vfp(float a, float b);
|
||||
//
|
||||
// Returns one iff a >= b and neither is NaN.
|
||||
// Uses Darwin calling convention where single precision arguments are passsed
|
||||
// like 32-bit ints
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__gesf2vfp)
|
||||
vmov s14, r0 // move from GPR 0 to float register
|
||||
vmov s15, r1 // move from GPR 1 to float register
|
||||
vcmp.f32 s14, s15
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movge r0, #1 // set result register to 1 if greater than or equal
|
||||
movlt r0, #0
|
||||
bx lr
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//===-- gtdf2vfp.S - Implement gtdf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __gtdf2vfp(double a, double b);
|
||||
//
|
||||
// Returns one iff a > b and neither is NaN.
|
||||
// Uses Darwin calling convention where double precision arguments are passsed
|
||||
// like in GPR pairs.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__gtdf2vfp)
|
||||
vmov d6, r0, r1 // load r0/r1 pair in double register
|
||||
vmov d7, r2, r3 // load r2/r3 pair in double register
|
||||
vcmp.f64 d6, d7
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movgt r0, #1 // set result register to 1 if equal
|
||||
movle r0, #0
|
||||
bx lr
|
||||
@@ -0,0 +1,29 @@
|
||||
//===-- gtsf2vfp.S - Implement gtsf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __gtsf2vfp(float a, float b);
|
||||
//
|
||||
// Returns one iff a > b and neither is NaN.
|
||||
// Uses Darwin calling convention where single precision arguments are passsed
|
||||
// like 32-bit ints
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__gtsf2vfp)
|
||||
vmov s14, r0 // move from GPR 0 to float register
|
||||
vmov s15, r1 // move from GPR 1 to float register
|
||||
vcmp.f32 s14, s15
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movgt r0, #1 // set result register to 1 if equal
|
||||
movle r0, #0
|
||||
bx lr
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//===-- ledf2vfp.S - Implement ledf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __ledf2vfp(double a, double b);
|
||||
//
|
||||
// Returns one iff a <= b and neither is NaN.
|
||||
// Uses Darwin calling convention where double precision arguments are passsed
|
||||
// like in GPR pairs.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__ledf2vfp)
|
||||
vmov d6, r0, r1 // load r0/r1 pair in double register
|
||||
vmov d7, r2, r3 // load r2/r3 pair in double register
|
||||
vcmp.f64 d6, d7
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movls r0, #1 // set result register to 1 if equal
|
||||
movhi r0, #0
|
||||
bx lr
|
||||
@@ -0,0 +1,29 @@
|
||||
//===-- lesf2vfp.S - Implement lesf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __lesf2vfp(float a, float b);
|
||||
//
|
||||
// Returns one iff a <= b and neither is NaN.
|
||||
// Uses Darwin calling convention where single precision arguments are passsed
|
||||
// like 32-bit ints
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__lesf2vfp)
|
||||
vmov s14, r0 // move from GPR 0 to float register
|
||||
vmov s15, r1 // move from GPR 1 to float register
|
||||
vcmp.f32 s14, s15
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movls r0, #1 // set result register to 1 if equal
|
||||
movhi r0, #0
|
||||
bx lr
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//===-- ltdf2vfp.S - Implement ltdf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __ltdf2vfp(double a, double b);
|
||||
//
|
||||
// Returns one iff a < b and neither is NaN.
|
||||
// Uses Darwin calling convention where double precision arguments are passsed
|
||||
// like in GPR pairs.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__ltdf2vfp)
|
||||
vmov d6, r0, r1 // load r0/r1 pair in double register
|
||||
vmov d7, r2, r3 // load r2/r3 pair in double register
|
||||
vcmp.f64 d6, d7
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movmi r0, #1 // set result register to 1 if equal
|
||||
movpl r0, #0
|
||||
bx lr
|
||||
@@ -0,0 +1,29 @@
|
||||
//===-- ltsf2vfp.S - Implement ltsf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __ltsf2vfp(float a, float b);
|
||||
//
|
||||
// Returns one iff a < b and neither is NaN.
|
||||
// Uses Darwin calling convention where single precision arguments are passsed
|
||||
// like 32-bit ints
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__ltsf2vfp)
|
||||
vmov s14, r0 // move from GPR 0 to float register
|
||||
vmov s15, r1 // move from GPR 1 to float register
|
||||
vcmp.f32 s14, s15
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movmi r0, #1 // set result register to 1 if equal
|
||||
movpl r0, #0
|
||||
bx lr
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*===-- modsi3.S - 32-bit signed integer modulus --------------------------===//
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===//
|
||||
*
|
||||
* This file implements the __modsi3 (32-bit signed integer modulus) function
|
||||
* for the ARM architecture as a wrapper around the unsigned routine.
|
||||
*
|
||||
*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
#define ESTABLISH_FRAME \
|
||||
push {r4, r7, lr} ;\
|
||||
add r7, sp, #4
|
||||
#define CLEAR_FRAME_AND_RETURN \
|
||||
pop {r4, r7, pc}
|
||||
|
||||
.syntax unified
|
||||
.align 3
|
||||
DEFINE_COMPILERRT_FUNCTION(__modsi3)
|
||||
#if __ARM_ARCH_7S__
|
||||
tst r1, r1
|
||||
beq LOCAL_LABEL(divzero)
|
||||
sdiv r2, r0, r1
|
||||
mls r0, r2, r1, r0
|
||||
bx lr
|
||||
LOCAL_LABEL(divzero):
|
||||
mov r0, #0
|
||||
bx lr
|
||||
#else
|
||||
ESTABLISH_FRAME
|
||||
// Set aside the sign of the dividend.
|
||||
mov r4, r0
|
||||
// Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31).
|
||||
eor r2, r0, r0, asr #31
|
||||
eor r3, r1, r1, asr #31
|
||||
sub r0, r2, r0, asr #31
|
||||
sub r1, r3, r1, asr #31
|
||||
// abs(a) % abs(b)
|
||||
bl SYMBOL_NAME(__umodsi3)
|
||||
// Apply sign of dividend to result and return.
|
||||
eor r0, r0, r4, asr #31
|
||||
sub r0, r0, r4, asr #31
|
||||
CLEAR_FRAME_AND_RETURN
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- muldf3vfp.S - Implement muldf3vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __muldf3vfp(double a, double b);
|
||||
//
|
||||
// Multiplies two double precision floating point numbers using the Darwin
|
||||
// calling convention where double arguments are passsed in GPR pairs
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__muldf3vfp)
|
||||
vmov d6, r0, r1 // move first param from r0/r1 pair into d6
|
||||
vmov d7, r2, r3 // move second param from r2/r3 pair into d7
|
||||
vmul.f64 d6, d6, d7
|
||||
vmov r0, r1, d6 // move result back to r0/r1 pair
|
||||
bx lr
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- mulsf3vfp.S - Implement mulsf3vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern float __mulsf3vfp(float a, float b);
|
||||
//
|
||||
// Multiplies two single precision floating point numbers using the Darwin
|
||||
// calling convention where single arguments are passsed like 32-bit ints.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__mulsf3vfp)
|
||||
vmov s14, r0 // move first param from r0 into float register
|
||||
vmov s15, r1 // move second param from r1 into float register
|
||||
vmul.f32 s13, s14, s15
|
||||
vmov r0, s13 // move result back to r0
|
||||
bx lr
|
||||
@@ -0,0 +1,28 @@
|
||||
//===-- nedf2vfp.S - Implement nedf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __nedf2vfp(double a, double b);
|
||||
//
|
||||
// Returns zero if a and b are unequal and neither is NaN.
|
||||
// Uses Darwin calling convention where double precision arguments are passsed
|
||||
// like in GPR pairs.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__nedf2vfp)
|
||||
vmov d6, r0, r1 // load r0/r1 pair in double register
|
||||
vmov d7, r2, r3 // load r2/r3 pair in double register
|
||||
vcmp.f64 d6, d7
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movne r0, #1 // set result register to 0 if unequal
|
||||
moveq r0, #0
|
||||
bx lr
|
||||
@@ -0,0 +1,22 @@
|
||||
//===-- negdf2vfp.S - Implement negdf2vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __negdf2vfp(double a, double b);
|
||||
//
|
||||
// Returns the negation a double precision floating point numbers using the
|
||||
// Darwin calling convention where double arguments are passsed in GPR pairs.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__negdf2vfp)
|
||||
eor r1, r1, #-2147483648 // flip sign bit on double in r0/r1 pair
|
||||
bx lr
|
||||
@@ -0,0 +1,22 @@
|
||||
//===-- negsf2vfp.S - Implement negsf2vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern float __negsf2vfp(float a);
|
||||
//
|
||||
// Returns the negation of a single precision floating point numbers using the
|
||||
// Darwin calling convention where single arguments are passsed like 32-bit ints
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__negsf2vfp)
|
||||
eor r0, r0, #-2147483648 // flip sign bit on float in r0
|
||||
bx lr
|
||||
@@ -0,0 +1,29 @@
|
||||
//===-- nesf2vfp.S - Implement nesf2vfp -----------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __nesf2vfp(float a, float b);
|
||||
//
|
||||
// Returns one iff a != b and neither is NaN.
|
||||
// Uses Darwin calling convention where single precision arguments are passsed
|
||||
// like 32-bit ints
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__nesf2vfp)
|
||||
vmov s14, r0 // move from GPR 0 to float register
|
||||
vmov s15, r1 // move from GPR 1 to float register
|
||||
vcmp.f32 s14, s15
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movne r0, #1 // set result register to 1 if unequal
|
||||
moveq r0, #0
|
||||
bx lr
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
//===-- save_restore_regs.S - Implement save/restore* ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// When compiling C++ functions that need to handle thrown exceptions the
|
||||
// compiler is required to save all registers and call __Unwind_SjLj_Register
|
||||
// in the function prolog. But when compiling for thumb1, there are
|
||||
// no instructions to access the floating point registers, so the
|
||||
// compiler needs to add a call to the helper function _save_vfp_d8_d15_regs
|
||||
// written in ARM to save the float registers. In the epilog, the compiler
|
||||
// must also add a call to __restore_vfp_d8_d15_regs to restore those registers.
|
||||
//
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
|
||||
//
|
||||
// Restore registers d8-d15 from stack
|
||||
//
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_PRIVATE_FUNCTION(__restore_vfp_d8_d15_regs)
|
||||
vldmia sp!, {d8-d15} // pop registers d8-d15 off stack
|
||||
bx lr // return to prolog
|
||||
|
||||
|
||||
|
||||
// tell linker it can break up file at label boundaries
|
||||
.subsections_via_symbols
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
//===-- save_restore_regs.S - Implement save/restore* ---------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// When compiling C++ functions that need to handle thrown exceptions the
|
||||
// compiler is required to save all registers and call __Unwind_SjLj_Register
|
||||
// in the function prolog. But when compiling for thumb1, there are
|
||||
// no instructions to access the floating point registers, so the
|
||||
// compiler needs to add a call to the helper function _save_vfp_d8_d15_regs
|
||||
// written in ARM to save the float registers. In the epilog, the compiler
|
||||
// must also add a call to __restore_vfp_d8_d15_regs to restore those registers.
|
||||
//
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
|
||||
//
|
||||
// Save registers d8-d15 onto stack
|
||||
//
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_PRIVATE_FUNCTION(__save_vfp_d8_d15_regs)
|
||||
vstmdb sp!, {d8-d15} // push registers d8-d15 onto stack
|
||||
bx lr // return to prolog
|
||||
|
||||
// tell linker it can break up file at label boundaries
|
||||
.subsections_via_symbols
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
#
|
||||
# These are soft float functions which can be
|
||||
# aliased to the *vfp functions on arm processors
|
||||
# that support floating point instructions.
|
||||
#
|
||||
___adddf3vfp ___adddf3
|
||||
___addsf3vfp ___addsf3
|
||||
___divdf3vfp ___divdf3
|
||||
___divsf3vfp ___divsf3
|
||||
___extendsfdf2vfp ___extendsfdf2
|
||||
___fixdfsivfp ___fixdfsi
|
||||
___fixsfsivfp ___fixsfsi
|
||||
___floatsidfvfp ___floatsidf
|
||||
___floatsisfvfp ___floatsisf
|
||||
___muldf3vfp ___muldf3
|
||||
___mulsf3vfp ___mulsf3
|
||||
___subdf3vfp ___subdf3
|
||||
___subsf3vfp ___subsf3
|
||||
___truncdfsf2vfp ___truncdfsf2
|
||||
___floatunssidfvfp ___floatunsidf
|
||||
___floatunssisfvfp ___floatunsisf
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- subdf3vfp.S - Implement subdf3vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern double __subdf3vfp(double a, double b);
|
||||
//
|
||||
// Returns difference between two double precision floating point numbers using
|
||||
// the Darwin calling convention where double arguments are passsed in GPR pairs
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__subdf3vfp)
|
||||
vmov d6, r0, r1 // move first param from r0/r1 pair into d6
|
||||
vmov d7, r2, r3 // move second param from r2/r3 pair into d7
|
||||
vsub.f64 d6, d6, d7
|
||||
vmov r0, r1, d6 // move result back to r0/r1 pair
|
||||
bx lr
|
||||
@@ -0,0 +1,26 @@
|
||||
//===-- subsf3vfp.S - Implement subsf3vfp ---------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern float __subsf3vfp(float a, float b);
|
||||
//
|
||||
// Returns the difference between two single precision floating point numbers
|
||||
// using the Darwin calling convention where single arguments are passsed
|
||||
// like 32-bit ints.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__subsf3vfp)
|
||||
vmov s14, r0 // move first param from r0 into float register
|
||||
vmov s15, r1 // move second param from r1 into float register
|
||||
vsub.f32 s14, s14, s15
|
||||
vmov r0, s14 // move result back to r0
|
||||
bx lr
|
||||
@@ -0,0 +1,44 @@
|
||||
//===-- switch.S - Implement switch* --------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// When compiling switch statements in thumb mode, the compiler
|
||||
// can use these __switch* helper functions The compiler emits a blx to
|
||||
// the __switch* function followed by a table of displacements for each
|
||||
// case statement. On entry, R0 is the index into the table. The __switch*
|
||||
// function uses the return address in lr to find the start of the table.
|
||||
// The first entry in the table is the count of the entries in the table.
|
||||
// It then uses R0 to index into the table and get the displacement of the
|
||||
// address to jump to. If R0 is greater than the size of the table, it jumps
|
||||
// to the last entry in the table. Each displacement in the table is actually
|
||||
// the distance from lr to the label, thus making the tables PIC.
|
||||
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
|
||||
//
|
||||
// The table contains signed 2-byte sized elements which are 1/2 the distance
|
||||
// from lr to the target label.
|
||||
//
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch16)
|
||||
ldrh ip, [lr, #-1] // get first 16-bit word in table
|
||||
cmp r0, ip // compare with index
|
||||
add r0, lr, r0, lsl #1 // compute address of element in table
|
||||
ldrshcc r0, [r0, #1] // load 16-bit element if r0 is in range
|
||||
add ip, lr, ip, lsl #1 // compute address of last element in table
|
||||
ldrshhs r0, [ip, #1] // load 16-bit element if r0 out of range
|
||||
add ip, lr, r0, lsl #1 // compute label = lr + element*2
|
||||
bx ip // jump to computed label
|
||||
|
||||
// tell linker it can break up file at label boundaries
|
||||
.subsections_via_symbols
|
||||
@@ -0,0 +1,46 @@
|
||||
//===-- switch.S - Implement switch* --------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// When compiling switch statements in thumb mode, the compiler
|
||||
// can use these __switch* helper functions The compiler emits a blx to
|
||||
// the __switch* function followed by a table of displacements for each
|
||||
// case statement. On entry, R0 is the index into the table. The __switch*
|
||||
// function uses the return address in lr to find the start of the table.
|
||||
// The first entry in the table is the count of the entries in the table.
|
||||
// It then uses R0 to index into the table and get the displacement of the
|
||||
// address to jump to. If R0 is greater than the size of the table, it jumps
|
||||
// to the last entry in the table. Each displacement in the table is actually
|
||||
// the distance from lr to the label, thus making the tables PIC.
|
||||
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
|
||||
//
|
||||
// The table contains signed 4-byte sized elements which are the distance
|
||||
// from lr to the target label.
|
||||
//
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch32)
|
||||
ldr ip, [lr, #-1] // get first 32-bit word in table
|
||||
cmp r0, ip // compare with index
|
||||
add r0, lr, r0, lsl #2 // compute address of element in table
|
||||
ldrcc r0, [r0, #3] // load 32-bit element if r0 is in range
|
||||
add ip, lr, ip, lsl #2 // compute address of last element in table
|
||||
ldrcs r0, [ip, #3] // load 32-bit element if r0 out of range
|
||||
add ip, lr, r0 // compute label = lr + element
|
||||
bx ip // jump to computed label
|
||||
|
||||
|
||||
// tell linker it can break up file at label boundaries
|
||||
.subsections_via_symbols
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//===-- switch.S - Implement switch* --------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// When compiling switch statements in thumb mode, the compiler
|
||||
// can use these __switch* helper functions The compiler emits a blx to
|
||||
// the __switch* function followed by a table of displacements for each
|
||||
// case statement. On entry, R0 is the index into the table. The __switch*
|
||||
// function uses the return address in lr to find the start of the table.
|
||||
// The first entry in the table is the count of the entries in the table.
|
||||
// It then uses R0 to index into the table and get the displacement of the
|
||||
// address to jump to. If R0 is greater than the size of the table, it jumps
|
||||
// to the last entry in the table. Each displacement in the table is actually
|
||||
// the distance from lr to the label, thus making the tables PIC.
|
||||
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
|
||||
//
|
||||
// The table contains signed byte sized elements which are 1/2 the distance
|
||||
// from lr to the target label.
|
||||
//
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switch8)
|
||||
ldrb ip, [lr, #-1] // get first byte in table
|
||||
cmp r0, ip // signed compare with index
|
||||
ldrsbcc r0, [lr, r0] // get indexed byte out of table
|
||||
ldrsbhs r0, [lr, ip] // if out of range, use last entry in table
|
||||
add ip, lr, r0, lsl #1 // compute label = lr + element*2
|
||||
bx ip // jump to computed label
|
||||
|
||||
// tell linker it can break up file at label boundaries
|
||||
.subsections_via_symbols
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//===-- switch.S - Implement switch* --------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// When compiling switch statements in thumb mode, the compiler
|
||||
// can use these __switch* helper functions The compiler emits a blx to
|
||||
// the __switch* function followed by a table of displacements for each
|
||||
// case statement. On entry, R0 is the index into the table. The __switch*
|
||||
// function uses the return address in lr to find the start of the table.
|
||||
// The first entry in the table is the count of the entries in the table.
|
||||
// It then uses R0 to index into the table and get the displacement of the
|
||||
// address to jump to. If R0 is greater than the size of the table, it jumps
|
||||
// to the last entry in the table. Each displacement in the table is actually
|
||||
// the distance from lr to the label, thus making the tables PIC.
|
||||
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
|
||||
//
|
||||
// The table contains unsigned byte sized elements which are 1/2 the distance
|
||||
// from lr to the target label.
|
||||
//
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_PRIVATE_FUNCTION(__switchu8)
|
||||
ldrb ip, [lr, #-1] // get first byte in table
|
||||
cmp r0, ip // compare with index
|
||||
ldrbcc r0, [lr, r0] // get indexed byte out of table
|
||||
ldrbhs r0, [lr, ip] // if out of range, use last entry in table
|
||||
add ip, lr, r0, lsl #1 // compute label = lr + element*2
|
||||
bx ip // jump to computed label
|
||||
|
||||
// tell linker it can break up file at label boundaries
|
||||
.subsections_via_symbols
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
//===-- sync_synchronize - Implement memory barrier * ----------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// When compiling a use of the gcc built-in __sync_synchronize() in thumb1 mode
|
||||
// the compiler may emit a call to __sync_synchronize.
|
||||
// On Darwin the implementation jumps to an OS supplied function named
|
||||
// OSMemoryBarrier
|
||||
//
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
|
||||
#if __APPLE__
|
||||
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_PRIVATE_FUNCTION(__sync_synchronize)
|
||||
stmfd sp!, {r7, lr}
|
||||
add r7, sp, #0
|
||||
bl _OSMemoryBarrier
|
||||
ldmfd sp!, {r7, pc}
|
||||
|
||||
// tell linker it can break up file at label boundaries
|
||||
.subsections_via_symbols
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
//===-- truncdfsf2vfp.S - Implement truncdfsf2vfp -------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern float __truncdfsf2vfp(double a);
|
||||
//
|
||||
// Converts double precision float to signle precision result.
|
||||
// Uses Darwin calling convention where a double precision parameter is
|
||||
// passed in a R0/R1 pair and a signle precision result is returned in R0.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__truncdfsf2vfp)
|
||||
vmov d7, r0, r1 // load double from r0/r1 pair
|
||||
vcvt.f32.f64 s15, d7 // convert double to single (trucate precision)
|
||||
vmov r0, s15 // return result in r0
|
||||
bx lr
|
||||
@@ -0,0 +1,93 @@
|
||||
/*===-- udivmodsi4.S - 32-bit unsigned integer divide and modulus ---------===//
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===//
|
||||
*
|
||||
* This file implements the __udivmodsi4 (32-bit unsigned integer divide and
|
||||
* modulus) function for the ARM architecture. A naive digit-by-digit
|
||||
* computation is employed for simplicity.
|
||||
*
|
||||
*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
#define ESTABLISH_FRAME \
|
||||
push {r4, r7, lr} ;\
|
||||
add r7, sp, #4
|
||||
#define CLEAR_FRAME_AND_RETURN \
|
||||
pop {r4, r7, pc}
|
||||
|
||||
#define a r0
|
||||
#define b r1
|
||||
#define i r3
|
||||
#define r r4
|
||||
#define q ip
|
||||
#define one lr
|
||||
|
||||
.syntax unified
|
||||
.align 3
|
||||
DEFINE_COMPILERRT_FUNCTION(__udivmodsi4)
|
||||
#if __ARM_ARCH_7S__
|
||||
tst r1, r1
|
||||
beq LOCAL_LABEL(divzero)
|
||||
mov r3, r0
|
||||
udiv r0, r3, r1
|
||||
mls r1, r0, r1, r3
|
||||
str r1, [r2]
|
||||
bx lr
|
||||
LOCAL_LABEL(divzero):
|
||||
mov r0, #0
|
||||
bx lr
|
||||
#else
|
||||
// We use a simple digit by digit algorithm; before we get into the actual
|
||||
// divide loop, we must calculate the left-shift amount necessary to align
|
||||
// the MSB of the divisor with that of the dividend (If this shift is
|
||||
// negative, then the result is zero, and we early out). We also conjure a
|
||||
// bit mask of 1 to use in constructing the quotient, and initialize the
|
||||
// quotient to zero.
|
||||
ESTABLISH_FRAME
|
||||
clz r4, a
|
||||
tst b, b // detect divide-by-zero
|
||||
clz r3, b
|
||||
mov q, #0
|
||||
beq LOCAL_LABEL(return) // return 0 if b is zero.
|
||||
mov one, #1
|
||||
subs i, r3, r4
|
||||
blt LOCAL_LABEL(return) // return 0 if MSB(a) < MSB(b)
|
||||
|
||||
LOCAL_LABEL(mainLoop):
|
||||
// This loop basically implements the following:
|
||||
//
|
||||
// do {
|
||||
// if (a >= b << i) {
|
||||
// a -= b << i;
|
||||
// q |= 1 << i;
|
||||
// if (a == 0) break;
|
||||
// }
|
||||
// } while (--i)
|
||||
//
|
||||
// Note that this does not perform the final iteration (i == 0); by doing it
|
||||
// this way, we can merge the two branches which is a substantial win for
|
||||
// such a tight loop on current ARM architectures.
|
||||
subs r, a, b, lsl i
|
||||
orrhs q, q,one, lsl i
|
||||
movhs a, r
|
||||
subsne i, i, #1
|
||||
bhi LOCAL_LABEL(mainLoop)
|
||||
|
||||
// Do the final test subtraction and update of quotient (i == 0), as it is
|
||||
// not performed in the main loop.
|
||||
subs r, a, b
|
||||
orrhs q, #1
|
||||
movhs a, r
|
||||
|
||||
LOCAL_LABEL(return):
|
||||
// Store the remainder, and move the quotient to r0, then return.
|
||||
str a, [r2]
|
||||
mov r0, q
|
||||
CLEAR_FRAME_AND_RETURN
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
/*===-- udivsi3.S - 32-bit unsigned integer divide ------------------------===//
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===//
|
||||
*
|
||||
* This file implements the __udivsi3 (32-bit unsigned integer divide)
|
||||
* function for the ARM architecture. A naive digit-by-digit computation is
|
||||
* employed for simplicity.
|
||||
*
|
||||
*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
#define ESTABLISH_FRAME \
|
||||
push {r7, lr} ;\
|
||||
mov r7, sp
|
||||
#define CLEAR_FRAME_AND_RETURN \
|
||||
pop {r7, pc}
|
||||
|
||||
#define a r0
|
||||
#define b r1
|
||||
#define r r2
|
||||
#define i r3
|
||||
#define q ip
|
||||
#define one lr
|
||||
|
||||
.syntax unified
|
||||
.align 3
|
||||
// Ok, APCS and AAPCS agree on 32 bit args, so it's safe to use the same routine.
|
||||
DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_uidiv, __udivsi3)
|
||||
DEFINE_COMPILERRT_FUNCTION(__udivsi3)
|
||||
#if __ARM_ARCH_7S__
|
||||
tst r1,r1
|
||||
beq LOCAL_LABEL(divzero)
|
||||
udiv r0, r0, r1
|
||||
bx lr
|
||||
LOCAL_LABEL(divzero):
|
||||
mov r0,#0
|
||||
bx lr
|
||||
#else
|
||||
// We use a simple digit by digit algorithm; before we get into the actual
|
||||
// divide loop, we must calculate the left-shift amount necessary to align
|
||||
// the MSB of the divisor with that of the dividend (If this shift is
|
||||
// negative, then the result is zero, and we early out). We also conjure a
|
||||
// bit mask of 1 to use in constructing the quotient, and initialize the
|
||||
// quotient to zero.
|
||||
ESTABLISH_FRAME
|
||||
clz r2, a
|
||||
tst b, b // detect divide-by-zero
|
||||
clz r3, b
|
||||
mov q, #0
|
||||
beq LOCAL_LABEL(return) // return 0 if b is zero.
|
||||
mov one, #1
|
||||
subs i, r3, r2
|
||||
blt LOCAL_LABEL(return) // return 0 if MSB(a) < MSB(b)
|
||||
|
||||
LOCAL_LABEL(mainLoop):
|
||||
// This loop basically implements the following:
|
||||
//
|
||||
// do {
|
||||
// if (a >= b << i) {
|
||||
// a -= b << i;
|
||||
// q |= 1 << i;
|
||||
// if (a == 0) break;
|
||||
// }
|
||||
// } while (--i)
|
||||
//
|
||||
// Note that this does not perform the final iteration (i == 0); by doing it
|
||||
// this way, we can merge the two branches which is a substantial win for
|
||||
// such a tight loop on current ARM architectures.
|
||||
subs r, a, b, lsl i
|
||||
orrhs q, q,one, lsl i
|
||||
movhs a, r
|
||||
subsne i, i, #1
|
||||
bhi LOCAL_LABEL(mainLoop)
|
||||
|
||||
// Do the final test subtraction and update of quotient (i == 0), as it is
|
||||
// not performed in the main loop.
|
||||
subs r, a, b
|
||||
orrhs q, #1
|
||||
|
||||
LOCAL_LABEL(return):
|
||||
// Move the quotient to r0 and return.
|
||||
mov r0, q
|
||||
CLEAR_FRAME_AND_RETURN
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
/*===-- umodsi3.S - 32-bit unsigned integer modulus -----------------------===//
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===//
|
||||
*
|
||||
* This file implements the __umodsi3 (32-bit unsigned integer modulus)
|
||||
* function for the ARM architecture. A naive digit-by-digit computation is
|
||||
* employed for simplicity.
|
||||
*
|
||||
*===----------------------------------------------------------------------===*/
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
#define a r0
|
||||
#define b r1
|
||||
#define r r2
|
||||
#define i r3
|
||||
|
||||
.syntax unified
|
||||
.align 3
|
||||
DEFINE_COMPILERRT_FUNCTION(__umodsi3)
|
||||
#if __ARM_ARCH_7S__
|
||||
tst r1, r1
|
||||
beq LOCAL_LABEL(divzero)
|
||||
udiv r2, r0, r1
|
||||
mls r0, r2, r1, r0
|
||||
bx lr
|
||||
LOCAL_LABEL(divzero):
|
||||
mov r0, #0
|
||||
bx lr
|
||||
#else
|
||||
// We use a simple digit by digit algorithm; before we get into the actual
|
||||
// divide loop, we must calculate the left-shift amount necessary to align
|
||||
// the MSB of the divisor with that of the dividend.
|
||||
clz r2, a
|
||||
tst b, b // detect b == 0
|
||||
clz r3, b
|
||||
bxeq lr // return a if b == 0
|
||||
subs i, r3, r2
|
||||
bxlt lr // return a if MSB(a) < MSB(b)
|
||||
|
||||
LOCAL_LABEL(mainLoop):
|
||||
// This loop basically implements the following:
|
||||
//
|
||||
// do {
|
||||
// if (a >= b << i) {
|
||||
// a -= b << i;
|
||||
// if (a == 0) break;
|
||||
// }
|
||||
// } while (--i)
|
||||
//
|
||||
// Note that this does not perform the final iteration (i == 0); by doing it
|
||||
// this way, we can merge the two branches which is a substantial win for
|
||||
// such a tight loop on current ARM architectures.
|
||||
subs r, a, b, lsl i
|
||||
movhs a, r
|
||||
subsne i, i, #1
|
||||
bhi LOCAL_LABEL(mainLoop)
|
||||
|
||||
// Do the final test subtraction and update of remainder (i == 0), as it is
|
||||
// not performed in the main loop.
|
||||
subs r, a, b
|
||||
movhs a, r
|
||||
bx lr
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
//===-- unorddf2vfp.S - Implement unorddf2vfp ------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __unorddf2vfp(double a, double b);
|
||||
//
|
||||
// Returns one iff a or b is NaN
|
||||
// Uses Darwin calling convention where double precision arguments are passsed
|
||||
// like in GPR pairs.
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__unorddf2vfp)
|
||||
vmov d6, r0, r1 // load r0/r1 pair in double register
|
||||
vmov d7, r2, r3 // load r2/r3 pair in double register
|
||||
vcmp.f64 d6, d7
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movvs r0, #1 // set result register to 1 if "overflow" (any NaNs)
|
||||
movvc r0, #0
|
||||
bx lr
|
||||
@@ -0,0 +1,29 @@
|
||||
//===-- unordsf2vfp.S - Implement unordsf2vfp -----------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../assembly.h"
|
||||
|
||||
//
|
||||
// extern int __unordsf2vfp(float a, float b);
|
||||
//
|
||||
// Returns one iff a or b is NaN
|
||||
// Uses Darwin calling convention where single precision arguments are passsed
|
||||
// like 32-bit ints
|
||||
//
|
||||
.syntax unified
|
||||
.align 2
|
||||
DEFINE_COMPILERRT_FUNCTION(__unordsf2vfp)
|
||||
vmov s14, r0 // move from GPR 0 to float register
|
||||
vmov s15, r1 // move from GPR 1 to float register
|
||||
vcmp.f32 s14, s15
|
||||
vmrs apsr_nzcv, fpscr
|
||||
movvs r0, #1 // set result register to 1 if "overflow" (any NaNs)
|
||||
movvc r0, #0
|
||||
bx lr
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/* ====-- ashldi3.c - Implement __ashldi3 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __ashldi3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* Returns: a << b */
|
||||
|
||||
/* Precondition: 0 <= b < bits_in_dword */
|
||||
|
||||
ARM_EABI_FNALIAS(llsl, ashldi3)
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__ashldi3(di_int a, si_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 = (input.s.high << b) | (input.s.low >> (bits_in_word - b));
|
||||
}
|
||||
return result.all;
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/* ===-- ashlti3.c - Implement __ashlti3 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __ashlti3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if __x86_64
|
||||
|
||||
/* Returns: a << b */
|
||||
|
||||
/* Precondition: 0 <= b < bits_in_tword */
|
||||
|
||||
ti_int
|
||||
__ashlti3(ti_int a, si_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 = (input.s.high << b) | (input.s.low >> (bits_in_dword - b));
|
||||
}
|
||||
return result.all;
|
||||
}
|
||||
|
||||
#endif /* __x86_64 */
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*===-- ashrdi3.c - Implement __ashrdi3 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __ashrdi3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
/* Returns: arithmetic a >> b */
|
||||
|
||||
/* Precondition: 0 <= b < bits_in_dword */
|
||||
|
||||
ARM_EABI_FNALIAS(lasr, ashrdi3)
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__ashrdi3(di_int a, si_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 = (input.s.high << (bits_in_word - b)) | (input.s.low >> b);
|
||||
}
|
||||
return result.all;
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/* ===-- ashrti3.c - Implement __ashrti3 -----------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __ashrti3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if __x86_64
|
||||
|
||||
/* Returns: arithmetic a >> b */
|
||||
|
||||
/* Precondition: 0 <= b < bits_in_tword */
|
||||
|
||||
ti_int
|
||||
__ashrti3(ti_int a, si_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 = (input.s.high << (bits_in_dword - b)) | (input.s.low >> b);
|
||||
}
|
||||
return result.all;
|
||||
}
|
||||
|
||||
#endif /* __x86_64 */
|
||||
@@ -0,0 +1,73 @@
|
||||
/* ===-- assembly.h - compiler-rt assembler support macros -----------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* 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
|
||||
|
||||
#if defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__)
|
||||
#define SEPARATOR @
|
||||
#else
|
||||
#define SEPARATOR ;
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#define HIDDEN_DIRECTIVE .private_extern
|
||||
#define LOCAL_LABEL(name) L_##name
|
||||
#define FILE_LEVEL_DIRECTIVE .subsections_via_symbols
|
||||
#else
|
||||
#define HIDDEN_DIRECTIVE .hidden
|
||||
#define LOCAL_LABEL(name) .L_##name
|
||||
#define FILE_LEVEL_DIRECTIVE
|
||||
#endif
|
||||
|
||||
#define GLUE2(a, b) a ## b
|
||||
#define GLUE(a, b) GLUE2(a, b)
|
||||
#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name)
|
||||
|
||||
#ifdef VISIBILITY_HIDDEN
|
||||
#define DECLARE_SYMBOL_VISIBILITY(name) \
|
||||
HIDDEN_DIRECTIVE SYMBOL_NAME(name) SEPARATOR
|
||||
#else
|
||||
#define DECLARE_SYMBOL_VISIBILITY(name)
|
||||
#endif
|
||||
|
||||
#define DEFINE_COMPILERRT_FUNCTION(name) \
|
||||
FILE_LEVEL_DIRECTIVE SEPARATOR \
|
||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
||||
DECLARE_SYMBOL_VISIBILITY(name) \
|
||||
SYMBOL_NAME(name):
|
||||
|
||||
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \
|
||||
.globl SYMBOL_NAME(name) SEPARATOR \
|
||||
HIDDEN_DIRECTIVE SYMBOL_NAME(name) SEPARATOR \
|
||||
SYMBOL_NAME(name):
|
||||
|
||||
#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \
|
||||
.globl name SEPARATOR \
|
||||
HIDDEN_DIRECTIVE name SEPARATOR \
|
||||
name:
|
||||
|
||||
#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \
|
||||
.globl SYMBOL_NAME(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
|
||||
|
||||
#endif /* COMPILERRT_ASSEMBLY_H */
|
||||
+337
@@ -0,0 +1,337 @@
|
||||
/*===-- atomic.c - Implement support functions for atomic operations.------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===
|
||||
*
|
||||
* atomic.c defines a set of functions for performing atomic accesses on
|
||||
* arbitrary-sized memory locations. This design uses locks that should
|
||||
* be fast in the uncontended case, for two reasons:
|
||||
*
|
||||
* 1) This code must work with C programs that do not link to anything
|
||||
* (including pthreads) and so it should not depend on any pthread
|
||||
* functions.
|
||||
* 2) Atomic operations, rather than explicit mutexes, are most commonly used
|
||||
* on code where contended operations are rate.
|
||||
*
|
||||
* To avoid needing a per-object lock, this code allocates an array of
|
||||
* locks and hashes the object pointers to find the one that it should use.
|
||||
* For operations that must be atomic on two locations, the lower lock is
|
||||
* always acquired first, to avoid deadlock.
|
||||
*
|
||||
*===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
// Clang objects if you redefine a builtin. This little hack allows us to
|
||||
// define a function with the same name as an intrinsic.
|
||||
#if __APPLE__
|
||||
// mach-o has extra leading underscore
|
||||
#pragma redefine_extname __atomic_load_c ___atomic_load
|
||||
#pragma redefine_extname __atomic_store_c ___atomic_store
|
||||
#pragma redefine_extname __atomic_exchange_c ___atomic_exchange
|
||||
#pragma redefine_extname __atomic_compare_exchange_c ___atomic_compare_exchange
|
||||
#else
|
||||
#pragma redefine_extname __atomic_load_c __atomic_load
|
||||
#pragma redefine_extname __atomic_store_c __atomic_store
|
||||
#pragma redefine_extname __atomic_exchange_c __atomic_exchange
|
||||
#pragma redefine_extname __atomic_compare_exchange_c __atomic_compare_exchange
|
||||
#endif
|
||||
|
||||
/// Number of locks. This allocates one page on 32-bit platforms, two on
|
||||
/// 64-bit. This can be specified externally if a different trade between
|
||||
/// memory usage and contention probability is required for a given platform.
|
||||
#ifndef SPINLOCK_COUNT
|
||||
#define SPINLOCK_COUNT (1<<10)
|
||||
#endif
|
||||
static const long SPINLOCK_MASK = SPINLOCK_COUNT - 1;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Platform-specific lock implementation. Falls back to spinlocks if none is
|
||||
// defined. Each platform should define the Lock type, and corresponding
|
||||
// lock() and unlock() functions.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef __FreeBSD__
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <machine/atomic.h>
|
||||
#include <sys/umtx.h>
|
||||
typedef struct _usem Lock;
|
||||
inline static void unlock(Lock *l) {
|
||||
__c11_atomic_store((_Atomic(uint32_t)*)&l->_count, 1, __ATOMIC_RELEASE);
|
||||
__c11_atomic_thread_fence(__ATOMIC_SEQ_CST);
|
||||
if (l->_has_waiters)
|
||||
_umtx_op(l, UMTX_OP_SEM_WAKE, 1, 0, 0);
|
||||
}
|
||||
inline static void lock(Lock *l) {
|
||||
uint32_t old = 1;
|
||||
while (!__c11_atomic_compare_exchange_weak((_Atomic(uint32_t)*)&l->_count, &old,
|
||||
0, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
|
||||
_umtx_op(l, UMTX_OP_SEM_WAIT, 0, 0, 0);
|
||||
old = 1;
|
||||
}
|
||||
}
|
||||
/// locks for atomic operations
|
||||
static Lock locks[SPINLOCK_COUNT] = { [0 ... SPINLOCK_COUNT-1] = {0,1,0} };
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#include <libkern/OSAtomic.h>
|
||||
typedef OSSpinLock Lock;
|
||||
inline static void unlock(Lock *l) {
|
||||
OSSpinLockUnlock(l);
|
||||
}
|
||||
/// Locks a lock. In the current implementation, this is potentially
|
||||
/// unbounded in the contended case.
|
||||
inline static void lock(Lock *l) {
|
||||
OSSpinLockLock(l);
|
||||
}
|
||||
static Lock locks[SPINLOCK_COUNT]; // initialized to OS_SPINLOCK_INIT which is 0
|
||||
|
||||
#else
|
||||
typedef _Atomic(uintptr_t) Lock;
|
||||
/// Unlock a lock. This is a release operation.
|
||||
inline static void unlock(Lock *l) {
|
||||
__c11_atomic_store(l, 0, __ATOMIC_RELEASE);
|
||||
}
|
||||
/// Locks a lock. In the current implementation, this is potentially
|
||||
/// unbounded in the contended case.
|
||||
inline static void lock(Lock *l) {
|
||||
uintptr_t old = 0;
|
||||
while (!__c11_atomic_compare_exchange_weak(l, &old, 1, __ATOMIC_ACQUIRE,
|
||||
__ATOMIC_RELAXED))
|
||||
old = 0;
|
||||
}
|
||||
/// locks for atomic operations
|
||||
static Lock locks[SPINLOCK_COUNT];
|
||||
#endif
|
||||
|
||||
|
||||
/// Returns a lock to use for a given pointer.
|
||||
static inline Lock *lock_for_pointer(void *ptr) {
|
||||
intptr_t hash = (intptr_t)ptr;
|
||||
// Disregard the lowest 4 bits. We want all values that may be part of the
|
||||
// same memory operation to hash to the same value and therefore use the same
|
||||
// lock.
|
||||
hash >>= 4;
|
||||
// Use the next bits as the basis for the hash
|
||||
intptr_t low = hash & SPINLOCK_MASK;
|
||||
// Now use the high(er) set of bits to perturb the hash, so that we don't
|
||||
// get collisions from atomic fields in a single object
|
||||
hash >>= 16;
|
||||
hash ^= low;
|
||||
// Return a pointer to the word to use
|
||||
return locks + (hash & SPINLOCK_MASK);
|
||||
}
|
||||
|
||||
/// Macros for determining whether a size is lock free. Clang can not yet
|
||||
/// codegen __atomic_is_lock_free(16), so for now we assume 16-byte values are
|
||||
/// not lock free.
|
||||
#define IS_LOCK_FREE_1 __c11_atomic_is_lock_free(1)
|
||||
#define IS_LOCK_FREE_2 __c11_atomic_is_lock_free(2)
|
||||
#define IS_LOCK_FREE_4 __c11_atomic_is_lock_free(4)
|
||||
#define IS_LOCK_FREE_8 __c11_atomic_is_lock_free(8)
|
||||
#define IS_LOCK_FREE_16 0
|
||||
|
||||
/// Macro that calls the compiler-generated lock-free versions of functions
|
||||
/// when they exist.
|
||||
#define LOCK_FREE_CASES() \
|
||||
do {\
|
||||
switch (size) {\
|
||||
case 2:\
|
||||
if (IS_LOCK_FREE_2) {\
|
||||
LOCK_FREE_ACTION(uint16_t);\
|
||||
}\
|
||||
case 4:\
|
||||
if (IS_LOCK_FREE_4) {\
|
||||
LOCK_FREE_ACTION(uint32_t);\
|
||||
}\
|
||||
case 8:\
|
||||
if (IS_LOCK_FREE_8) {\
|
||||
LOCK_FREE_ACTION(uint64_t);\
|
||||
}\
|
||||
case 16:\
|
||||
if (IS_LOCK_FREE_16) {\
|
||||
/* FIXME: __uint128_t isn't available on 32 bit platforms.
|
||||
LOCK_FREE_ACTION(__uint128_t);*/\
|
||||
}\
|
||||
}\
|
||||
} while (0)
|
||||
|
||||
|
||||
/// An atomic load operation. This is atomic with respect to the source
|
||||
/// pointer only.
|
||||
void __atomic_load_c(int size, void *src, void *dest, int model) {
|
||||
#define LOCK_FREE_ACTION(type) \
|
||||
*((type*)dest) = __c11_atomic_load((_Atomic(type)*)src, model);\
|
||||
return;
|
||||
LOCK_FREE_CASES();
|
||||
#undef LOCK_FREE_ACTION
|
||||
Lock *l = lock_for_pointer(src);
|
||||
lock(l);
|
||||
memcpy(dest, src, size);
|
||||
unlock(l);
|
||||
}
|
||||
|
||||
/// An atomic store operation. This is atomic with respect to the destination
|
||||
/// pointer only.
|
||||
void __atomic_store_c(int size, void *dest, void *src, int model) {
|
||||
#define LOCK_FREE_ACTION(type) \
|
||||
__c11_atomic_store((_Atomic(type)*)dest, *(type*)dest, model);\
|
||||
return;
|
||||
LOCK_FREE_CASES();
|
||||
#undef LOCK_FREE_ACTION
|
||||
Lock *l = lock_for_pointer(dest);
|
||||
lock(l);
|
||||
memcpy(dest, src, size);
|
||||
unlock(l);
|
||||
}
|
||||
|
||||
/// Atomic compare and exchange operation. If the value at *ptr is identical
|
||||
/// to the value at *expected, then this copies value at *desired to *ptr. If
|
||||
/// they are not, then this stores the current value from *ptr in *expected.
|
||||
///
|
||||
/// This function returns 1 if the exchange takes place or 0 if it fails.
|
||||
int __atomic_compare_exchange_c(int size, void *ptr, void *expected,
|
||||
void *desired, int success, int failure) {
|
||||
#define LOCK_FREE_ACTION(type) \
|
||||
return __c11_atomic_compare_exchange_strong((_Atomic(type)*)ptr, (type*)expected,\
|
||||
*(type*)desired, success, failure)
|
||||
LOCK_FREE_CASES();
|
||||
#undef LOCK_FREE_ACTION
|
||||
Lock *l = lock_for_pointer(ptr);
|
||||
lock(l);
|
||||
if (memcmp(ptr, expected, size) == 0) {
|
||||
memcpy(ptr, desired, size);
|
||||
unlock(l);
|
||||
return 1;
|
||||
}
|
||||
memcpy(expected, ptr, size);
|
||||
unlock(l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Performs an atomic exchange operation between two pointers. This is atomic
|
||||
/// with respect to the target address.
|
||||
void __atomic_exchange_c(int size, void *ptr, void *val, void *old, int model) {
|
||||
#define LOCK_FREE_ACTION(type) \
|
||||
*(type*)old = __c11_atomic_exchange((_Atomic(type)*)ptr, *(type*)val,\
|
||||
model);\
|
||||
return;
|
||||
LOCK_FREE_CASES();
|
||||
#undef LOCK_FREE_ACTION
|
||||
Lock *l = lock_for_pointer(ptr);
|
||||
lock(l);
|
||||
memcpy(old, ptr, size);
|
||||
memcpy(ptr, val, size);
|
||||
unlock(l);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Where the size is known at compile time, the compiler may emit calls to
|
||||
// specialised versions of the above functions.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define OPTIMISED_CASES\
|
||||
OPTIMISED_CASE(1, IS_LOCK_FREE_1, uint8_t)\
|
||||
OPTIMISED_CASE(2, IS_LOCK_FREE_2, uint16_t)\
|
||||
OPTIMISED_CASE(4, IS_LOCK_FREE_4, uint32_t)\
|
||||
OPTIMISED_CASE(8, IS_LOCK_FREE_8, uint64_t)\
|
||||
/* FIXME: __uint128_t isn't available on 32 bit platforms.
|
||||
OPTIMISED_CASE(16, IS_LOCK_FREE_16, __uint128_t)*/\
|
||||
|
||||
#define OPTIMISED_CASE(n, lockfree, type)\
|
||||
type __atomic_load_##n(type *src, int model) {\
|
||||
if (lockfree)\
|
||||
return __c11_atomic_load((_Atomic(type)*)src, model);\
|
||||
Lock *l = lock_for_pointer(src);\
|
||||
lock(l);\
|
||||
type val = *src;\
|
||||
unlock(l);\
|
||||
return val;\
|
||||
}
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
|
||||
#define OPTIMISED_CASE(n, lockfree, type)\
|
||||
void __atomic_store_##n(type *dest, type val, int model) {\
|
||||
if (lockfree) {\
|
||||
__c11_atomic_store((_Atomic(type)*)dest, val, model);\
|
||||
return;\
|
||||
}\
|
||||
Lock *l = lock_for_pointer(dest);\
|
||||
lock(l);\
|
||||
*dest = val;\
|
||||
unlock(l);\
|
||||
return;\
|
||||
}
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
|
||||
#define OPTIMISED_CASE(n, lockfree, type)\
|
||||
type __atomic_exchange_##n(type *dest, type val, int model) {\
|
||||
if (lockfree)\
|
||||
return __c11_atomic_exchange((_Atomic(type)*)dest, val, model);\
|
||||
Lock *l = lock_for_pointer(dest);\
|
||||
lock(l);\
|
||||
type tmp = *dest;\
|
||||
*dest = val;\
|
||||
unlock(l);\
|
||||
return tmp;\
|
||||
}
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
|
||||
#define OPTIMISED_CASE(n, lockfree, type)\
|
||||
int __atomic_compare_exchange_##n(type *ptr, type *expected, type desired,\
|
||||
int success, int failure) {\
|
||||
if (lockfree)\
|
||||
return __c11_atomic_compare_exchange_strong((_Atomic(type)*)ptr, expected, desired,\
|
||||
success, failure);\
|
||||
Lock *l = lock_for_pointer(ptr);\
|
||||
lock(l);\
|
||||
if (*ptr == *expected) {\
|
||||
*ptr = desired;\
|
||||
unlock(l);\
|
||||
return 1;\
|
||||
}\
|
||||
*expected = *ptr;\
|
||||
unlock(l);\
|
||||
return 0;\
|
||||
}
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Atomic read-modify-write operations for integers of various sizes.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#define ATOMIC_RMW(n, lockfree, type, opname, op) \
|
||||
type __atomic_fetch_##opname##_##n(type *ptr, type val, int model) {\
|
||||
if (lockfree) \
|
||||
return __c11_atomic_fetch_##opname((_Atomic(type)*)ptr, val, model);\
|
||||
Lock *l = lock_for_pointer(ptr);\
|
||||
lock(l);\
|
||||
type tmp = *ptr;\
|
||||
*ptr = tmp op val;\
|
||||
unlock(l);\
|
||||
return tmp;\
|
||||
}
|
||||
|
||||
#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, add, +)
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, sub, -)
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, and, &)
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, or, |)
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
#define OPTIMISED_CASE(n, lockfree, type) ATOMIC_RMW(n, lockfree, type, xor, ^)
|
||||
OPTIMISED_CASES
|
||||
#undef OPTIMISED_CASE
|
||||
@@ -0,0 +1,40 @@
|
||||
/* ===-- clear_cache.c - Implement __clear_cache ---------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if __APPLE__
|
||||
#include <libkern/OSCacheControl.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The compiler generates calls to __clear_cache() when creating
|
||||
* trampoline functions on the stack for use with nested functions.
|
||||
* It is expected to invalidate the instruction cache for the
|
||||
* specified range.
|
||||
*/
|
||||
|
||||
void __clear_cache(void* start, void* end)
|
||||
{
|
||||
#if __i386__ || __x86_64__
|
||||
/*
|
||||
* Intel processors have a unified instruction and data cache
|
||||
* so there is nothing to do
|
||||
*/
|
||||
#else
|
||||
#if __APPLE__
|
||||
/* On Darwin, sys_icache_invalidate() provides this functionality */
|
||||
sys_icache_invalidate(start, end-start);
|
||||
#else
|
||||
compilerrt_abort();
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/* ===-- clzdi2.c - Implement __clzdi2 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* 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 si_int
|
||||
__clzdi2(di_int a)
|
||||
{
|
||||
dwords x;
|
||||
x.all = a;
|
||||
const si_int f = -(x.s.high == 0);
|
||||
return __builtin_clz((x.s.high & ~f) | (x.s.low & f)) +
|
||||
(f & ((si_int)(sizeof(si_int) * CHAR_BIT)));
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/* ===-- clzsi2.c - Implement __clzsi2 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* 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 si_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));
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/* ===-- clzti2.c - Implement __clzti2 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __clzti2 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if __x86_64
|
||||
|
||||
/* Returns: the number of leading 0-bits */
|
||||
|
||||
/* Precondition: a != 0 */
|
||||
|
||||
si_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 /* __x86_64 */
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/* ===-- cmpdi2.c - Implement __cmpdi2 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* 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;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/* ===-- cmpti2.c - Implement __cmpti2 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __cmpti2 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if __x86_64
|
||||
|
||||
/* Returns: if (a < b) returns 0
|
||||
* if (a == b) returns 1
|
||||
* if (a > b) returns 2
|
||||
*/
|
||||
|
||||
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
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
//===-- lib/comparedf2.c - Double-precision comparisons -----------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// // 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"
|
||||
|
||||
enum LE_RESULT {
|
||||
LE_LESS = -1,
|
||||
LE_EQUAL = 0,
|
||||
LE_GREATER = 1,
|
||||
LE_UNORDERED = 1
|
||||
};
|
||||
|
||||
enum LE_RESULT __ledf2(fp_t a, fp_t b) {
|
||||
|
||||
const srep_t aInt = toRep(a);
|
||||
const srep_t bInt = toRep(b);
|
||||
const rep_t aAbs = aInt & absMask;
|
||||
const rep_t bAbs = bInt & absMask;
|
||||
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
|
||||
|
||||
// If a and b are both zeros, they are equal.
|
||||
if ((aAbs | bAbs) == 0) return LE_EQUAL;
|
||||
|
||||
// If at least one of a and b is positive, we get the same result comparing
|
||||
// a and b as signed integers as we would with a floating-point compare.
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) return LE_LESS;
|
||||
else if (aInt == bInt) return LE_EQUAL;
|
||||
else return LE_GREATER;
|
||||
}
|
||||
|
||||
// Otherwise, both are negative, so we need to flip the sense of the
|
||||
// comparison to get the correct result. (This assumes a twos- or ones-
|
||||
// complement integer representation; if integers are represented in a
|
||||
// sign-magnitude representation, then this flip is incorrect).
|
||||
else {
|
||||
if (aInt > bInt) return LE_LESS;
|
||||
else if (aInt == bInt) return LE_EQUAL;
|
||||
else return LE_GREATER;
|
||||
}
|
||||
}
|
||||
|
||||
enum GE_RESULT {
|
||||
GE_LESS = -1,
|
||||
GE_EQUAL = 0,
|
||||
GE_GREATER = 1,
|
||||
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
|
||||
};
|
||||
|
||||
enum GE_RESULT __gedf2(fp_t a, fp_t b) {
|
||||
|
||||
const srep_t aInt = toRep(a);
|
||||
const srep_t bInt = toRep(b);
|
||||
const rep_t aAbs = aInt & absMask;
|
||||
const rep_t bAbs = bInt & absMask;
|
||||
|
||||
if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
|
||||
if ((aAbs | bAbs) == 0) return GE_EQUAL;
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) return GE_LESS;
|
||||
else if (aInt == bInt) return GE_EQUAL;
|
||||
else return GE_GREATER;
|
||||
} else {
|
||||
if (aInt > bInt) return GE_LESS;
|
||||
else if (aInt == bInt) return GE_EQUAL;
|
||||
else return GE_GREATER;
|
||||
}
|
||||
}
|
||||
|
||||
ARM_EABI_FNALIAS(dcmpun, unorddf2)
|
||||
|
||||
int __unorddf2(fp_t a, fp_t b) {
|
||||
const rep_t aAbs = toRep(a) & absMask;
|
||||
const rep_t bAbs = toRep(b) & absMask;
|
||||
return aAbs > infRep || bAbs > infRep;
|
||||
}
|
||||
|
||||
// The following are alternative names for the preceeding routines.
|
||||
|
||||
enum LE_RESULT __eqdf2(fp_t a, fp_t b) {
|
||||
return __ledf2(a, b);
|
||||
}
|
||||
|
||||
enum LE_RESULT __ltdf2(fp_t a, fp_t b) {
|
||||
return __ledf2(a, b);
|
||||
}
|
||||
|
||||
enum LE_RESULT __nedf2(fp_t a, fp_t b) {
|
||||
return __ledf2(a, b);
|
||||
}
|
||||
|
||||
enum GE_RESULT __gtdf2(fp_t a, fp_t b) {
|
||||
return __gedf2(a, b);
|
||||
}
|
||||
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
//===-- lib/comparesf2.c - Single-precision comparisons -----------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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"
|
||||
|
||||
enum LE_RESULT {
|
||||
LE_LESS = -1,
|
||||
LE_EQUAL = 0,
|
||||
LE_GREATER = 1,
|
||||
LE_UNORDERED = 1
|
||||
};
|
||||
|
||||
enum LE_RESULT __lesf2(fp_t a, fp_t b) {
|
||||
|
||||
const srep_t aInt = toRep(a);
|
||||
const srep_t bInt = toRep(b);
|
||||
const rep_t aAbs = aInt & absMask;
|
||||
const rep_t bAbs = bInt & absMask;
|
||||
|
||||
// If either a or b is NaN, they are unordered.
|
||||
if (aAbs > infRep || bAbs > infRep) return LE_UNORDERED;
|
||||
|
||||
// If a and b are both zeros, they are equal.
|
||||
if ((aAbs | bAbs) == 0) return LE_EQUAL;
|
||||
|
||||
// If at least one of a and b is positive, we get the same result comparing
|
||||
// a and b as signed integers as we would with a fp_ting-point compare.
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) return LE_LESS;
|
||||
else if (aInt == bInt) return LE_EQUAL;
|
||||
else return LE_GREATER;
|
||||
}
|
||||
|
||||
// Otherwise, both are negative, so we need to flip the sense of the
|
||||
// comparison to get the correct result. (This assumes a twos- or ones-
|
||||
// complement integer representation; if integers are represented in a
|
||||
// sign-magnitude representation, then this flip is incorrect).
|
||||
else {
|
||||
if (aInt > bInt) return LE_LESS;
|
||||
else if (aInt == bInt) return LE_EQUAL;
|
||||
else return LE_GREATER;
|
||||
}
|
||||
}
|
||||
|
||||
enum GE_RESULT {
|
||||
GE_LESS = -1,
|
||||
GE_EQUAL = 0,
|
||||
GE_GREATER = 1,
|
||||
GE_UNORDERED = -1 // Note: different from LE_UNORDERED
|
||||
};
|
||||
|
||||
enum GE_RESULT __gesf2(fp_t a, fp_t b) {
|
||||
|
||||
const srep_t aInt = toRep(a);
|
||||
const srep_t bInt = toRep(b);
|
||||
const rep_t aAbs = aInt & absMask;
|
||||
const rep_t bAbs = bInt & absMask;
|
||||
|
||||
if (aAbs > infRep || bAbs > infRep) return GE_UNORDERED;
|
||||
if ((aAbs | bAbs) == 0) return GE_EQUAL;
|
||||
if ((aInt & bInt) >= 0) {
|
||||
if (aInt < bInt) return GE_LESS;
|
||||
else if (aInt == bInt) return GE_EQUAL;
|
||||
else return GE_GREATER;
|
||||
} else {
|
||||
if (aInt > bInt) return GE_LESS;
|
||||
else if (aInt == bInt) return GE_EQUAL;
|
||||
else return GE_GREATER;
|
||||
}
|
||||
}
|
||||
|
||||
ARM_EABI_FNALIAS(fcmpun, unordsf2)
|
||||
|
||||
int __unordsf2(fp_t a, fp_t b) {
|
||||
const rep_t aAbs = toRep(a) & absMask;
|
||||
const rep_t bAbs = toRep(b) & absMask;
|
||||
return aAbs > infRep || bAbs > infRep;
|
||||
}
|
||||
|
||||
// The following are alternative names for the preceeding routines.
|
||||
|
||||
enum LE_RESULT __eqsf2(fp_t a, fp_t b) {
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
enum LE_RESULT __ltsf2(fp_t a, fp_t b) {
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
enum LE_RESULT __nesf2(fp_t a, fp_t b) {
|
||||
return __lesf2(a, b);
|
||||
}
|
||||
|
||||
enum GE_RESULT __gtsf2(fp_t a, fp_t b) {
|
||||
return __gesf2(a, b);
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/* ===-- ctzdi2.c - Implement __ctzdi2 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* 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 si_int
|
||||
__ctzdi2(di_int a)
|
||||
{
|
||||
dwords x;
|
||||
x.all = a;
|
||||
const si_int f = -(x.s.low == 0);
|
||||
return __builtin_ctz((x.s.high & f) | (x.s.low & ~f)) +
|
||||
(f & ((si_int)(sizeof(si_int) * CHAR_BIT)));
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/* ===-- ctzsi2.c - Implement __ctzsi2 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* 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 si_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));
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/* ===-- ctzti2.c - Implement __ctzti2 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __ctzti2 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if __x86_64
|
||||
|
||||
/* Returns: the number of trailing 0-bits */
|
||||
|
||||
/* Precondition: a != 0 */
|
||||
|
||||
si_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
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/* ===-- divdc3.c - Implement __divdc3 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __divdc3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
#include "int_math.h"
|
||||
|
||||
/* Returns: the quotient of (a + ib) / (c + id) */
|
||||
|
||||
double _Complex
|
||||
__divdc3(double __a, double __b, double __c, double __d)
|
||||
{
|
||||
int __ilogbw = 0;
|
||||
double __logbw = crt_logb(crt_fmax(crt_fabs(__c), crt_fabs(__d)));
|
||||
if (crt_isfinite(__logbw))
|
||||
{
|
||||
__ilogbw = (int)__logbw;
|
||||
__c = crt_scalbn(__c, -__ilogbw);
|
||||
__d = crt_scalbn(__d, -__ilogbw);
|
||||
}
|
||||
double __denom = __c * __c + __d * __d;
|
||||
double _Complex z;
|
||||
__real__ z = crt_scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
__imag__ z = crt_scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(__real__ z) && crt_isnan(__imag__ z))
|
||||
{
|
||||
if ((__denom == 0.0) && (!crt_isnan(__a) || !crt_isnan(__b)))
|
||||
{
|
||||
__real__ z = crt_copysign(CRT_INFINITY, __c) * __a;
|
||||
__imag__ z = crt_copysign(CRT_INFINITY, __c) * __b;
|
||||
}
|
||||
else if ((crt_isinf(__a) || crt_isinf(__b)) &&
|
||||
crt_isfinite(__c) && crt_isfinite(__d))
|
||||
{
|
||||
__a = crt_copysign(crt_isinf(__a) ? 1.0 : 0.0, __a);
|
||||
__b = crt_copysign(crt_isinf(__b) ? 1.0 : 0.0, __b);
|
||||
__real__ z = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
__imag__ z = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
}
|
||||
else if (crt_isinf(__logbw) && __logbw > 0.0 &&
|
||||
crt_isfinite(__a) && crt_isfinite(__b))
|
||||
{
|
||||
__c = crt_copysign(crt_isinf(__c) ? 1.0 : 0.0, __c);
|
||||
__d = crt_copysign(crt_isinf(__d) ? 1.0 : 0.0, __d);
|
||||
__real__ z = 0.0 * (__a * __c + __b * __d);
|
||||
__imag__ z = 0.0 * (__b * __c - __a * __d);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
//===-- lib/divdf3.c - Double-precision division ------------------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements double-precision soft-float division
|
||||
// with the IEEE-754 default rounding (to nearest, ties to even).
|
||||
//
|
||||
// For simplicity, this implementation currently flushes denormals to zero.
|
||||
// It should be a fairly straightforward exercise to implement gradual
|
||||
// underflow with correct rounding.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DOUBLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
ARM_EABI_FNALIAS(ddiv, divdf3)
|
||||
|
||||
fp_t __divdf3(fp_t a, fp_t b) {
|
||||
|
||||
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
|
||||
const unsigned int bExponent = toRep(b) >> significandBits & maxExponent;
|
||||
const rep_t quotientSign = (toRep(a) ^ toRep(b)) & signBit;
|
||||
|
||||
rep_t aSignificand = toRep(a) & significandMask;
|
||||
rep_t bSignificand = toRep(b) & significandMask;
|
||||
int scale = 0;
|
||||
|
||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||
if (aExponent-1U >= maxExponent-1U || bExponent-1U >= maxExponent-1U) {
|
||||
|
||||
const rep_t aAbs = toRep(a) & absMask;
|
||||
const rep_t bAbs = toRep(b) & absMask;
|
||||
|
||||
// NaN / anything = qNaN
|
||||
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
|
||||
// anything / NaN = qNaN
|
||||
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
|
||||
|
||||
if (aAbs == infRep) {
|
||||
// infinity / infinity = NaN
|
||||
if (bAbs == infRep) return fromRep(qnanRep);
|
||||
// infinity / anything else = +/- infinity
|
||||
else return fromRep(aAbs | quotientSign);
|
||||
}
|
||||
|
||||
// anything else / infinity = +/- 0
|
||||
if (bAbs == infRep) return fromRep(quotientSign);
|
||||
|
||||
if (!aAbs) {
|
||||
// zero / zero = NaN
|
||||
if (!bAbs) return fromRep(qnanRep);
|
||||
// zero / anything else = +/- zero
|
||||
else return fromRep(quotientSign);
|
||||
}
|
||||
// anything else / zero = +/- infinity
|
||||
if (!bAbs) return fromRep(infRep | quotientSign);
|
||||
|
||||
// one or both of a or b is denormal, the other (if applicable) is a
|
||||
// normal number. Renormalize one or both of a and b, and set scale to
|
||||
// include the necessary exponent adjustment.
|
||||
if (aAbs < implicitBit) scale += normalize(&aSignificand);
|
||||
if (bAbs < implicitBit) scale -= normalize(&bSignificand);
|
||||
}
|
||||
|
||||
// Or in the implicit significand bit. (If we fell through from the
|
||||
// denormal path it was already set by normalize( ), but setting it twice
|
||||
// won't hurt anything.)
|
||||
aSignificand |= implicitBit;
|
||||
bSignificand |= implicitBit;
|
||||
int quotientExponent = aExponent - bExponent + scale;
|
||||
|
||||
// Align the significand of b as a Q31 fixed-point number in the range
|
||||
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
|
||||
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
||||
// is accurate to about 3.5 binary digits.
|
||||
const uint32_t q31b = bSignificand >> 21;
|
||||
uint32_t recip32 = UINT32_C(0x7504f333) - q31b;
|
||||
|
||||
// Now refine the reciprocal estimate using a Newton-Raphson iteration:
|
||||
//
|
||||
// x1 = x0 * (2 - x0 * b)
|
||||
//
|
||||
// This doubles the number of correct binary digits in the approximation
|
||||
// with each iteration, so after three iterations, we have about 28 binary
|
||||
// digits of accuracy.
|
||||
uint32_t correction32;
|
||||
correction32 = -((uint64_t)recip32 * q31b >> 32);
|
||||
recip32 = (uint64_t)recip32 * correction32 >> 31;
|
||||
correction32 = -((uint64_t)recip32 * q31b >> 32);
|
||||
recip32 = (uint64_t)recip32 * correction32 >> 31;
|
||||
correction32 = -((uint64_t)recip32 * q31b >> 32);
|
||||
recip32 = (uint64_t)recip32 * correction32 >> 31;
|
||||
|
||||
// recip32 might have overflowed to exactly zero in the preceeding
|
||||
// computation if the high word of b is exactly 1.0. This would sabotage
|
||||
// the full-width final stage of the computation that follows, so we adjust
|
||||
// recip32 downward by one bit.
|
||||
recip32--;
|
||||
|
||||
// We need to perform one more iteration to get us to 56 binary digits;
|
||||
// The last iteration needs to happen with extra precision.
|
||||
const uint32_t q63blo = bSignificand << 11;
|
||||
uint64_t correction, reciprocal;
|
||||
correction = -((uint64_t)recip32*q31b + ((uint64_t)recip32*q63blo >> 32));
|
||||
uint32_t cHi = correction >> 32;
|
||||
uint32_t cLo = correction;
|
||||
reciprocal = (uint64_t)recip32*cHi + ((uint64_t)recip32*cLo >> 32);
|
||||
|
||||
// We already adjusted the 32-bit estimate, now we need to adjust the final
|
||||
// 64-bit reciprocal estimate downward to ensure that it is strictly smaller
|
||||
// than the infinitely precise exact reciprocal. Because the computation
|
||||
// of the Newton-Raphson step is truncating at every step, this adjustment
|
||||
// is small; most of the work is already done.
|
||||
reciprocal -= 2;
|
||||
|
||||
// The numerical reciprocal is accurate to within 2^-56, lies in the
|
||||
// interval [0.5, 1.0), and is strictly smaller than the true reciprocal
|
||||
// of b. Multiplying a by this reciprocal thus gives a numerical q = a/b
|
||||
// in Q53 with the following properties:
|
||||
//
|
||||
// 1. q < a/b
|
||||
// 2. q is in the interval [0.5, 2.0)
|
||||
// 3. the error in q is bounded away from 2^-53 (actually, we have a
|
||||
// couple of bits to spare, but this is all we need).
|
||||
|
||||
// We need a 64 x 64 multiply high to compute q, which isn't a basic
|
||||
// operation in C, so we need to be a little bit fussy.
|
||||
rep_t quotient, quotientLo;
|
||||
wideMultiply(aSignificand << 2, reciprocal, "ient, "ientLo);
|
||||
|
||||
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
|
||||
// In either case, we are going to compute a residual of the form
|
||||
//
|
||||
// r = a - q*b
|
||||
//
|
||||
// We know from the construction of q that r satisfies:
|
||||
//
|
||||
// 0 <= r < ulp(q)*b
|
||||
//
|
||||
// if r is greater than 1/2 ulp(q)*b, then q rounds up. Otherwise, we
|
||||
// already have the correct result. The exact halfway case cannot occur.
|
||||
// We also take this time to right shift quotient if it falls in the [1,2)
|
||||
// range and adjust the exponent accordingly.
|
||||
rep_t residual;
|
||||
if (quotient < (implicitBit << 1)) {
|
||||
residual = (aSignificand << 53) - quotient * bSignificand;
|
||||
quotientExponent--;
|
||||
} else {
|
||||
quotient >>= 1;
|
||||
residual = (aSignificand << 52) - quotient * bSignificand;
|
||||
}
|
||||
|
||||
const int writtenExponent = quotientExponent + exponentBias;
|
||||
|
||||
if (writtenExponent >= maxExponent) {
|
||||
// If we have overflowed the exponent, return infinity.
|
||||
return fromRep(infRep | quotientSign);
|
||||
}
|
||||
|
||||
else if (writtenExponent < 1) {
|
||||
// Flush denormals to zero. In the future, it would be nice to add
|
||||
// code to round them correctly.
|
||||
return fromRep(quotientSign);
|
||||
}
|
||||
|
||||
else {
|
||||
const bool round = (residual << 1) > bSignificand;
|
||||
// Clear the implicit bit
|
||||
rep_t absResult = quotient & significandMask;
|
||||
// Insert the exponent
|
||||
absResult |= (rep_t)writtenExponent << significandBits;
|
||||
// Round
|
||||
absResult += round;
|
||||
// Insert the sign and return
|
||||
const double result = fromRep(absResult | quotientSign);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/* ===-- divdi3.c - Implement __divdi3 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __divdi3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
du_int COMPILER_RT_ABI __udivmoddi4(du_int a, du_int b, du_int* rem);
|
||||
|
||||
/* Returns: a / b */
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__divdi3(di_int a, di_int b)
|
||||
{
|
||||
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 = (a ^ s_a) - s_a; /* negate if s_a == -1 */
|
||||
b = (b ^ s_b) - s_b; /* negate if s_b == -1 */
|
||||
s_a ^= s_b; /*sign of quotient */
|
||||
return (__udivmoddi4(a, b, (du_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*===-- divmoddi4.c - Implement __divmoddi4 --------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __divmoddi4 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
extern COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b);
|
||||
|
||||
/* Returns: a / b, *rem = a % b */
|
||||
|
||||
COMPILER_RT_ABI di_int
|
||||
__divmoddi4(di_int a, di_int b, di_int* rem)
|
||||
{
|
||||
di_int d = __divdi3(a,b);
|
||||
*rem = a - (d*b);
|
||||
return d;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*===-- divmodsi4.c - Implement __divmodsi4 --------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __divmodsi4 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
extern COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b);
|
||||
|
||||
|
||||
/* Returns: a / b, *rem = a % b */
|
||||
|
||||
COMPILER_RT_ABI si_int
|
||||
__divmodsi4(si_int a, si_int b, si_int* rem)
|
||||
{
|
||||
si_int d = __divsi3(a,b);
|
||||
*rem = a - (d*b);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*===-- divsc3.c - Implement __divsc3 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __divsc3 for the compiler_rt library.
|
||||
*
|
||||
*===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
#include "int_math.h"
|
||||
|
||||
/* Returns: the quotient of (a + ib) / (c + id) */
|
||||
|
||||
float _Complex
|
||||
__divsc3(float __a, float __b, float __c, float __d)
|
||||
{
|
||||
int __ilogbw = 0;
|
||||
float __logbw = crt_logbf(crt_fmaxf(crt_fabsf(__c), crt_fabsf(__d)));
|
||||
if (crt_isfinite(__logbw))
|
||||
{
|
||||
__ilogbw = (int)__logbw;
|
||||
__c = crt_scalbnf(__c, -__ilogbw);
|
||||
__d = crt_scalbnf(__d, -__ilogbw);
|
||||
}
|
||||
float __denom = __c * __c + __d * __d;
|
||||
float _Complex z;
|
||||
__real__ z = crt_scalbnf((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
__imag__ z = crt_scalbnf((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(__real__ z) && crt_isnan(__imag__ z))
|
||||
{
|
||||
if ((__denom == 0) && (!crt_isnan(__a) || !crt_isnan(__b)))
|
||||
{
|
||||
__real__ z = crt_copysignf(CRT_INFINITY, __c) * __a;
|
||||
__imag__ z = crt_copysignf(CRT_INFINITY, __c) * __b;
|
||||
}
|
||||
else if ((crt_isinf(__a) || crt_isinf(__b)) &&
|
||||
crt_isfinite(__c) && crt_isfinite(__d))
|
||||
{
|
||||
__a = crt_copysignf(crt_isinf(__a) ? 1 : 0, __a);
|
||||
__b = crt_copysignf(crt_isinf(__b) ? 1 : 0, __b);
|
||||
__real__ z = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
__imag__ z = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
}
|
||||
else if (crt_isinf(__logbw) && __logbw > 0 &&
|
||||
crt_isfinite(__a) && crt_isfinite(__b))
|
||||
{
|
||||
__c = crt_copysignf(crt_isinf(__c) ? 1 : 0, __c);
|
||||
__d = crt_copysignf(crt_isinf(__d) ? 1 : 0, __d);
|
||||
__real__ z = 0 * (__a * __c + __b * __d);
|
||||
__imag__ z = 0 * (__b * __c - __a * __d);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
//===-- lib/divsf3.c - Single-precision division ------------------*- C -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||
// Source Licenses. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements single-precision soft-float division
|
||||
// with the IEEE-754 default rounding (to nearest, ties to even).
|
||||
//
|
||||
// For simplicity, this implementation currently flushes denormals to zero.
|
||||
// It should be a fairly straightforward exercise to implement gradual
|
||||
// underflow with correct rounding.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define SINGLE_PRECISION
|
||||
#include "fp_lib.h"
|
||||
|
||||
ARM_EABI_FNALIAS(fdiv, divsf3)
|
||||
|
||||
fp_t __divsf3(fp_t a, fp_t b) {
|
||||
|
||||
const unsigned int aExponent = toRep(a) >> significandBits & maxExponent;
|
||||
const unsigned int bExponent = toRep(b) >> significandBits & maxExponent;
|
||||
const rep_t quotientSign = (toRep(a) ^ toRep(b)) & signBit;
|
||||
|
||||
rep_t aSignificand = toRep(a) & significandMask;
|
||||
rep_t bSignificand = toRep(b) & significandMask;
|
||||
int scale = 0;
|
||||
|
||||
// Detect if a or b is zero, denormal, infinity, or NaN.
|
||||
if (aExponent-1U >= maxExponent-1U || bExponent-1U >= maxExponent-1U) {
|
||||
|
||||
const rep_t aAbs = toRep(a) & absMask;
|
||||
const rep_t bAbs = toRep(b) & absMask;
|
||||
|
||||
// NaN / anything = qNaN
|
||||
if (aAbs > infRep) return fromRep(toRep(a) | quietBit);
|
||||
// anything / NaN = qNaN
|
||||
if (bAbs > infRep) return fromRep(toRep(b) | quietBit);
|
||||
|
||||
if (aAbs == infRep) {
|
||||
// infinity / infinity = NaN
|
||||
if (bAbs == infRep) return fromRep(qnanRep);
|
||||
// infinity / anything else = +/- infinity
|
||||
else return fromRep(aAbs | quotientSign);
|
||||
}
|
||||
|
||||
// anything else / infinity = +/- 0
|
||||
if (bAbs == infRep) return fromRep(quotientSign);
|
||||
|
||||
if (!aAbs) {
|
||||
// zero / zero = NaN
|
||||
if (!bAbs) return fromRep(qnanRep);
|
||||
// zero / anything else = +/- zero
|
||||
else return fromRep(quotientSign);
|
||||
}
|
||||
// anything else / zero = +/- infinity
|
||||
if (!bAbs) return fromRep(infRep | quotientSign);
|
||||
|
||||
// one or both of a or b is denormal, the other (if applicable) is a
|
||||
// normal number. Renormalize one or both of a and b, and set scale to
|
||||
// include the necessary exponent adjustment.
|
||||
if (aAbs < implicitBit) scale += normalize(&aSignificand);
|
||||
if (bAbs < implicitBit) scale -= normalize(&bSignificand);
|
||||
}
|
||||
|
||||
// Or in the implicit significand bit. (If we fell through from the
|
||||
// denormal path it was already set by normalize( ), but setting it twice
|
||||
// won't hurt anything.)
|
||||
aSignificand |= implicitBit;
|
||||
bSignificand |= implicitBit;
|
||||
int quotientExponent = aExponent - bExponent + scale;
|
||||
|
||||
// Align the significand of b as a Q31 fixed-point number in the range
|
||||
// [1, 2.0) and get a Q32 approximate reciprocal using a small minimax
|
||||
// polynomial approximation: reciprocal = 3/4 + 1/sqrt(2) - b/2. This
|
||||
// is accurate to about 3.5 binary digits.
|
||||
uint32_t q31b = bSignificand << 8;
|
||||
uint32_t reciprocal = UINT32_C(0x7504f333) - q31b;
|
||||
|
||||
// Now refine the reciprocal estimate using a Newton-Raphson iteration:
|
||||
//
|
||||
// x1 = x0 * (2 - x0 * b)
|
||||
//
|
||||
// This doubles the number of correct binary digits in the approximation
|
||||
// with each iteration, so after three iterations, we have about 28 binary
|
||||
// digits of accuracy.
|
||||
uint32_t correction;
|
||||
correction = -((uint64_t)reciprocal * q31b >> 32);
|
||||
reciprocal = (uint64_t)reciprocal * correction >> 31;
|
||||
correction = -((uint64_t)reciprocal * q31b >> 32);
|
||||
reciprocal = (uint64_t)reciprocal * correction >> 31;
|
||||
correction = -((uint64_t)reciprocal * q31b >> 32);
|
||||
reciprocal = (uint64_t)reciprocal * correction >> 31;
|
||||
|
||||
// Exhaustive testing shows that the error in reciprocal after three steps
|
||||
// is in the interval [-0x1.f58108p-31, 0x1.d0e48cp-29], in line with our
|
||||
// expectations. We bump the reciprocal by a tiny value to force the error
|
||||
// to be strictly positive (in the range [0x1.4fdfp-37,0x1.287246p-29], to
|
||||
// be specific). This also causes 1/1 to give a sensible approximation
|
||||
// instead of zero (due to overflow).
|
||||
reciprocal -= 2;
|
||||
|
||||
// The numerical reciprocal is accurate to within 2^-28, lies in the
|
||||
// interval [0x1.000000eep-1, 0x1.fffffffcp-1], and is strictly smaller
|
||||
// than the true reciprocal of b. Multiplying a by this reciprocal thus
|
||||
// gives a numerical q = a/b in Q24 with the following properties:
|
||||
//
|
||||
// 1. q < a/b
|
||||
// 2. q is in the interval [0x1.000000eep-1, 0x1.fffffffcp0)
|
||||
// 3. the error in q is at most 2^-24 + 2^-27 -- the 2^24 term comes
|
||||
// from the fact that we truncate the product, and the 2^27 term
|
||||
// is the error in the reciprocal of b scaled by the maximum
|
||||
// possible value of a. As a consequence of this error bound,
|
||||
// either q or nextafter(q) is the correctly rounded
|
||||
rep_t quotient = (uint64_t)reciprocal*(aSignificand << 1) >> 32;
|
||||
|
||||
// Two cases: quotient is in [0.5, 1.0) or quotient is in [1.0, 2.0).
|
||||
// In either case, we are going to compute a residual of the form
|
||||
//
|
||||
// r = a - q*b
|
||||
//
|
||||
// We know from the construction of q that r satisfies:
|
||||
//
|
||||
// 0 <= r < ulp(q)*b
|
||||
//
|
||||
// if r is greater than 1/2 ulp(q)*b, then q rounds up. Otherwise, we
|
||||
// already have the correct result. The exact halfway case cannot occur.
|
||||
// We also take this time to right shift quotient if it falls in the [1,2)
|
||||
// range and adjust the exponent accordingly.
|
||||
rep_t residual;
|
||||
if (quotient < (implicitBit << 1)) {
|
||||
residual = (aSignificand << 24) - quotient * bSignificand;
|
||||
quotientExponent--;
|
||||
} else {
|
||||
quotient >>= 1;
|
||||
residual = (aSignificand << 23) - quotient * bSignificand;
|
||||
}
|
||||
|
||||
const int writtenExponent = quotientExponent + exponentBias;
|
||||
|
||||
if (writtenExponent >= maxExponent) {
|
||||
// If we have overflowed the exponent, return infinity.
|
||||
return fromRep(infRep | quotientSign);
|
||||
}
|
||||
|
||||
else if (writtenExponent < 1) {
|
||||
// Flush denormals to zero. In the future, it would be nice to add
|
||||
// code to round them correctly.
|
||||
return fromRep(quotientSign);
|
||||
}
|
||||
|
||||
else {
|
||||
const bool round = (residual << 1) > bSignificand;
|
||||
// Clear the implicit bit
|
||||
rep_t absResult = quotient & significandMask;
|
||||
// Insert the exponent
|
||||
absResult |= (rep_t)writtenExponent << significandBits;
|
||||
// Round
|
||||
absResult += round;
|
||||
// Insert the sign and return
|
||||
return fromRep(absResult | quotientSign);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/* ===-- divsi3.c - Implement __divsi3 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __divsi3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
su_int COMPILER_RT_ABI __udivsi3(su_int n, su_int d);
|
||||
|
||||
/* Returns: a / b */
|
||||
|
||||
ARM_EABI_FNALIAS(idiv, divsi3)
|
||||
|
||||
COMPILER_RT_ABI si_int
|
||||
__divsi3(si_int a, si_int b)
|
||||
{
|
||||
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 = (a ^ s_a) - s_a; /* negate if s_a == -1 */
|
||||
b = (b ^ s_b) - s_b; /* negate if s_b == -1 */
|
||||
s_a ^= s_b; /* sign of quotient */
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
return ((su_int)a/(su_int)b ^ s_a) - s_a; /* negate if s_a == -1 */
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/* ===-- divti3.c - Implement __divti3 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __divti3 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#if __x86_64
|
||||
|
||||
tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem);
|
||||
|
||||
/* Returns: a / b */
|
||||
|
||||
ti_int
|
||||
__divti3(ti_int a, ti_int b)
|
||||
{
|
||||
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 = (a ^ s_a) - s_a; /* negate if s_a == -1 */
|
||||
b = (b ^ s_b) - s_b; /* negate if s_b == -1 */
|
||||
s_a ^= s_b; /* sign of quotient */
|
||||
return (__udivmodti4(a, b, (tu_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */
|
||||
}
|
||||
|
||||
#endif
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/* ===-- divxc3.c - Implement __divxc3 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __divxc3 for the compiler_rt library.
|
||||
*
|
||||
*/
|
||||
|
||||
#if !_ARCH_PPC
|
||||
|
||||
#include "int_lib.h"
|
||||
#include "int_math.h"
|
||||
|
||||
/* Returns: the quotient of (a + ib) / (c + id) */
|
||||
|
||||
long double _Complex
|
||||
__divxc3(long double __a, long double __b, long double __c, long double __d)
|
||||
{
|
||||
int __ilogbw = 0;
|
||||
long double __logbw = crt_logbl(crt_fmaxl(crt_fabsl(__c), crt_fabsl(__d)));
|
||||
if (crt_isfinite(__logbw))
|
||||
{
|
||||
__ilogbw = (int)__logbw;
|
||||
__c = crt_scalbnl(__c, -__ilogbw);
|
||||
__d = crt_scalbnl(__d, -__ilogbw);
|
||||
}
|
||||
long double __denom = __c * __c + __d * __d;
|
||||
long double _Complex z;
|
||||
__real__ z = crt_scalbnl((__a * __c + __b * __d) / __denom, -__ilogbw);
|
||||
__imag__ z = crt_scalbnl((__b * __c - __a * __d) / __denom, -__ilogbw);
|
||||
if (crt_isnan(__real__ z) && crt_isnan(__imag__ z))
|
||||
{
|
||||
if ((__denom == 0) && (!crt_isnan(__a) || !crt_isnan(__b)))
|
||||
{
|
||||
__real__ z = crt_copysignl(CRT_INFINITY, __c) * __a;
|
||||
__imag__ z = crt_copysignl(CRT_INFINITY, __c) * __b;
|
||||
}
|
||||
else if ((crt_isinf(__a) || crt_isinf(__b)) &&
|
||||
crt_isfinite(__c) && crt_isfinite(__d))
|
||||
{
|
||||
__a = crt_copysignl(crt_isinf(__a) ? 1 : 0, __a);
|
||||
__b = crt_copysignl(crt_isinf(__b) ? 1 : 0, __b);
|
||||
__real__ z = CRT_INFINITY * (__a * __c + __b * __d);
|
||||
__imag__ z = CRT_INFINITY * (__b * __c - __a * __d);
|
||||
}
|
||||
else if (crt_isinf(__logbw) && __logbw > 0 &&
|
||||
crt_isfinite(__a) && crt_isfinite(__b))
|
||||
{
|
||||
__c = crt_copysignl(crt_isinf(__c) ? 1 : 0, __c);
|
||||
__d = crt_copysignl(crt_isinf(__d) ? 1 : 0, __d);
|
||||
__real__ z = 0 * (__a * __c + __b * __d);
|
||||
__imag__ z = 0 * (__b * __c - __a * __d);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* ===-- enable_execute_stack.c - Implement __enable_execute_stack ---------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#include "int_lib.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
/* #include "config.h"
|
||||
* FIXME: CMake - include when cmake system is ready.
|
||||
* Remove #define HAVE_SYSCONF 1 line.
|
||||
*/
|
||||
#define HAVE_SYSCONF 1
|
||||
|
||||
#ifndef __APPLE__
|
||||
#include <unistd.h>
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#if __LP64__
|
||||
#define TRAMPOLINE_SIZE 48
|
||||
#else
|
||||
#define TRAMPOLINE_SIZE 40
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The compiler generates calls to __enable_execute_stack() when creating
|
||||
* trampoline functions on the stack for use with nested functions.
|
||||
* It is expected to mark the page(s) containing the address
|
||||
* and the next 48 bytes as executable. Since the stack is normally rw-
|
||||
* that means changing the protection on those page(s) to rwx.
|
||||
*/
|
||||
|
||||
void __enable_execute_stack(void* addr)
|
||||
{
|
||||
|
||||
#if __APPLE__
|
||||
/* On Darwin, pagesize is always 4096 bytes */
|
||||
const uintptr_t pageSize = 4096;
|
||||
#elif !defined(HAVE_SYSCONF)
|
||||
#error "HAVE_SYSCONF not defined! See enable_execute_stack.c"
|
||||
#else
|
||||
const uintptr_t pageSize = sysconf(_SC_PAGESIZE);
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
const uintptr_t pageAlignMask = ~(pageSize-1);
|
||||
uintptr_t p = (uintptr_t)addr;
|
||||
unsigned char* startPage = (unsigned char*)(p & pageAlignMask);
|
||||
unsigned char* endPage = (unsigned char*)((p+TRAMPOLINE_SIZE+pageSize) & pageAlignMask);
|
||||
size_t length = endPage - startPage;
|
||||
(void) mprotect((void *)startPage, length, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user