Merge "Change bool, and string properties to *bool, and *string for cc"
diff --git a/benchmarks/tests/interface_test.cpp b/benchmarks/tests/interface_test.cpp
index b8279b6..6987320 100644
--- a/benchmarks/tests/interface_test.cpp
+++ b/benchmarks/tests/interface_test.cpp
@@ -71,7 +71,8 @@
char path[PATH_MAX];
ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path));
ASSERT_TRUE(path_len >= 0);
- *exe_name = std::string(std::regex_replace(path, std::regex("-tests"), ""));
+ *exe_name = std::string(std::regex_replace(path, std::regex("nativetest"), "benchmarktest"));
+ *exe_name = std::regex_replace(*exe_name, std::regex("-tests"), "");
}
void SystemTests::Exec(std::vector<const char*> args) {
@@ -289,6 +290,10 @@
"BM_stdio_fopen_fgetc_fclose_no_locking/1024/iterations:1\n"
"BM_stdio_fopen_getline_fclose_locking/iterations:1\n"
"BM_stdio_fopen_getline_fclose_no_locking/iterations:1\n"
+ "BM_stdio_printf_literal/iterations:1\n"
+ "BM_stdio_printf_s/iterations:1\n"
+ "BM_stdio_printf_d/iterations:1\n"
+ "BM_stdio_printf_1$s/iterations:1\n"
"BM_string_memcmp/8/0/0/iterations:1\n"
"BM_string_memcmp/64/0/0/iterations:1\n"
"BM_string_memcmp/512/0/0/iterations:1\n"
diff --git a/libc/NOTICE b/libc/NOTICE
index cbcafc8..db4b5a5 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -5643,6 +5643,34 @@
-------------------------------------------------------------------
+Copyright (c) 2017 ARM Ltd
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. The name of the company may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
Copyright (c) 2017 Imagination Technologies.
All rights reserved.
diff --git a/libc/arch-arm64/generic/bionic/memcmp.S b/libc/arch-arm64/generic/bionic/memcmp.S
index 3d08ecd..3a138bf 100644
--- a/libc/arch-arm64/generic/bionic/memcmp.S
+++ b/libc/arch-arm64/generic/bionic/memcmp.S
@@ -1,33 +1,34 @@
-/* Copyright (c) 2014, Linaro Limited
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of the Linaro nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
+/*
+ * Copyright (c) 2017 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
/* Assumptions:
*
- * ARMv8-a, AArch64
+ * ARMv8-a, AArch64, unaligned accesses.
*/
#include <private/bionic_asm.h>
@@ -36,120 +37,93 @@
#define src1 x0
#define src2 x1
#define limit x2
-#define result x0
+#define result w0
/* Internal variables. */
#define data1 x3
#define data1w w3
#define data2 x4
#define data2w w4
-#define has_nul x5
-#define diff x6
-#define endloop x7
-#define tmp1 x8
-#define tmp2 x9
-#define tmp3 x10
-#define pos x11
-#define limit_wd x12
-#define mask x13
+#define tmp1 x5
+/* Small inputs of less than 8 bytes are handled separately. This allows the
+ main code to be sped up using unaligned loads since there are now at least
+ 8 bytes to be compared. If the first 8 bytes are equal, align src1.
+ This ensures each iteration does at most one unaligned access even if both
+ src1 and src2 are unaligned, and mutually aligned inputs behave as if
+ aligned. After the main loop, process the last 8 bytes using unaligned
+ accesses. */
+
+.p2align 6
ENTRY(memcmp)
- cbz limit, .Lret0
- eor tmp1, src1, src2
- tst tmp1, #7
- b.ne .Lmisaligned8
- ands tmp1, src1, #7
- b.ne .Lmutual_align
- add limit_wd, limit, #7
- lsr limit_wd, limit_wd, #3
- /* Start of performance-critical section -- one 64B cache line. */
-.Lloop_aligned:
- ldr data1, [src1], #8
- ldr data2, [src2], #8
-.Lstart_realigned:
- subs limit_wd, limit_wd, #1
- eor diff, data1, data2 /* Non-zero if differences found. */
- csinv endloop, diff, xzr, ne /* Last Dword or differences. */
- cbz endloop, .Lloop_aligned
- /* End of performance-critical section -- one 64B cache line. */
+ subs limit, limit, 8
+ b.lo .Lless8
- /* Not reached the limit, must have found a diff. */
- cbnz limit_wd, .Lnot_limit
+ /* Limit >= 8, so check first 8 bytes using unaligned loads. */
+ ldr data1, [src1], 8
+ ldr data2, [src2], 8
+ and tmp1, src1, 7
+ add limit, limit, tmp1
+ cmp data1, data2
+ bne .Lreturn
- /* Limit % 8 == 0 => all bytes significant. */
- ands limit, limit, #7
- b.eq .Lnot_limit
+ /* Align src1 and adjust src2 with bytes not yet done. */
+ sub src1, src1, tmp1
+ sub src2, src2, tmp1
- lsl limit, limit, #3 /* Bits -> bytes. */
- mov mask, #~0
-#ifdef __AARCH64EB__
- lsr mask, mask, limit
-#else
- lsl mask, mask, limit
-#endif
- bic data1, data1, mask
- bic data2, data2, mask
+ subs limit, limit, 8
+ b.ls .Llast_bytes
- orr diff, diff, mask
-.Lnot_limit:
+ /* Loop performing 8 bytes per iteration using aligned src1.
+ Limit is pre-decremented by 8 and must be larger than zero.
+ Exit if <= 8 bytes left to do or if the data is not equal. */
+ .p2align 4
+.Lloop8:
+ ldr data1, [src1], 8
+ ldr data2, [src2], 8
+ subs limit, limit, 8
+ ccmp data1, data2, 0, hi /* NZCV = 0b0000. */
+ b.eq .Lloop8
-#ifndef __AARCH64EB__
- rev diff, diff
+ cmp data1, data2
+ bne .Lreturn
+
+ /* Compare last 1-8 bytes using unaligned access. */
+.Llast_bytes:
+ ldr data1, [src1, limit]
+ ldr data2, [src2, limit]
+
+ /* Compare data bytes and set return value to 0, -1 or 1. */
+.Lreturn:
+#ifndef __AARCH64EB__
rev data1, data1
rev data2, data2
#endif
- /* The MS-non-zero bit of DIFF marks either the first bit
- that is different, or the end of the significant data.
- Shifting left now will bring the critical information into the
- top bits. */
- clz pos, diff
- lsl data1, data1, pos
- lsl data2, data2, pos
- /* But we need to zero-extend (char is unsigned) the value and then
- perform a signed 32-bit subtraction. */
- lsr data1, data1, #56
- sub result, data1, data2, lsr #56
- ret
+ cmp data1, data2
+.Lret_eq:
+ cset result, ne
+ cneg result, result, lo
+ ret
-.Lmutual_align:
- /* Sources are mutually aligned, but are not currently at an
- alignment boundary. Round down the addresses and then mask off
- the bytes that precede the start point. */
- bic src1, src1, #7
- bic src2, src2, #7
- add limit, limit, tmp1 /* Adjust the limit for the extra. */
- lsl tmp1, tmp1, #3 /* Bytes beyond alignment -> bits. */
- ldr data1, [src1], #8
- neg tmp1, tmp1 /* Bits to alignment -64. */
- ldr data2, [src2], #8
- mov tmp2, #~0
-#ifdef __AARCH64EB__
- /* Big-endian. Early bytes are at MSB. */
- lsl tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
-#else
- /* Little-endian. Early bytes are at LSB. */
- lsr tmp2, tmp2, tmp1 /* Shift (tmp1 & 63). */
-#endif
- add limit_wd, limit, #7
- orr data1, data1, tmp2
- orr data2, data2, tmp2
- lsr limit_wd, limit_wd, #3
- b .Lstart_realigned
-
-.Lret0:
- mov result, #0
- ret
-
- .p2align 6
-.Lmisaligned8:
- sub limit, limit, #1
-1:
- /* Perhaps we can do better than this. */
- ldrb data1w, [src1], #1
- ldrb data2w, [src2], #1
- subs limit, limit, #1
- ccmp data1w, data2w, #0, cs /* NZCV = 0b0000. */
- b.eq 1b
- sub result, data1, data2
+ .p2align 4
+ /* Compare up to 8 bytes. Limit is [-8..-1]. */
+.Lless8:
+ adds limit, limit, 4
+ b.lo .Lless4
+ ldr data1w, [src1], 4
+ ldr data2w, [src2], 4
+ cmp data1w, data2w
+ b.ne .Lreturn
+ sub limit, limit, 4
+.Lless4:
+ adds limit, limit, 4
+ beq .Lret_eq
+.Lbyte_loop:
+ ldrb data1w, [src1], 1
+ ldrb data2w, [src2], 1
+ subs limit, limit, 1
+ ccmp data1w, data2w, 0, ne /* NZCV = 0b0000. */
+ b.eq .Lbyte_loop
+ sub result, data1w, data2w
ret
END(memcmp)
diff --git a/libc/include/android/legacy_fenv_inlines_arm.h b/libc/include/android/legacy_fenv_inlines_arm.h
index 58c49c2..de024cf 100644
--- a/libc/include/android/legacy_fenv_inlines_arm.h
+++ b/libc/include/android/legacy_fenv_inlines_arm.h
@@ -35,9 +35,6 @@
__BEGIN_DECLS
-#define FPSCR_ENABLE_SHIFT 8
-#define FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << FPSCR_ENABLE_SHIFT)
-
#define FPSCR_RMODE_SHIFT 22
static __inline int fegetenv(fenv_t* __envp) {
@@ -108,7 +105,7 @@
fenv_t __env;
fegetenv(&__env);
*__envp = __env;
- __env &= ~(FE_ALL_EXCEPT | FPSCR_ENABLE_MASK);
+ __env &= ~FE_ALL_EXCEPT;
fesetenv(&__env);
return 0;
}
@@ -121,30 +118,18 @@
return 0;
}
-static __inline int feenableexcept(int __mask) {
- fenv_t __old_fpscr, __new_fpscr;
- fegetenv(&__old_fpscr);
- __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT;
- fesetenv(&__new_fpscr);
- return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+static __inline int feenableexcept(int __mask __unused) {
+ return -1;
}
-static __inline int fedisableexcept(int __mask) {
- fenv_t __old_fpscr, __new_fpscr;
- fegetenv(&__old_fpscr);
- __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT);
- fesetenv(&__new_fpscr);
- return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+static __inline int fedisableexcept(int __mask __unused) {
+ return 0;
}
static __inline int fegetexcept(void) {
- fenv_t __fpscr;
- fegetenv(&__fpscr);
- return ((__fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT);
+ return 0;
}
-#undef FPSCR_ENABLE_SHIFT
-#undef FPSCR_ENABLE_MASK
#undef FPSCR_RMODE_SHIFT
__END_DECLS
diff --git a/libc/include/bits/fenv_arm.h b/libc/include/bits/fenv_arm.h
index 542ddbe..042fec3 100644
--- a/libc/include/bits/fenv_arm.h
+++ b/libc/include/bits/fenv_arm.h
@@ -26,13 +26,6 @@
* $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
*/
-/*
- * Rewritten for Android.
- *
- * The ARM FPSCR is described here:
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344b/Chdfafia.html
- */
-
#ifndef _BITS_FENV_ARM_H_
#define _BITS_FENV_ARM_H_
@@ -40,7 +33,28 @@
__BEGIN_DECLS
+/*
+ * The ARM Cortex-A75 registers are described here:
+ *
+ * AArch64:
+ * FPCR: http://infocenter.arm.com/help/topic/com.arm.doc.100403_0200_00_en/lau1442502503726.html
+ * FPSR: http://infocenter.arm.com/help/topic/com.arm.doc.100403_0200_00_en/lau1442502526288.html
+ * AArch32:
+ * FPSCR: http://infocenter.arm.com/help/topic/com.arm.doc.100403_0200_00_en/lau1442504290459.html
+ */
+
+#if defined(__LP64__)
+typedef struct {
+ /* FPCR, Floating-point Control Register. */
+ __uint32_t __control;
+ /* FPSR, Floating-point Status Register. */
+ __uint32_t __status;
+} fenv_t;
+
+#else
typedef __uint32_t fenv_t;
+#endif
+
typedef __uint32_t fexcept_t;
/* Exception flags. */
@@ -49,8 +63,8 @@
#define FE_OVERFLOW 0x04
#define FE_UNDERFLOW 0x08
#define FE_INEXACT 0x10
-#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
- FE_OVERFLOW | FE_UNDERFLOW)
+#define FE_DENORMAL 0x80
+#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL)
/* Rounding modes. */
#define FE_TONEAREST 0x0
diff --git a/libc/include/bits/fenv_arm64.h b/libc/include/bits/fenv_arm64.h
deleted file mode 100644
index 67f0fb4..0000000
--- a/libc/include/bits/fenv_arm64.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/*-
- * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
- */
-
-/*
- * In ARMv8, AArch64 state, floating-point operation is controlled by:
- *
- * * FPCR - 32Bit Floating-Point Control Register:
- * * [31:27] - Reserved, Res0;
- * * [26] - AHP, Alternative half-precision control bit;
- * * [25] - DN, Default NaN mode control bit;
- * * [24] - FZ, Flush-to-zero mode control bit;
- * * [23:22] - RMode, Rounding Mode control field:
- * * 00 - Round to Nearest (RN) mode;
- * * 01 - Round towards Plus Infinity (RP) mode;
- * * 10 - Round towards Minus Infinity (RM) mode;
- * * 11 - Round towards Zero (RZ) mode.
- * * [21:20] - Stride, ignored during AArch64 execution;
- * * [19] - Reserved, Res0;
- * * [18:16] - Len, ignored during AArch64 execution;
- * * [15] - IDE, Input Denormal exception trap;
- * * [14:13] - Reserved, Res0;
- * * [12] - IXE, Inexact exception trap;
- * * [11] - UFE, Underflow exception trap;
- * * [10] - OFE, Overflow exception trap;
- * * [9] - DZE, Division by Zero exception;
- * * [8] - IOE, Invalid Operation exception;
- * * [7:0] - Reserved, Res0.
- *
- * * FPSR - 32Bit Floating-Point Status Register:
- * * [31] - N, Negative condition flag for AArch32 (AArch64 sets PSTATE.N);
- * * [30] - Z, Zero condition flag for AArch32 (AArch64 sets PSTATE.Z);
- * * [29] - C, Carry conditon flag for AArch32 (AArch64 sets PSTATE.C);
- * * [28] - V, Overflow conditon flag for AArch32 (AArch64 sets PSTATE.V);
- * * [27] - QC, Cumulative saturation bit, Advanced SIMD only;
- * * [26:8] - Reserved, Res0;
- * * [7] - IDC, Input Denormal cumulative exception;
- * * [6:5] - Reserved, Res0;
- * * [4] - IXC, Inexact cumulative exception;
- * * [3] - UFC, Underflow cumulative exception;
- * * [2] - OFC, Overflow cumulative exception;
- * * [1] - DZC, Division by Zero cumulative exception;
- * * [0] - IOC, Invalid Operation cumulative exception.
- */
-
-#ifndef _BITS_FENV_ARM64_H_
-#define _BITS_FENV_ARM64_H_
-
-#include <sys/types.h>
-
-__BEGIN_DECLS
-
-typedef struct {
- __uint32_t __control; /* FPCR, Floating-point Control Register */
- __uint32_t __status; /* FPSR, Floating-point Status Register */
-} fenv_t;
-
-typedef __uint32_t fexcept_t;
-
-/* Exception flags. */
-#define FE_INVALID 0x01
-#define FE_DIVBYZERO 0x02
-#define FE_OVERFLOW 0x04
-#define FE_UNDERFLOW 0x08
-#define FE_INEXACT 0x10
-#define FE_DENORMAL 0x80
-#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
- FE_OVERFLOW | FE_UNDERFLOW | FE_DENORMAL)
-
-/* Rounding modes. */
-#define FE_TONEAREST 0x0
-#define FE_UPWARD 0x1
-#define FE_DOWNWARD 0x2
-#define FE_TOWARDZERO 0x3
-
-__END_DECLS
-
-#endif
diff --git a/libc/include/fenv.h b/libc/include/fenv.h
index 4276e87..2b607f5 100644
--- a/libc/include/fenv.h
+++ b/libc/include/fenv.h
@@ -32,9 +32,7 @@
#include <sys/cdefs.h>
-#if defined(__aarch64__)
-#include <bits/fenv_arm64.h>
-#elif defined(__arm__)
+#if defined(__aarch64__) || defined(__arm__)
#include <bits/fenv_arm.h>
#elif defined(__i386__)
#include <bits/fenv_x86.h>
diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp
index 46d717a..b4b2a36 100644
--- a/libc/stdio/stdio.cpp
+++ b/libc/stdio/stdio.cpp
@@ -581,7 +581,7 @@
int fseeko64(FILE* fp, off64_t offset, int whence) {
CHECK_FP(fp);
- return __fseeko64(fp, offset, whence, 8*sizeof(off_t));
+ return __fseeko64(fp, offset, whence, 8*sizeof(off64_t));
}
int fsetpos(FILE* fp, const fpos_t* pos) {
diff --git a/libc/stdio/vfprintf.cpp b/libc/stdio/vfprintf.cpp
index 366b196..fe2e338 100644
--- a/libc/stdio/vfprintf.cpp
+++ b/libc/stdio/vfprintf.cpp
@@ -32,6 +32,7 @@
*/
#define CHAR_TYPE char
+#define FUNCTION_NAME __vfprintf
#include <sys/mman.h>
#include <sys/types.h>
@@ -108,8 +109,7 @@
* temporary buffer. We only work on write-only files; this avoids
* worries about ungetc buffers and so forth.
*/
-static int __sbprintf(FILE* fp, const char* fmt, va_list ap) {
- int ret;
+static int __sbprintf(FILE* fp, const CHAR_TYPE* fmt, va_list ap) {
FILE fake;
struct __sfileext fakeext;
unsigned char buf[BUFSIZ];
@@ -127,7 +127,7 @@
fake._lbfsize = 0; /* not actually used, but Just In Case */
/* do the work, then copy any error status */
- ret = __vfprintf(&fake, fmt, ap);
+ int ret = FUNCTION_NAME(&fake, fmt, ap);
if (ret >= 0 && __sflush(&fake)) ret = EOF;
if (fake._flags & __SERR) fp->_flags |= __SERR;
return (ret);
@@ -250,17 +250,16 @@
#define CHARINT 0x0800 /* 8 bit integer */
#define MAXINT 0x1000 /* largest integer size (intmax_t) */
-int __vfprintf(FILE* fp, const char* fmt0, __va_list ap) {
+int FUNCTION_NAME(FILE* fp, const CHAR_TYPE* fmt0, __va_list ap) {
int ch; /* character from fmt */
int n, n2; /* handy integers (short term usage) */
- char* cp; /* handy char pointer (short term usage) */
+ CHAR_TYPE* cp; /* handy char pointer (short term usage) */
struct __siov* iovp; /* for PRINT macro */
+ CHAR_TYPE sign; /* sign prefix (' ', '+', '-', or \0) */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */
- char sign; /* sign prefix (' ', '+', '-', or \0) */
- mbstate_t ps;
/*
* We can decompose the printed representation of floating
* point numbers into several parts, some of which may be empty:
@@ -287,7 +286,7 @@
int expsize; /* character count for expstr */
int lead; /* sig figs before decimal or group sep */
int ndig; /* actual number of digits returned by dtoa */
- char expstr[MAXEXPDIG + 2]; /* buffer for exponent string: e+ZZZ */
+ CHAR_TYPE expstr[MAXEXPDIG + 2]; /* buffer for exponent string: e+ZZZ */
char* dtoaresult = NULL;
uintmax_t _umax; /* integer arguments %[diouxX] */
@@ -299,14 +298,14 @@
#define NIOV 8
struct __suio uio; /* output information: summary */
struct __siov iov[NIOV]; /* ... and individual io vectors */
- char buf[BUF]; /* buffer with space for digits of uintmax_t */
- char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
+ CHAR_TYPE buf[BUF]; /* buffer with space for digits of uintmax_t */
+ CHAR_TYPE ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
union arg* argtable; /* args, built due to positional arg */
union arg statargtable[STATIC_ARG_TBL_SIZE];
size_t argtablesiz;
int nextarg; /* 1-based argument index */
va_list orgap; /* original argument pointer */
- char* convbuf; /* buffer for wide to multi-byte conversion */
+ CHAR_TYPE* convbuf; /* buffer for wide/multibyte conversion */
/*
* Choose PADSIZE to trade efficiency vs. size. If larger printf
@@ -466,7 +465,6 @@
ret = 0;
convbuf = NULL;
- memset(&ps, 0, sizeof(ps));
/*
* Scan the format for conversions (`%' character).
*/
@@ -1275,10 +1273,7 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 's':
- if (flags & LONGINT)
- ADDTYPE(TP_WCHAR);
- else
- ADDTYPE(TP_CHAR);
+ ADDTYPE((flags & LONGINT) ? TP_WCHAR : TP_CHAR);
break;
case 'U':
flags |= LONGINT;
diff --git a/libc/stdio/vfwprintf.cpp b/libc/stdio/vfwprintf.cpp
index 7235969..e8f1056 100644
--- a/libc/stdio/vfwprintf.cpp
+++ b/libc/stdio/vfwprintf.cpp
@@ -32,6 +32,7 @@
*/
#define CHAR_TYPE wchar_t
+#define FUNCTION_NAME __vfwprintf
#include <sys/mman.h>
#include <sys/types.h>
@@ -91,8 +92,7 @@
* temporary buffer. We only work on write-only files; this avoids
* worries about ungetc buffers and so forth.
*/
-static int __sbprintf(FILE* fp, const wchar_t* fmt, va_list ap) {
- int ret;
+static int __sbprintf(FILE* fp, const CHAR_TYPE* fmt, va_list ap) {
FILE fake;
struct __sfileext fakeext;
unsigned char buf[BUFSIZ];
@@ -110,7 +110,7 @@
fake._lbfsize = 0; /* not actually used, but Just In Case */
/* do the work, then copy any error status */
- ret = __vfwprintf(&fake, fmt, ap);
+ int ret = FUNCTION_NAME(&fake, fmt, ap);
if (ret >= 0 && __sflush(&fake)) ret = EOF;
if (fake._flags & __SERR) fp->_flags |= __SERR;
return (ret);
@@ -276,15 +276,15 @@
#define CHARINT 0x0800 /* 8 bit integer */
#define MAXINT 0x1000 /* largest integer size (intmax_t) */
-int __vfwprintf(FILE* __restrict fp, const wchar_t* __restrict fmt0, __va_list ap) {
+int FUNCTION_NAME(FILE* fp, const CHAR_TYPE* fmt0, __va_list ap) {
wchar_t ch; /* character from fmt */
int n, n2, n3; /* handy integers (short term usage) */
- wchar_t* cp; /* handy char pointer (short term usage) */
+ CHAR_TYPE* cp; /* handy char pointer (short term usage) */
+ CHAR_TYPE sign; /* sign prefix (' ', '+', '-', or \0) */
int flags; /* flags as above */
int ret; /* return value accumulator */
int width; /* width from format (%8d), or 0 */
int prec; /* precision from format; <0 for N/A */
- wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
/*
* We can decompose the printed representation of floating
* point numbers into several parts, some of which may be empty:
@@ -311,7 +311,7 @@
int expsize; /* character count for expstr */
int lead; /* sig figs before decimal or group sep */
int ndig; /* actual number of digits returned by dtoa */
- wchar_t expstr[MAXEXPDIG + 2]; /* buffer for exponent string: e+ZZZ */
+ CHAR_TYPE expstr[MAXEXPDIG + 2]; /* buffer for exponent string: e+ZZZ */
char* dtoaresult = NULL;
uintmax_t _umax; /* integer arguments %[diouxX] */
@@ -320,14 +320,14 @@
int realsz; /* field size expanded by dprec */
int size; /* size of converted field or string */
const char* xdigs; /* digits for %[xX] conversion */
- wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */
- wchar_t ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
+ CHAR_TYPE buf[BUF]; /* buffer with space for digits of uintmax_t */
+ CHAR_TYPE ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
union arg* argtable; /* args, built due to positional arg */
union arg statargtable[STATIC_ARG_TBL_SIZE];
size_t argtablesiz;
int nextarg; /* 1-based argument index */
va_list orgap; /* original argument pointer */
- wchar_t* convbuf; /* buffer for multibyte to wide conversion */
+ CHAR_TYPE* convbuf; /* buffer for wide/multibyte conversion */
/*
* Choose PADSIZE to trade efficiency vs. size. If larger printf
@@ -1271,10 +1271,7 @@
flags |= LONGINT;
/*FALLTHROUGH*/
case 's':
- if (flags & LONGINT)
- ADDTYPE(TP_CHAR);
- else
- ADDTYPE(TP_WCHAR);
+ ADDTYPE((flags & LONGINT) ? TP_WCHAR : TP_CHAR);
break;
case 'U':
flags |= LONGINT;
diff --git a/libm/arm/fenv.c b/libm/arm/fenv.c
index 2124730..c988e4f 100644
--- a/libm/arm/fenv.c
+++ b/libm/arm/fenv.c
@@ -28,9 +28,6 @@
#include <fenv.h>
-#define FPSCR_ENABLE_SHIFT 8
-#define FPSCR_ENABLE_MASK (FE_ALL_EXCEPT << FPSCR_ENABLE_SHIFT)
-
#define FPSCR_RMODE_SHIFT 22
const fenv_t __fe_dfl_env = 0;
@@ -103,7 +100,7 @@
fenv_t __env;
fegetenv(&__env);
*__envp = __env;
- __env &= ~(FE_ALL_EXCEPT | FPSCR_ENABLE_MASK);
+ __env &= ~FE_ALL_EXCEPT;
fesetenv(&__env);
return 0;
}
@@ -116,24 +113,14 @@
return 0;
}
-int feenableexcept(int __mask) {
- fenv_t __old_fpscr, __new_fpscr;
- fegetenv(&__old_fpscr);
- __new_fpscr = __old_fpscr | (__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT;
- fesetenv(&__new_fpscr);
- return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+int feenableexcept(int __mask __unused) {
+ return -1;
}
-int fedisableexcept(int __mask) {
- fenv_t __old_fpscr, __new_fpscr;
- fegetenv(&__old_fpscr);
- __new_fpscr = __old_fpscr & ~((__mask & FE_ALL_EXCEPT) << FPSCR_ENABLE_SHIFT);
- fesetenv(&__new_fpscr);
- return ((__old_fpscr >> FPSCR_ENABLE_SHIFT) & FE_ALL_EXCEPT);
+int fedisableexcept(int __mask __unused) {
+ return 0;
}
int fegetexcept(void) {
- fenv_t __fpscr;
- fegetenv(&__fpscr);
- return ((__fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT);
+ return 0;
}
diff --git a/libm/arm64/fenv.c b/libm/arm64/fenv.c
index 19a2393..a99288b 100644
--- a/libm/arm64/fenv.c
+++ b/libm/arm64/fenv.c
@@ -29,9 +29,6 @@
#include <stdint.h>
#include <fenv.h>
-#define FPCR_EXCEPT_SHIFT 8
-#define FPCR_EXCEPT_MASK (FE_ALL_EXCEPT << FPCR_EXCEPT_SHIFT)
-
#define FPCR_RMODE_SHIFT 22
const fenv_t __fe_dfl_env = { 0 /* control */, 0 /* status */};
@@ -137,22 +134,13 @@
}
int feholdexcept(fenv_t* envp) {
- fenv_t env;
fpu_status_t fpsr;
- fpu_control_t fpcr, new_fpcr;
-
__get_fpsr(fpsr);
+ fpu_control_t fpcr;
__get_fpcr(fpcr);
- env.__status = fpsr;
- env.__control = fpcr;
+ fenv_t env = { .__status = fpsr, .__control = fpcr };
*envp = env;
- // Set exceptions to untrapped.
- new_fpcr = fpcr & ~(FE_ALL_EXCEPT << FPCR_EXCEPT_SHIFT);
- if (new_fpcr != fpcr) {
- __set_fpcr(new_fpcr);
- }
-
// Clear all exceptions.
fpsr &= ~FE_ALL_EXCEPT;
__set_fpsr(fpsr);
@@ -176,31 +164,14 @@
return 0;
}
-int feenableexcept(int mask) {
- fpu_control_t old_fpcr, new_fpcr;
-
- __get_fpcr(old_fpcr);
- new_fpcr = old_fpcr | ((mask & FE_ALL_EXCEPT) << FPCR_EXCEPT_SHIFT);
- if (new_fpcr != old_fpcr) {
- __set_fpcr(new_fpcr);
- }
- return ((old_fpcr >> FPCR_EXCEPT_SHIFT) & FE_ALL_EXCEPT);
+int feenableexcept(int mask __unused) {
+ return -1;
}
-int fedisableexcept(int mask) {
- fpu_control_t old_fpcr, new_fpcr;
-
- __get_fpcr(old_fpcr);
- new_fpcr = old_fpcr & ~((mask & FE_ALL_EXCEPT) << FPCR_EXCEPT_SHIFT);
- if (new_fpcr != old_fpcr) {
- __set_fpcr(new_fpcr);
- }
- return ((old_fpcr >> FPCR_EXCEPT_SHIFT) & FE_ALL_EXCEPT);
+int fedisableexcept(int mask __unused) {
+ return 0;
}
int fegetexcept(void) {
- fpu_control_t fpcr;
-
- __get_fpcr(fpcr);
- return ((fpcr & FPCR_EXCEPT_MASK) >> FPCR_EXCEPT_SHIFT);
+ return 0;
}
diff --git a/tests/fenv_test.cpp b/tests/fenv_test.cpp
index c914692..9fc7d96 100644
--- a/tests/fenv_test.cpp
+++ b/tests/fenv_test.cpp
@@ -182,12 +182,20 @@
TEST(fenv, feenableexcept_fegetexcept) {
#if defined(__aarch64__) || defined(__arm__)
- // Unsupported.
- // arm:
- // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100403_0200_00_en/lau1442504290459.html
- // aarch64:
- // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488h/way1382990760439.html
- GTEST_LOG_(INFO) << "arm and arm64 don't support feenableexcept";
+ // ARM doesn't support this. They used to if you go back far enough, but it was removed in
+ // the Cortex-A8 between r3p1 and r3p2.
+ ASSERT_EQ(-1, feenableexcept(FE_INVALID));
+ ASSERT_EQ(0, fegetexcept());
+ ASSERT_EQ(-1, feenableexcept(FE_DIVBYZERO));
+ ASSERT_EQ(0, fegetexcept());
+ ASSERT_EQ(-1, feenableexcept(FE_OVERFLOW));
+ ASSERT_EQ(0, fegetexcept());
+ ASSERT_EQ(-1, feenableexcept(FE_UNDERFLOW));
+ ASSERT_EQ(0, fegetexcept());
+ ASSERT_EQ(-1, feenableexcept(FE_INEXACT));
+ ASSERT_EQ(0, fegetexcept());
+ ASSERT_EQ(-1, feenableexcept(FE_DENORMAL));
+ ASSERT_EQ(0, fegetexcept());
#else
// We can't recover from SIGFPE, so sacrifice a child...
pid_t pid = fork();
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 87a0eae..05a19d1 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -2148,3 +2148,37 @@
ASSERT_EQ(0, fclose(fp));
}
+
+TEST(STDIO_TEST, fseek_64bit) {
+ TemporaryFile tf;
+ FILE* fp = fopen64(tf.filename, "w+");
+ ASSERT_TRUE(fp != nullptr);
+ ASSERT_EQ(0, fseeko64(fp, 0x2'0000'0000, SEEK_SET));
+ ASSERT_EQ(0x2'0000'0000, ftello64(fp));
+ ASSERT_EQ(0, fseeko64(fp, 0x1'0000'0000, SEEK_CUR));
+ ASSERT_EQ(0x3'0000'0000, ftello64(fp));
+ ASSERT_EQ(0, fclose(fp));
+}
+
+// POSIX requires that fseek/fseeko fail with EOVERFLOW if the new file offset
+// isn't representable in long/off_t.
+TEST(STDIO_TEST, fseek_overflow_32bit) {
+ TemporaryFile tf;
+ FILE* fp = fopen64(tf.filename, "w+");
+ ASSERT_EQ(0, ftruncate64(fileno(fp), 0x2'0000'0000));
+
+ // Bionic implements overflow checking for SEEK_CUR, but glibc doesn't.
+#if defined(__BIONIC__) && !defined(__LP64__)
+ ASSERT_EQ(0, fseek(fp, 0x7fff'ffff, SEEK_SET));
+ ASSERT_EQ(-1, fseek(fp, 1, SEEK_CUR));
+ ASSERT_EQ(EOVERFLOW, errno);
+#endif
+
+ // Neither Bionic nor glibc implement the overflow checking for SEEK_END.
+ // (Aside: FreeBSD's libc is an example of a libc that checks both SEEK_CUR
+ // and SEEK_END -- many C libraries check neither.)
+ ASSERT_EQ(0, fseek(fp, 0, SEEK_END));
+ ASSERT_EQ(0x2'0000'0000, ftello64(fp));
+
+ fclose(fp);
+}