mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Improve signal handling and math
- Polyfill ucontext_t on FreeBSD/OpenBSD/NetBSD - Add tests confirming signals can edit CPU state - Work towards supporting ZIP filesystem on bare metal - Add more tinymath unit tests for POSIX conformance - Add X87 and SSE status flags to crash report - Fix some bugs in blinkenlights - Fix llvm build breakage
This commit is contained in:
parent
cdc54ea1fd
commit
40291c9db3
109 changed files with 2316 additions and 520 deletions
|
@ -1103,8 +1103,8 @@ ape_grub:
|
|||
.align 4
|
||||
ape_grub_entry:
|
||||
.code32
|
||||
/ cmp $GRUB_EAX,%eax
|
||||
/ jne triplf
|
||||
// cmp $GRUB_EAX,%eax
|
||||
// jne triplf
|
||||
push $0
|
||||
popf
|
||||
mov $0x40,%dl
|
||||
|
@ -1426,7 +1426,7 @@ long: push $GDT_LONG_DATA
|
|||
jmp _start
|
||||
.endfn long
|
||||
|
||||
.rodata.str1.1
|
||||
.rodata
|
||||
.Larg0: .asciz "ape.com"
|
||||
.Lenv0: .asciz "METAL=1"
|
||||
.previous
|
||||
|
|
|
@ -95,7 +95,7 @@ CONFIG_COPTS += \
|
|||
$(SANITIZER)
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-march=native
|
||||
-msse3
|
||||
|
||||
OVERRIDE_CCFLAGS += \
|
||||
-fno-pie
|
||||
|
|
|
@ -166,8 +166,7 @@ DEFAULT_LDFLAGS = \
|
|||
--gc-sections \
|
||||
--build-id=none \
|
||||
--no-dynamic-linker \
|
||||
-z max-page-size=0x1000 \
|
||||
--cref -Map=$@.map
|
||||
-z max-page-size=0x1000
|
||||
|
||||
ZIPOBJ_FLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
|
34
examples/ucontext-sigfpe-recovery.c
Normal file
34
examples/ucontext-sigfpe-recovery.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "third_party/xed/x86.h"
|
||||
|
||||
void handler(int sig, siginfo_t *si, ucontext_t *ctx) {
|
||||
struct XedDecodedInst xedd;
|
||||
xed_decoded_inst_zero_set_mode(&xedd, XED_MACHINE_MODE_LONG_64);
|
||||
xed_instruction_length_decode(&xedd, (void *)ctx->uc_mcontext.rip, 15);
|
||||
ctx->uc_mcontext.rip += xedd.length;
|
||||
ctx->uc_mcontext.rax = 42;
|
||||
ctx->uc_mcontext.rdx = 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct sigaction saint = {.sa_sigaction = handler, .sa_flags = SA_SIGINFO};
|
||||
sigaction(SIGFPE, &saint, NULL);
|
||||
volatile long x = 0;
|
||||
printf("123/0 = %ld\n", 123 / x);
|
||||
return 0;
|
||||
}
|
|
@ -245,9 +245,9 @@ int vdprintf(int, const char *, va_list) paramsnonnull();
|
|||
void _init_onntconsoleevent(void);
|
||||
void _init_wincrash(void);
|
||||
|
||||
#ifndef __SIGACTION
|
||||
#define __SIGACTION(FN, SIG, ...) \
|
||||
({ \
|
||||
#ifndef __SIGACTION_YOINK
|
||||
#define __SIGACTION_YOINK(SIG) \
|
||||
do { \
|
||||
if (SupportsWindows()) { \
|
||||
if (__builtin_constant_p(SIG)) { \
|
||||
switch (SIG) { \
|
||||
|
@ -272,14 +272,23 @@ void _init_wincrash(void);
|
|||
YOINK(_init_wincrash); \
|
||||
} \
|
||||
} \
|
||||
(FN)(SIG, __VA_ARGS__); \
|
||||
})
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define dprintf(FD, FMT, ...) (dprintf)(FD, PFLINK(FMT), ##__VA_ARGS__)
|
||||
#define sigaction(SIG, ACT, OLD) __SIGACTION(sigaction, SIG, ACT, OLD)
|
||||
#define signal(SIG, HAND) __SIGACTION(signal, SIG, HAND)
|
||||
#define vdprintf(FD, FMT, VA) (vdprintf)(FD, PFLINK(FMT), VA)
|
||||
#define sigaction(SIG, ACT, OLD) \
|
||||
({ \
|
||||
__SIGACTION_YOINK(SIG); \
|
||||
sigaction(SIG, (ACT), OLD); \
|
||||
})
|
||||
|
||||
#define signal(SIG, HAND) \
|
||||
({ \
|
||||
__SIGACTION_YOINK(SIG); \
|
||||
signal(SIG, HAND); \
|
||||
})
|
||||
|
||||
#define dprintf(FD, FMT, ...) (dprintf)(FD, PFLINK(FMT), ##__VA_ARGS__)
|
||||
#define vdprintf(FD, FMT, VA) (vdprintf)(FD, PFLINK(FMT), VA)
|
||||
|
||||
#endif /* GNU && !ANSI */
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -40,8 +40,10 @@ int close(int fd) {
|
|||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = weaken(__zipos_close)(fd);
|
||||
} else {
|
||||
if (!IsWindows()) {
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
rc = sys_close(fd);
|
||||
} else if (IsMetal()) {
|
||||
rc = 0;
|
||||
} else {
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdEpoll) {
|
||||
rc = weaken(sys_close_epoll_nt)(fd);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int fstat_metal(int fd, struct stat *st) {
|
||||
int sys_fstat_metal(int fd, struct stat *st) {
|
||||
if (fd < 0) return einval();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
||||
memset(st, 0, sizeof(*st));
|
||||
|
|
|
@ -34,7 +34,7 @@ int fstat(int fd, struct stat *st) {
|
|||
} else if (!IsWindows() && !IsMetal()) {
|
||||
return sys_fstat(fd, st);
|
||||
} else if (IsMetal()) {
|
||||
return fstat_metal(fd, st);
|
||||
return sys_fstat_metal(fd, st);
|
||||
} else {
|
||||
if (!__isfdkind(fd, kFdFile)) return ebadf();
|
||||
return sys_fstat_nt(g_fds.p[fd].handle, st);
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
*/
|
||||
int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
axdx_t ad;
|
||||
if (!IsWindows()) {
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
ad = sys_gettimeofday(tv, tz, NULL);
|
||||
assert(ad.ax != -1);
|
||||
if (SupportsXnu() && ad.ax && tv) {
|
||||
|
@ -43,6 +43,8 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
|||
tv->tv_usec = ad.dx;
|
||||
}
|
||||
return 0;
|
||||
} else if (IsMetal()) {
|
||||
return enosys();
|
||||
} else {
|
||||
return sys_gettimeofday_nt(tv, tz);
|
||||
}
|
||||
|
|
|
@ -206,17 +206,15 @@ void sys_exit(int) hidden;
|
|||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
void __onfork(void) hidden;
|
||||
bool32 __sigenter(i32, struct siginfo *, struct ucontext *) hidden;
|
||||
i32 __fixupnewfd(i32, i32) hidden;
|
||||
u32 __prot2nt(i32, i32) privileged;
|
||||
void __restore_rt() hidden;
|
||||
void __sigenter_xnu(void *, i32, i32, void *, void *) hidden wontreturn;
|
||||
int sys_utimensat_xnu(int, const char *, const struct timespec *, int) hidden;
|
||||
int sys_nanosleep_xnu(const struct timespec *, struct timespec *) hidden;
|
||||
void __stat2linux(void *) hidden;
|
||||
void __restore_rt_netbsd(void) hidden;
|
||||
void __xnutrampoline(void *, i32, i32, const struct __darwin_siginfo *,
|
||||
const struct __darwin_ucontext *) hidden wontreturn;
|
||||
void __sigenter_xnu(void *, i32, i32, struct __darwin_siginfo *,
|
||||
struct __darwin_ucontext *) hidden;
|
||||
int gethostname_linux(char *, size_t) hidden;
|
||||
int gethostname_bsd(char *, size_t) hidden;
|
||||
int gethostname_nt(char *, size_t) hidden;
|
||||
|
@ -288,19 +286,24 @@ int __mkntpath(const char *, char16_t[hasatleast PATH_MAX - 16]) hidden;
|
|||
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX - 16], int) hidden;
|
||||
int __mkntpathat(int, const char *, int, char16_t[PATH_MAX]) hidden;
|
||||
unsigned __wincrash_nt(struct NtExceptionPointers *);
|
||||
ssize_t sys_readv_nt(struct Fd *, const struct iovec *, int) hidden;
|
||||
ssize_t sys_writev_nt(struct Fd *, const struct iovec *, int) hidden;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § syscalls » metal ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
int fstat_metal(int, struct stat *);
|
||||
int sys_fstat_metal(int, struct stat *);
|
||||
int sys_openat_metal(int, const char *, int, unsigned);
|
||||
ssize_t sys_readv_metal(struct Fd *, const struct iovec *, int) hidden;
|
||||
ssize_t sys_writev_metal(struct Fd *, const struct iovec *, int) hidden;
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § syscalls » drivers ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
ssize_t readv_serial(struct Fd *, const struct iovec *, int) hidden;
|
||||
ssize_t writev_serial(struct Fd *, const struct iovec *, int) hidden;
|
||||
ssize_t sys_readv_serial(struct Fd *, const struct iovec *, int) hidden;
|
||||
ssize_t sys_writev_serial(struct Fd *, const struct iovec *, int) hidden;
|
||||
|
||||
#undef sigset
|
||||
#undef i32
|
||||
|
|
14
libc/calls/metalfile.internal.h
Normal file
14
libc/calls/metalfile.internal.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_METALFILE_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_METALFILE_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct MetalFile {
|
||||
char *base;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
};
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_METALFILE_INTERNAL_H_ */
|
40
libc/calls/openat-metal.c
Normal file
40
libc/calls/openat-metal.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/metalfile.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_openat_metal(int dirfd, const char *file, int flags, unsigned mode) {
|
||||
int fd;
|
||||
struct MetalFile *state;
|
||||
if (strcmp(file, "ape.com")) return enoent();
|
||||
if (!weaken(calloc)) return enomem();
|
||||
if ((fd = __reservefd()) == -1) return -1;
|
||||
state = weaken(calloc)(1, sizeof(struct MetalFile));
|
||||
state->base = (char *)_base;
|
||||
state->size = _end - _base;
|
||||
g_fds.p[fd].kind = kFdFile;
|
||||
g_fds.p[fd].flags = flags;
|
||||
g_fds.p[fd].handle = (intptr_t)state;
|
||||
return fd;
|
||||
}
|
|
@ -51,8 +51,10 @@ int openat(int dirfd, const char *file, int flags, ...) {
|
|||
if (__vforked) return einval();
|
||||
if (dirfd != AT_FDCWD) return einval();
|
||||
return weaken(__zipos_open)(&zipname, flags, mode);
|
||||
} else if (!IsWindows()) {
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
return sys_openat(dirfd, file, flags, mode);
|
||||
} else if (IsMetal()) {
|
||||
return sys_openat_metal(dirfd, file, flags, mode);
|
||||
} else {
|
||||
return sys_open_nt(dirfd, file, flags, mode);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -17,32 +17,27 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/metalfile.internal.h"
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
// BSD signal handler.
|
||||
//
|
||||
// This is needed because (1) a signal is allowed to trigger at
|
||||
// just about any time, and leaf functions (e.g. memcpy) aren't
|
||||
// required to leave Cosmopolitan's image base register alone.
|
||||
//
|
||||
// @param %edi is the signal number
|
||||
// @param %rsi will be passed for sigactions
|
||||
// @param %rdx will be passed for sigactions
|
||||
// @return true if handler was invoked
|
||||
__sigenter:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
and $NSIG-1,%edi
|
||||
mov __sighandrvas(,%rdi,4),%eax
|
||||
cmp $kSigactionMinRva,%eax
|
||||
jl 2f
|
||||
lea _base(%rax),%eax
|
||||
call *%rax
|
||||
mov $1,%eax
|
||||
1: leave
|
||||
ret
|
||||
2: xor %eax,%eax
|
||||
jmp 1b
|
||||
.endfn __sigenter,globl,hidden
|
||||
ssize_t sys_readv_metal(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||
int i;
|
||||
size_t got, toto;
|
||||
struct MetalFile *file;
|
||||
switch (fd->kind) {
|
||||
case kFdSerial:
|
||||
return sys_readv_serial(fd, iov, iovlen);
|
||||
case kFdFile:
|
||||
file = (struct MetalFile *)fd->handle;
|
||||
for (toto = i = 0; i < iovlen && file->pos < file->size; ++i) {
|
||||
got = MIN(iov[i].iov_len, file->size - file->pos);
|
||||
memcpy(iov[i].iov_base, file->base, got);
|
||||
toto += got;
|
||||
}
|
||||
return toto;
|
||||
default:
|
||||
return ebadf();
|
||||
}
|
||||
}
|
35
libc/calls/readv-nt.c
Normal file
35
libc/calls/readv-nt.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows ssize_t sys_readv_nt(struct Fd *fd, const struct iovec *iov,
|
||||
int iovlen) {
|
||||
switch (fd->kind) {
|
||||
case kFdFile:
|
||||
case kFdConsole:
|
||||
return sys_read_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return weaken(sys_recvfrom_nt)(fd, iov, iovlen, 0, NULL, 0);
|
||||
default:
|
||||
return ebadf();
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ static int GetFirstIov(struct iovec *iov, int iovlen) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
ssize_t readv_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||
ssize_t sys_readv_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||
size_t i, j, got = 0;
|
||||
if ((i = GetFirstIov(iov, iovlen)) != -1) {
|
||||
while (!IsDataAvailable(fd)) asm("pause");
|
||||
|
|
|
@ -36,16 +36,13 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
|||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return weaken(__zipos_read)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||
} else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
||||
return readv_serial(&g_fds.p[fd], iov, iovlen);
|
||||
} else if (!IsWindows()) {
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
return sys_readv(fd, iov, iovlen);
|
||||
} else if (fd < g_fds.n &&
|
||||
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
|
||||
return sys_read_nt(&g_fds.p[fd], iov, iovlen, -1);
|
||||
} else if (fd < g_fds.n && (g_fds.p[fd].kind == kFdSocket)) {
|
||||
return weaken(sys_recvfrom_nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
|
||||
} else {
|
||||
} else if (fd >= g_fds.n) {
|
||||
return ebadf();
|
||||
} else if (IsMetal()) {
|
||||
return sys_readv_metal(g_fds.p + fd, iov, iovlen);
|
||||
} else {
|
||||
return sys_readv_nt(g_fds.p + fd, iov, iovlen);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,16 +39,6 @@
|
|||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
union metasigaction {
|
||||
struct sigaction cosmo;
|
||||
struct sigaction_linux linux;
|
||||
struct sigaction_freebsd freebsd;
|
||||
struct sigaction_openbsd openbsd;
|
||||
struct sigaction_netbsd netbsd;
|
||||
struct sigaction_xnu_in xnu_in;
|
||||
struct sigaction_xnu_out xnu_out;
|
||||
};
|
||||
|
||||
#ifndef SWITCHEROO
|
||||
#define SWITCHEROO(S1, S2, A, B, C, D) \
|
||||
do { \
|
||||
|
@ -66,6 +56,20 @@ union metasigaction {
|
|||
} while (0);
|
||||
#endif
|
||||
|
||||
union metasigaction {
|
||||
struct sigaction cosmo;
|
||||
struct sigaction_linux linux;
|
||||
struct sigaction_freebsd freebsd;
|
||||
struct sigaction_openbsd openbsd;
|
||||
struct sigaction_netbsd netbsd;
|
||||
struct sigaction_xnu_in xnu_in;
|
||||
struct sigaction_xnu_out xnu_out;
|
||||
};
|
||||
|
||||
void __sigenter_netbsd(int, void *, void *);
|
||||
void __sigenter_freebsd(int, void *, void *);
|
||||
void __sigenter_openbsd(int, void *, void *);
|
||||
|
||||
static void sigaction_cosmo2native(union metasigaction *sa) {
|
||||
if (!sa) return;
|
||||
switch (__hostos) {
|
||||
|
@ -165,17 +169,21 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) {
|
|||
memcpy(©, act, sizeof(copy));
|
||||
ap = ©
|
||||
if (IsXnu()) {
|
||||
ap->sa_restorer = (void *)&__xnutrampoline;
|
||||
ap->sa_handler = (void *)&__xnutrampoline;
|
||||
ap->sa_restorer = (void *)&__sigenter_xnu;
|
||||
ap->sa_handler = (void *)&__sigenter_xnu;
|
||||
} else if (IsLinux()) {
|
||||
if (!(ap->sa_flags & SA_RESTORER)) {
|
||||
ap->sa_flags |= SA_RESTORER;
|
||||
ap->sa_restorer = &__restore_rt;
|
||||
}
|
||||
} else if (IsNetbsd()) {
|
||||
ap->sa_sigaction = act->sa_sigaction;
|
||||
} else if (rva >= kSigactionMinRva) {
|
||||
ap->sa_sigaction = (sigaction_f)__sigenter;
|
||||
ap->sa_sigaction = (sigaction_f)__sigenter_netbsd;
|
||||
} else if (IsFreebsd()) {
|
||||
ap->sa_sigaction = (sigaction_f)__sigenter_freebsd;
|
||||
} else if (IsOpenbsd()) {
|
||||
ap->sa_sigaction = (sigaction_f)__sigenter_openbsd;
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
sigaction_cosmo2native((union metasigaction *)ap);
|
||||
} else {
|
||||
|
|
196
libc/calls/sigenter-freebsd.c
Normal file
196
libc/calls/sigenter-freebsd.c
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/sigaction-freebsd.internal.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
union sigval_freebsd {
|
||||
int32_t sival_int;
|
||||
void *sival_ptr;
|
||||
int32_t sigval_int;
|
||||
void *sigval_ptr;
|
||||
};
|
||||
|
||||
struct siginfo_freebsd {
|
||||
int32_t si_signo;
|
||||
int32_t si_errno;
|
||||
int32_t si_code;
|
||||
int32_t si_pid;
|
||||
uint32_t si_uid;
|
||||
int32_t si_status;
|
||||
void *si_addr;
|
||||
union sigval_freebsd si_value;
|
||||
union {
|
||||
struct {
|
||||
int _trapno;
|
||||
} _fault;
|
||||
struct {
|
||||
int _timerid;
|
||||
int _overrun;
|
||||
} _timer;
|
||||
struct {
|
||||
int _mqd;
|
||||
} _mesgq;
|
||||
struct {
|
||||
long _band;
|
||||
} _poll;
|
||||
struct {
|
||||
long __spare1__;
|
||||
int __spare2__[7];
|
||||
} __spare__;
|
||||
} _reason;
|
||||
};
|
||||
|
||||
struct stack_freebsd {
|
||||
void *ss_sp;
|
||||
uint64_t ss_size;
|
||||
int32_t ss_flags;
|
||||
};
|
||||
|
||||
struct mcontext_freebsd {
|
||||
int64_t mc_onstack;
|
||||
int64_t mc_rdi;
|
||||
int64_t mc_rsi;
|
||||
int64_t mc_rdx;
|
||||
int64_t mc_rcx;
|
||||
int64_t mc_r8;
|
||||
int64_t mc_r9;
|
||||
int64_t mc_rax;
|
||||
int64_t mc_rbx;
|
||||
int64_t mc_rbp;
|
||||
int64_t mc_r10;
|
||||
int64_t mc_r11;
|
||||
int64_t mc_r12;
|
||||
int64_t mc_r13;
|
||||
int64_t mc_r14;
|
||||
int64_t mc_r15;
|
||||
uint32_t mc_trapno;
|
||||
uint16_t mc_fs;
|
||||
uint16_t mc_gs;
|
||||
int64_t mc_addr;
|
||||
uint32_t mc_flags;
|
||||
uint16_t mc_es;
|
||||
uint16_t mc_ds;
|
||||
int64_t mc_err;
|
||||
int64_t mc_rip;
|
||||
int64_t mc_cs;
|
||||
int64_t mc_rflags;
|
||||
int64_t mc_rsp;
|
||||
int64_t mc_ss;
|
||||
int64_t mc_len;
|
||||
int64_t mc_fpformat;
|
||||
int64_t mc_ownedfp;
|
||||
int64_t mc_fpstate[64];
|
||||
int64_t mc_fsbase;
|
||||
int64_t mc_gsbase;
|
||||
int64_t mc_xfpustate;
|
||||
int64_t mc_xfpustate_len;
|
||||
long mc_spare[4];
|
||||
};
|
||||
|
||||
struct ucontext_freebsd {
|
||||
struct sigset_freebsd uc_sigmask;
|
||||
struct mcontext_freebsd uc_mcontext;
|
||||
struct ucontext_freebsd *uc_link;
|
||||
struct stack_freebsd uc_stack;
|
||||
int32_t uc_flags;
|
||||
int32_t __spare__[4];
|
||||
};
|
||||
|
||||
hidden void __sigenter_freebsd(int sig, struct siginfo_freebsd *si,
|
||||
struct ucontext_freebsd *ctx) {
|
||||
int rva;
|
||||
ucontext_t uc;
|
||||
rva = __sighandrvas[sig & (NSIG - 1)];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
memset(&uc, 0, sizeof(uc));
|
||||
if (ctx) {
|
||||
uc.uc_mcontext.fpregs = &uc.__fpustate;
|
||||
uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
|
||||
uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
|
||||
uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
|
||||
uc.uc_flags = ctx->uc_flags;
|
||||
memcpy(&uc.uc_sigmask, &ctx->uc_sigmask,
|
||||
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
|
||||
uc.uc_mcontext.rdi = ctx->uc_mcontext.mc_rdi;
|
||||
uc.uc_mcontext.rsi = ctx->uc_mcontext.mc_rsi;
|
||||
uc.uc_mcontext.rdx = ctx->uc_mcontext.mc_rdx;
|
||||
uc.uc_mcontext.rcx = ctx->uc_mcontext.mc_rcx;
|
||||
uc.uc_mcontext.r8 = ctx->uc_mcontext.mc_r8;
|
||||
uc.uc_mcontext.r9 = ctx->uc_mcontext.mc_r9;
|
||||
uc.uc_mcontext.rax = ctx->uc_mcontext.mc_rax;
|
||||
uc.uc_mcontext.rbx = ctx->uc_mcontext.mc_rbx;
|
||||
uc.uc_mcontext.rbp = ctx->uc_mcontext.mc_rbp;
|
||||
uc.uc_mcontext.r10 = ctx->uc_mcontext.mc_r10;
|
||||
uc.uc_mcontext.r11 = ctx->uc_mcontext.mc_r11;
|
||||
uc.uc_mcontext.r12 = ctx->uc_mcontext.mc_r12;
|
||||
uc.uc_mcontext.r13 = ctx->uc_mcontext.mc_r13;
|
||||
uc.uc_mcontext.r14 = ctx->uc_mcontext.mc_r14;
|
||||
uc.uc_mcontext.r15 = ctx->uc_mcontext.mc_r15;
|
||||
uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno;
|
||||
uc.uc_mcontext.fs = ctx->uc_mcontext.mc_fs;
|
||||
uc.uc_mcontext.gs = ctx->uc_mcontext.mc_gs;
|
||||
uc.uc_mcontext.eflags = ctx->uc_mcontext.mc_flags;
|
||||
uc.uc_mcontext.err = ctx->uc_mcontext.mc_err;
|
||||
uc.uc_mcontext.rip = ctx->uc_mcontext.mc_rip;
|
||||
uc.uc_mcontext.rsp = ctx->uc_mcontext.mc_rsp;
|
||||
}
|
||||
((sigaction_f)(_base + rva))(sig, (void *)si, &uc);
|
||||
if (ctx) {
|
||||
ctx->uc_stack.ss_sp = uc.uc_stack.ss_sp;
|
||||
ctx->uc_stack.ss_size = uc.uc_stack.ss_size;
|
||||
ctx->uc_stack.ss_flags = uc.uc_stack.ss_flags;
|
||||
ctx->uc_flags = uc.uc_flags;
|
||||
memcpy(&ctx->uc_sigmask, &uc.uc_sigmask,
|
||||
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
|
||||
ctx->uc_mcontext.mc_rdi = uc.uc_mcontext.rdi;
|
||||
ctx->uc_mcontext.mc_rsi = uc.uc_mcontext.rsi;
|
||||
ctx->uc_mcontext.mc_rdx = uc.uc_mcontext.rdx;
|
||||
ctx->uc_mcontext.mc_rcx = uc.uc_mcontext.rcx;
|
||||
ctx->uc_mcontext.mc_r8 = uc.uc_mcontext.r8;
|
||||
ctx->uc_mcontext.mc_r9 = uc.uc_mcontext.r9;
|
||||
ctx->uc_mcontext.mc_rax = uc.uc_mcontext.rax;
|
||||
ctx->uc_mcontext.mc_rbx = uc.uc_mcontext.rbx;
|
||||
ctx->uc_mcontext.mc_rbp = uc.uc_mcontext.rbp;
|
||||
ctx->uc_mcontext.mc_r10 = uc.uc_mcontext.r10;
|
||||
ctx->uc_mcontext.mc_r11 = uc.uc_mcontext.r11;
|
||||
ctx->uc_mcontext.mc_r12 = uc.uc_mcontext.r12;
|
||||
ctx->uc_mcontext.mc_r13 = uc.uc_mcontext.r13;
|
||||
ctx->uc_mcontext.mc_r14 = uc.uc_mcontext.r14;
|
||||
ctx->uc_mcontext.mc_r15 = uc.uc_mcontext.r15;
|
||||
ctx->uc_mcontext.mc_trapno = uc.uc_mcontext.trapno;
|
||||
ctx->uc_mcontext.mc_fs = uc.uc_mcontext.fs;
|
||||
ctx->uc_mcontext.mc_gs = uc.uc_mcontext.gs;
|
||||
ctx->uc_mcontext.mc_flags = uc.uc_mcontext.eflags;
|
||||
ctx->uc_mcontext.mc_err = uc.uc_mcontext.err;
|
||||
ctx->uc_mcontext.mc_rip = uc.uc_mcontext.rip;
|
||||
ctx->uc_mcontext.mc_rsp = uc.uc_mcontext.rsp;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* When the FreeBSD kernel invokes this signal handler it pushes a
|
||||
* trampoline on the stack which does two things: 1) it calls this
|
||||
* function, and 2) calls sys_sigreturn() once this returns.
|
||||
*/
|
||||
}
|
204
libc/calls/sigenter-netbsd.c
Normal file
204
libc/calls/sigenter-netbsd.c
Normal file
|
@ -0,0 +1,204 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/sigaction-freebsd.internal.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
#define RDI 0
|
||||
#define RSI 1
|
||||
#define RDX 2
|
||||
#define R10 6
|
||||
#define R8 4
|
||||
#define R9 5
|
||||
#define RCX 3
|
||||
#define R11 7
|
||||
#define R12 8
|
||||
#define R13 9
|
||||
#define R14 10
|
||||
#define R15 11
|
||||
#define RBP 12
|
||||
#define RBX 13
|
||||
#define RAX 14
|
||||
#define GS 15
|
||||
#define FS 16
|
||||
#define ES 17
|
||||
#define DS 18
|
||||
#define TRAP 19
|
||||
#define ERR 20
|
||||
#define RIP 21
|
||||
#define CS 22
|
||||
#define RFLAGS 23
|
||||
#define RSP 24
|
||||
#define SS 25
|
||||
|
||||
union sigval_netbsd {
|
||||
int32_t sival_int;
|
||||
void *sival_ptr;
|
||||
};
|
||||
|
||||
struct siginfo_netbsd {
|
||||
int32_t _signo;
|
||||
int32_t _code;
|
||||
int32_t _errno;
|
||||
int32_t _pad;
|
||||
union {
|
||||
struct {
|
||||
int32_t _pid;
|
||||
uint32_t _uid;
|
||||
union sigval_netbsd _value;
|
||||
} _rt;
|
||||
struct {
|
||||
int32_t _pid;
|
||||
uint32_t _uid;
|
||||
int32_t _status;
|
||||
int64_t _utime;
|
||||
int64_t _stime;
|
||||
} _child;
|
||||
struct {
|
||||
void *_addr;
|
||||
int32_t _trap;
|
||||
int32_t _trap2;
|
||||
int32_t _trap3;
|
||||
} _fault;
|
||||
struct {
|
||||
int64_t _band;
|
||||
int32_t _fd;
|
||||
} _poll;
|
||||
struct {
|
||||
int32_t _sysnum;
|
||||
int32_t _retval[2];
|
||||
int32_t _error;
|
||||
uint64_t _args[8];
|
||||
} _syscall;
|
||||
struct {
|
||||
int32_t _pe_report_event;
|
||||
union {
|
||||
int32_t _pe_other_pid;
|
||||
int32_t _pe_lwp;
|
||||
} _option;
|
||||
} _ptrace_state;
|
||||
} _reason;
|
||||
};
|
||||
|
||||
struct sigset_netbsd {
|
||||
uint32_t __bits[4];
|
||||
};
|
||||
|
||||
struct stack_netbsd {
|
||||
void *ss_sp;
|
||||
size_t ss_size;
|
||||
int32_t ss_flags;
|
||||
};
|
||||
|
||||
struct mcontext_netbsd {
|
||||
int64_t __gregs[26];
|
||||
int64_t _mc_tlsbase;
|
||||
struct FpuState __fpregs;
|
||||
};
|
||||
|
||||
struct ucontext_netbsd {
|
||||
uint32_t uc_flags;
|
||||
struct ucontext_netbsd *uc_link;
|
||||
struct sigset_netbsd uc_sigmask;
|
||||
struct stack_netbsd uc_stack;
|
||||
struct mcontext_netbsd uc_mcontext;
|
||||
};
|
||||
|
||||
hidden void __sigenter_netbsd(int sig, struct siginfo_netbsd *si,
|
||||
struct ucontext_netbsd *ctx) {
|
||||
int rva;
|
||||
ucontext_t uc;
|
||||
struct siginfo si2;
|
||||
rva = __sighandrvas[sig & (NSIG - 1)];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
memset(&uc, 0, sizeof(uc));
|
||||
memset(&si2, 0, sizeof(si2));
|
||||
if (si) {
|
||||
si2.si_signo = si->_signo;
|
||||
si2.si_code = si->_code;
|
||||
si2.si_errno = si->_errno;
|
||||
}
|
||||
if (ctx) {
|
||||
uc.uc_mcontext.fpregs = &uc.__fpustate;
|
||||
uc.uc_flags = ctx->uc_flags;
|
||||
uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
|
||||
uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
|
||||
uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
|
||||
memcpy(&uc.uc_sigmask, &ctx->uc_sigmask,
|
||||
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->uc_sigmask)));
|
||||
uc.uc_mcontext.rdi = ctx->uc_mcontext.__gregs[RDI];
|
||||
uc.uc_mcontext.rsi = ctx->uc_mcontext.__gregs[RSI];
|
||||
uc.uc_mcontext.rdx = ctx->uc_mcontext.__gregs[RDX];
|
||||
uc.uc_mcontext.rcx = ctx->uc_mcontext.__gregs[RCX];
|
||||
uc.uc_mcontext.r8 = ctx->uc_mcontext.__gregs[R8];
|
||||
uc.uc_mcontext.r9 = ctx->uc_mcontext.__gregs[R9];
|
||||
uc.uc_mcontext.rax = ctx->uc_mcontext.__gregs[RAX];
|
||||
uc.uc_mcontext.rbx = ctx->uc_mcontext.__gregs[RBX];
|
||||
uc.uc_mcontext.rbp = ctx->uc_mcontext.__gregs[RBP];
|
||||
uc.uc_mcontext.r10 = ctx->uc_mcontext.__gregs[R10];
|
||||
uc.uc_mcontext.r11 = ctx->uc_mcontext.__gregs[R11];
|
||||
uc.uc_mcontext.r12 = ctx->uc_mcontext.__gregs[R12];
|
||||
uc.uc_mcontext.r13 = ctx->uc_mcontext.__gregs[R13];
|
||||
uc.uc_mcontext.r14 = ctx->uc_mcontext.__gregs[R14];
|
||||
uc.uc_mcontext.r15 = ctx->uc_mcontext.__gregs[R15];
|
||||
uc.uc_mcontext.trapno = ctx->uc_mcontext.__gregs[TRAP];
|
||||
uc.uc_mcontext.fs = ctx->uc_mcontext.__gregs[FS];
|
||||
uc.uc_mcontext.gs = ctx->uc_mcontext.__gregs[GS];
|
||||
uc.uc_mcontext.err = ctx->uc_mcontext.__gregs[ERR];
|
||||
uc.uc_mcontext.rip = ctx->uc_mcontext.__gregs[RIP];
|
||||
uc.uc_mcontext.rsp = ctx->uc_mcontext.__gregs[RSP];
|
||||
*uc.uc_mcontext.fpregs = ctx->uc_mcontext.__fpregs;
|
||||
}
|
||||
((sigaction_f)(_base + rva))(sig, &si2, &uc);
|
||||
if (ctx) {
|
||||
ctx->uc_mcontext.__gregs[RDI] = uc.uc_mcontext.rdi;
|
||||
ctx->uc_mcontext.__gregs[RSI] = uc.uc_mcontext.rsi;
|
||||
ctx->uc_mcontext.__gregs[RDX] = uc.uc_mcontext.rdx;
|
||||
ctx->uc_mcontext.__gregs[RCX] = uc.uc_mcontext.rcx;
|
||||
ctx->uc_mcontext.__gregs[R8] = uc.uc_mcontext.r8;
|
||||
ctx->uc_mcontext.__gregs[R9] = uc.uc_mcontext.r9;
|
||||
ctx->uc_mcontext.__gregs[RAX] = uc.uc_mcontext.rax;
|
||||
ctx->uc_mcontext.__gregs[RBX] = uc.uc_mcontext.rbx;
|
||||
ctx->uc_mcontext.__gregs[RBP] = uc.uc_mcontext.rbp;
|
||||
ctx->uc_mcontext.__gregs[R10] = uc.uc_mcontext.r10;
|
||||
ctx->uc_mcontext.__gregs[R11] = uc.uc_mcontext.r11;
|
||||
ctx->uc_mcontext.__gregs[R12] = uc.uc_mcontext.r12;
|
||||
ctx->uc_mcontext.__gregs[R13] = uc.uc_mcontext.r13;
|
||||
ctx->uc_mcontext.__gregs[R14] = uc.uc_mcontext.r14;
|
||||
ctx->uc_mcontext.__gregs[R15] = uc.uc_mcontext.r15;
|
||||
ctx->uc_mcontext.__gregs[TRAP] = uc.uc_mcontext.trapno;
|
||||
ctx->uc_mcontext.__gregs[FS] = uc.uc_mcontext.fs;
|
||||
ctx->uc_mcontext.__gregs[GS] = uc.uc_mcontext.gs;
|
||||
ctx->uc_mcontext.__gregs[ERR] = uc.uc_mcontext.err;
|
||||
ctx->uc_mcontext.__gregs[RIP] = uc.uc_mcontext.rip;
|
||||
ctx->uc_mcontext.__gregs[RSP] = uc.uc_mcontext.rsp;
|
||||
ctx->uc_mcontext.__fpregs = *uc.uc_mcontext.fpregs;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* When the NetBSD kernel invokes this signal handler it pushes a
|
||||
* trampoline on the stack which does two things: 1) it calls this
|
||||
* function, and 2) calls sys_sigreturn() once this returns.
|
||||
*/
|
||||
}
|
169
libc/calls/sigenter-openbsd.c
Normal file
169
libc/calls/sigenter-openbsd.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/sigaction-freebsd.internal.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
union sigval_openbsd {
|
||||
int32_t sival_int;
|
||||
void *sival_ptr;
|
||||
};
|
||||
|
||||
struct siginfo_openbsd {
|
||||
int32_t si_signo;
|
||||
int32_t si_code;
|
||||
int32_t si_errno;
|
||||
union {
|
||||
int _pad[29];
|
||||
struct {
|
||||
int32_t _pid;
|
||||
union {
|
||||
struct {
|
||||
uint32_t _uid;
|
||||
union sigval_openbsd _value;
|
||||
} _kill;
|
||||
struct {
|
||||
int64_t _utime;
|
||||
int64_t _stime;
|
||||
int32_t _status;
|
||||
} _cld;
|
||||
} _pdata;
|
||||
} _proc;
|
||||
struct {
|
||||
void *_addr;
|
||||
int32_t _trapno;
|
||||
} _fault;
|
||||
} _data;
|
||||
};
|
||||
|
||||
struct ucontext_openbsd {
|
||||
int64_t sc_rdi;
|
||||
int64_t sc_rsi;
|
||||
int64_t sc_rdx;
|
||||
int64_t sc_rcx;
|
||||
int64_t sc_r8;
|
||||
int64_t sc_r9;
|
||||
int64_t sc_r10;
|
||||
int64_t sc_r11;
|
||||
int64_t sc_r12;
|
||||
int64_t sc_r13;
|
||||
int64_t sc_r14;
|
||||
int64_t sc_r15;
|
||||
int64_t sc_rbp;
|
||||
int64_t sc_rbx;
|
||||
int64_t sc_rax;
|
||||
int64_t sc_gs;
|
||||
int64_t sc_fs;
|
||||
int64_t sc_es;
|
||||
int64_t sc_ds;
|
||||
int64_t sc_trapno;
|
||||
int64_t sc_err;
|
||||
int64_t sc_rip;
|
||||
int64_t sc_cs;
|
||||
int64_t sc_rflags;
|
||||
int64_t sc_rsp;
|
||||
int64_t sc_ss;
|
||||
struct FpuState *sc_fpstate;
|
||||
int32_t __sc_unused;
|
||||
int32_t sc_mask;
|
||||
int64_t sc_cookie;
|
||||
};
|
||||
|
||||
hidden void __sigenter_openbsd(int sig, struct siginfo_openbsd *si,
|
||||
struct ucontext_openbsd *ctx) {
|
||||
int rva;
|
||||
ucontext_t uc;
|
||||
struct siginfo si2;
|
||||
rva = __sighandrvas[sig & (NSIG - 1)];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
memset(&uc, 0, sizeof(uc));
|
||||
memset(&si2, 0, sizeof(si2));
|
||||
if (si) {
|
||||
si2.si_signo = si->si_signo;
|
||||
si2.si_code = si->si_code;
|
||||
si2.si_errno = si->si_errno;
|
||||
}
|
||||
if (ctx) {
|
||||
uc.uc_mcontext.fpregs = &uc.__fpustate;
|
||||
memcpy(&uc.uc_sigmask, &ctx->sc_mask,
|
||||
MIN(sizeof(uc.uc_sigmask), sizeof(ctx->sc_mask)));
|
||||
uc.uc_mcontext.rdi = ctx->sc_rdi;
|
||||
uc.uc_mcontext.rsi = ctx->sc_rsi;
|
||||
uc.uc_mcontext.rdx = ctx->sc_rdx;
|
||||
uc.uc_mcontext.rcx = ctx->sc_rcx;
|
||||
uc.uc_mcontext.r8 = ctx->sc_r8;
|
||||
uc.uc_mcontext.r9 = ctx->sc_r9;
|
||||
uc.uc_mcontext.rax = ctx->sc_rax;
|
||||
uc.uc_mcontext.rbx = ctx->sc_rbx;
|
||||
uc.uc_mcontext.rbp = ctx->sc_rbp;
|
||||
uc.uc_mcontext.r10 = ctx->sc_r10;
|
||||
uc.uc_mcontext.r11 = ctx->sc_r11;
|
||||
uc.uc_mcontext.r12 = ctx->sc_r12;
|
||||
uc.uc_mcontext.r13 = ctx->sc_r13;
|
||||
uc.uc_mcontext.r14 = ctx->sc_r14;
|
||||
uc.uc_mcontext.r15 = ctx->sc_r15;
|
||||
uc.uc_mcontext.trapno = ctx->sc_trapno;
|
||||
uc.uc_mcontext.fs = ctx->sc_fs;
|
||||
uc.uc_mcontext.gs = ctx->sc_gs;
|
||||
uc.uc_mcontext.err = ctx->sc_err;
|
||||
uc.uc_mcontext.rip = ctx->sc_rip;
|
||||
uc.uc_mcontext.rsp = ctx->sc_rsp;
|
||||
if (ctx->sc_fpstate) {
|
||||
*uc.uc_mcontext.fpregs = *ctx->sc_fpstate;
|
||||
}
|
||||
}
|
||||
((sigaction_f)(_base + rva))(sig, &si2, &uc);
|
||||
if (ctx) {
|
||||
ctx->sc_rdi = uc.uc_mcontext.rdi;
|
||||
ctx->sc_rsi = uc.uc_mcontext.rsi;
|
||||
ctx->sc_rdx = uc.uc_mcontext.rdx;
|
||||
ctx->sc_rcx = uc.uc_mcontext.rcx;
|
||||
ctx->sc_r8 = uc.uc_mcontext.r8;
|
||||
ctx->sc_r9 = uc.uc_mcontext.r9;
|
||||
ctx->sc_rax = uc.uc_mcontext.rax;
|
||||
ctx->sc_rbx = uc.uc_mcontext.rbx;
|
||||
ctx->sc_rbp = uc.uc_mcontext.rbp;
|
||||
ctx->sc_r10 = uc.uc_mcontext.r10;
|
||||
ctx->sc_r11 = uc.uc_mcontext.r11;
|
||||
ctx->sc_r12 = uc.uc_mcontext.r12;
|
||||
ctx->sc_r13 = uc.uc_mcontext.r13;
|
||||
ctx->sc_r14 = uc.uc_mcontext.r14;
|
||||
ctx->sc_r15 = uc.uc_mcontext.r15;
|
||||
ctx->sc_trapno = uc.uc_mcontext.trapno;
|
||||
ctx->sc_fs = uc.uc_mcontext.fs;
|
||||
ctx->sc_gs = uc.uc_mcontext.gs;
|
||||
ctx->sc_err = uc.uc_mcontext.err;
|
||||
ctx->sc_rip = uc.uc_mcontext.rip;
|
||||
ctx->sc_rsp = uc.uc_mcontext.rsp;
|
||||
if (ctx->sc_fpstate) {
|
||||
*ctx->sc_fpstate = *uc.uc_mcontext.fpregs;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* When the OpenBSD kernel invokes this signal handler it pushes a
|
||||
* trampoline on the stack which does two things: 1) it calls this
|
||||
* function, and 2) calls sys_sigreturn() once this returns.
|
||||
*/
|
||||
}
|
|
@ -49,7 +49,7 @@ struct siginfo {
|
|||
};
|
||||
char __ignoreme[128 - 2 * sizeof(int32_t) - sizeof(int64_t)];
|
||||
};
|
||||
} forcealign(8);
|
||||
};
|
||||
|
||||
typedef struct siginfo siginfo_t;
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ struct FpuStackEntry {
|
|||
uint16_t padding[3];
|
||||
};
|
||||
|
||||
struct FpuState {
|
||||
struct thatispacked FpuState {
|
||||
uint16_t cwd;
|
||||
uint16_t swd;
|
||||
uint16_t ftw;
|
||||
|
@ -122,26 +122,7 @@ struct MachineContext {
|
|||
typedef struct MachineContext mcontext_t;
|
||||
|
||||
struct ucontext {
|
||||
union {
|
||||
uint64_t uc_flags;
|
||||
struct {
|
||||
unsigned cf : 1; /* bit 0: carry flag */
|
||||
unsigned vf : 1; /* bit 1: V flag: was 8085 signed-number overflow */
|
||||
unsigned pf : 1; /* bit 2: parity flag */
|
||||
unsigned rf : 1; /* bit 3: always zero [undoc] */
|
||||
unsigned af : 1; /* bit 4: auxiliary flag */
|
||||
unsigned kf : 1; /* bit 5: K flag = V flag ⊕ sgn(result) [undoc] */
|
||||
unsigned zf : 1; /* bit 6: zero flag */
|
||||
unsigned sf : 1; /* bit 7: sign flag */
|
||||
unsigned tf : 1; /* bit 8: trap flag */
|
||||
unsigned if_ : 1; /* bit 9: interrupt enable flag */
|
||||
unsigned df : 1; /* bit 10: direction flag */
|
||||
unsigned of : 1; /* bit 11: overflow flag */
|
||||
unsigned pl : 2; /* b12-13: i/o privilege level (80286+) */
|
||||
unsigned nt : 1; /* bit 14: nested task flag (80286+) */
|
||||
unsigned pc : 1; /* bit 15: oldskool flag */
|
||||
};
|
||||
};
|
||||
uint64_t uc_flags;
|
||||
struct ucontext *uc_link;
|
||||
stack_t uc_stack;
|
||||
mcontext_t uc_mcontext; /* use this */
|
||||
|
|
|
@ -23,8 +23,12 @@
|
|||
|
||||
void __winalarm(void *lpArgToCompletionRoutine, uint32_t dwTimerLowValue,
|
||||
uint32_t dwTimerHighValue) {
|
||||
int rva;
|
||||
siginfo_t info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.si_signo = SIGALRM;
|
||||
__sigenter(info.si_signo, &info, NULL);
|
||||
rva = __sighandrvas[SIGALRM];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
((sigaction_f)(_base + rva))(SIGALRM, &info, NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "libc/str/str.h"
|
||||
|
||||
textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
|
||||
int sig;
|
||||
int sig, rva;
|
||||
struct Goodies {
|
||||
ucontext_t ctx;
|
||||
struct siginfo si;
|
||||
|
@ -69,7 +69,10 @@ textwindows unsigned __wincrash(struct NtExceptionPointers *ep) {
|
|||
return kNtExceptionContinueSearch;
|
||||
}
|
||||
memset(&g, 0, sizeof(g));
|
||||
ntcontext2linux(&g.ctx, ep->ContextRecord);
|
||||
return __sigenter(sig, &g.si, &g.ctx) ? kNtExceptionContinueExecution
|
||||
: kNtExceptionContinueSearch;
|
||||
rva = __sighandrvas[sig];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
ntcontext2linux(&g.ctx, ep->ContextRecord);
|
||||
((sigaction_f)(_base + rva))(sig, &g.si, &g.ctx);
|
||||
}
|
||||
return kNtExceptionContinueExecution;
|
||||
}
|
||||
|
|
29
libc/calls/writev-metal.c
Normal file
29
libc/calls/writev-metal.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
ssize_t sys_writev_metal(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||
switch (fd->kind) {
|
||||
case kFdSerial:
|
||||
return sys_writev_serial(fd, iov, iovlen);
|
||||
default:
|
||||
return ebadf();
|
||||
}
|
||||
}
|
35
libc/calls/writev-nt.c
Normal file
35
libc/calls/writev-nt.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows ssize_t sys_writev_nt(struct Fd *fd, const struct iovec *iov,
|
||||
int iovlen) {
|
||||
switch (fd->kind) {
|
||||
case kFdFile:
|
||||
case kFdConsole:
|
||||
return sys_write_nt(fd, iov, iovlen, -1);
|
||||
case kFdSocket:
|
||||
return weaken(sys_sendto_nt)(fd, iov, iovlen, 0, NULL, 0);
|
||||
default:
|
||||
return ebadf();
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/nexgen32e/uart.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
|
||||
ssize_t writev_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||
ssize_t sys_writev_serial(struct Fd *fd, const struct iovec *iov, int iovlen) {
|
||||
size_t i, j, wrote = 0;
|
||||
for (i = 0; i < iovlen; ++i) {
|
||||
for (j = 0; j < iov[i].iov_len; ++j) {
|
||||
|
|
|
@ -39,16 +39,13 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
|||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return weaken(__zipos_write)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||
} else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) {
|
||||
return writev_serial(&g_fds.p[fd], iov, iovlen);
|
||||
} else if (!IsWindows()) {
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
return sys_writev(fd, iov, iovlen);
|
||||
} else if (fd < g_fds.n &&
|
||||
(g_fds.p[fd].kind == kFdFile || g_fds.p[fd].kind == kFdConsole)) {
|
||||
return sys_write_nt(&g_fds.p[fd], iov, iovlen, -1);
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdSocket) {
|
||||
return weaken(sys_sendto_nt)(&g_fds.p[fd], iov, iovlen, 0, NULL, 0);
|
||||
} else {
|
||||
} else if (fd >= g_fds.n) {
|
||||
return ebadf();
|
||||
} else if (IsMetal()) {
|
||||
return sys_writev_metal(g_fds.p + fd, iov, iovlen);
|
||||
} else {
|
||||
return sys_writev_nt(g_fds.p + fd, iov, iovlen);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,17 +50,6 @@ struct __darwin_sigaltstack {
|
|||
int32_t ss_flags;
|
||||
};
|
||||
|
||||
struct __darwin_fp_control {
|
||||
uint16_t __invalid : 1, __denorm : 1, __zdiv : 1, __ovrfl : 1, __undfl : 1,
|
||||
__precis : 1, : 2, __pc : 2, __rc : 2, : 1, : 3;
|
||||
};
|
||||
|
||||
struct __darwin_fp_status {
|
||||
uint16_t __invalid : 1, __denorm : 1, __zdiv : 1, __ovrfl : 1, __undfl : 1,
|
||||
__precis : 1, __stkflt : 1, __errsumm : 1, __c0 : 1, __c1 : 1, __c2 : 1,
|
||||
__tos : 3, __c3 : 1, __busy : 1;
|
||||
};
|
||||
|
||||
struct __darwin_mmst_reg {
|
||||
char __mmst_reg[10];
|
||||
char __mmst_rsrv[6];
|
||||
|
@ -116,8 +105,8 @@ struct __darwin_x86_thread_full_state64 {
|
|||
|
||||
struct __darwin_x86_float_state64 {
|
||||
int32_t __fpu_reserved[2];
|
||||
struct __darwin_fp_control __fpu_fcw;
|
||||
struct __darwin_fp_status __fpu_fsw;
|
||||
uint16_t __fpu_fcw;
|
||||
uint16_t __fpu_fsw;
|
||||
uint8_t __fpu_ftw;
|
||||
uint8_t __fpu_rsrv1;
|
||||
uint16_t __fpu_fop;
|
||||
|
@ -153,14 +142,14 @@ struct __darwin_x86_float_state64 {
|
|||
struct __darwin_xmm_reg __fpu_xmm13;
|
||||
struct __darwin_xmm_reg __fpu_xmm14;
|
||||
struct __darwin_xmm_reg __fpu_xmm15;
|
||||
char __fpu_rsrv4[6 * 16];
|
||||
char __fpu_rsrv4[96];
|
||||
int32_t __fpu_reserved1;
|
||||
};
|
||||
|
||||
struct __darwin_x86_avx_state64 {
|
||||
int32_t __fpu_reserved[2];
|
||||
struct __darwin_fp_control __fpu_fcw;
|
||||
struct __darwin_fp_status __fpu_fsw;
|
||||
uint16_t __fpu_fcw;
|
||||
uint16_t __fpu_fsw;
|
||||
uint8_t __fpu_ftw;
|
||||
uint8_t __fpu_rsrv1;
|
||||
uint16_t __fpu_fop;
|
||||
|
@ -219,8 +208,8 @@ struct __darwin_x86_avx_state64 {
|
|||
|
||||
struct __darwin_x86_avx512_state64 {
|
||||
int32_t __fpu_reserved[2];
|
||||
struct __darwin_fp_control __fpu_fcw;
|
||||
struct __darwin_fp_status __fpu_fsw;
|
||||
uint16_t __fpu_fcw;
|
||||
uint16_t __fpu_fsw;
|
||||
uint8_t __fpu_ftw;
|
||||
uint8_t __fpu_rsrv1;
|
||||
uint16_t __fpu_fop;
|
||||
|
@ -390,6 +379,12 @@ static void xnuexceptionstate2linux(
|
|||
mc->err = xnues->__err;
|
||||
}
|
||||
|
||||
static void linuxexceptionstate2xnu(
|
||||
struct __darwin_x86_exception_state64 *xnues, mcontext_t *mc) {
|
||||
xnues->__trapno = mc->trapno;
|
||||
xnues->__err = mc->err;
|
||||
}
|
||||
|
||||
static void xnuthreadstate2linux(ucontext_t *uc, mcontext_t *mc,
|
||||
struct __darwin_x86_thread_state64 *xnuss) {
|
||||
mc->rdi = xnuss->__rdi;
|
||||
|
@ -401,7 +396,6 @@ static void xnuthreadstate2linux(ucontext_t *uc, mcontext_t *mc,
|
|||
mc->rcx = xnuss->__rcx;
|
||||
mc->rsp = xnuss->__rsp;
|
||||
mc->rip = xnuss->__rip;
|
||||
/* g.uc.uc_mcontext.rip = xnuctx->uc_mcontext->__es.__faultvaddr; */
|
||||
mc->cs = xnuss->__cs;
|
||||
mc->gs = xnuss->__gs;
|
||||
mc->fs = xnuss->__fs;
|
||||
|
@ -410,10 +404,29 @@ static void xnuthreadstate2linux(ucontext_t *uc, mcontext_t *mc,
|
|||
memcpy(&mc->r8, &xnuss->__r8, 8 * sizeof(int64_t));
|
||||
}
|
||||
|
||||
static void linuxthreadstate2xnu(struct __darwin_x86_thread_state64 *xnuss,
|
||||
ucontext_t *uc, mcontext_t *mc) {
|
||||
xnuss->__rdi = mc->rdi;
|
||||
xnuss->__rsi = mc->rsi;
|
||||
xnuss->__rbp = mc->rbp;
|
||||
xnuss->__rbx = mc->rbx;
|
||||
xnuss->__rdx = mc->rdx;
|
||||
xnuss->__rax = mc->rax;
|
||||
xnuss->__rcx = mc->rcx;
|
||||
xnuss->__rsp = mc->rsp;
|
||||
xnuss->__rip = mc->rip;
|
||||
xnuss->__cs = mc->cs;
|
||||
xnuss->__gs = mc->gs;
|
||||
xnuss->__fs = mc->fs;
|
||||
xnuss->__rflags = mc->eflags;
|
||||
xnuss->__rflags = uc->uc_flags;
|
||||
memcpy(&xnuss->__r8, &mc->r8, 8 * sizeof(int64_t));
|
||||
}
|
||||
|
||||
static void xnussefpustate2linux(struct FpuState *fs,
|
||||
struct __darwin_x86_float_state64 *xnufs) {
|
||||
memcpy(&fs->cwd, &xnufs->__fpu_fcw, 2);
|
||||
memcpy(&fs->swd, &xnufs->__fpu_fsw, 2);
|
||||
fs->cwd = xnufs->__fpu_fcw;
|
||||
fs->swd = xnufs->__fpu_fsw;
|
||||
fs->ftw = xnufs->__fpu_ftw;
|
||||
fs->fop = xnufs->__fpu_fop;
|
||||
fs->rip = xnufs->__fpu_ip;
|
||||
|
@ -424,49 +437,91 @@ static void xnussefpustate2linux(struct FpuState *fs,
|
|||
memcpy(fs->st, &xnufs->__fpu_stmm0, (8 + 16) * sizeof(uint128_t));
|
||||
}
|
||||
|
||||
wontreturn void __xnutrampoline(void *fn, int infostyle, int sig,
|
||||
const struct __darwin_siginfo *xnuinfo,
|
||||
const struct __darwin_ucontext *xnuctx) {
|
||||
/* note: this function impl can't access static memory */
|
||||
static void linuxssefpustate2xnu(struct __darwin_x86_float_state64 *xnufs,
|
||||
struct FpuState *fs) {
|
||||
xnufs->__fpu_fcw = fs->cwd;
|
||||
xnufs->__fpu_fsw = fs->swd;
|
||||
xnufs->__fpu_ftw = fs->ftw;
|
||||
xnufs->__fpu_fop = fs->fop;
|
||||
xnufs->__fpu_ip = fs->rip;
|
||||
xnufs->__fpu_dp = fs->rdp;
|
||||
xnufs->__fpu_mxcsr = fs->mxcsr;
|
||||
xnufs->__fpu_mxcsrmask = fs->mxcr_mask;
|
||||
/* copy st0-st7 as well as xmm0-xmm15 */
|
||||
memcpy(&xnufs->__fpu_stmm0, fs->st, (8 + 16) * sizeof(uint128_t));
|
||||
}
|
||||
|
||||
void __sigenter_xnu(void *fn, int infostyle, int sig,
|
||||
struct __darwin_siginfo *xnuinfo,
|
||||
struct __darwin_ucontext *xnuctx) {
|
||||
int rva;
|
||||
intptr_t ax;
|
||||
struct Goodies {
|
||||
ucontext_t uc;
|
||||
siginfo_t si;
|
||||
} g;
|
||||
memset(&g, 0, sizeof(g));
|
||||
if (xnuctx) {
|
||||
/* g.uc.uc_sigmask = xnuctx->uc_sigmask; */
|
||||
g.uc.uc_stack.ss_sp = xnuctx->uc_stack.ss_sp;
|
||||
g.uc.uc_stack.ss_flags = xnuctx->uc_stack.ss_flags;
|
||||
g.uc.uc_stack.ss_size = xnuctx->uc_stack.ss_size;
|
||||
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
|
||||
if (xnuctx->uc_mcontext) {
|
||||
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_x86_exception_state64)) {
|
||||
xnuexceptionstate2linux(&g.uc.uc_mcontext, &xnuctx->uc_mcontext->__es);
|
||||
rva = __sighandrvas[sig & (NSIG - 1)];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
memset(&g, 0, sizeof(g));
|
||||
if (xnuctx) {
|
||||
memcpy(&g.uc.uc_sigmask, &xnuctx->uc_sigmask,
|
||||
MIN(sizeof(g.uc.uc_sigmask), sizeof(xnuctx->uc_sigmask)));
|
||||
g.uc.uc_stack.ss_sp = xnuctx->uc_stack.ss_sp;
|
||||
g.uc.uc_stack.ss_flags = xnuctx->uc_stack.ss_flags;
|
||||
g.uc.uc_stack.ss_size = xnuctx->uc_stack.ss_size;
|
||||
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
|
||||
if (xnuctx->uc_mcontext) {
|
||||
if (xnuctx->uc_mcsize >=
|
||||
sizeof(struct __darwin_x86_exception_state64)) {
|
||||
xnuexceptionstate2linux(&g.uc.uc_mcontext,
|
||||
&xnuctx->uc_mcontext->__es);
|
||||
}
|
||||
if (xnuctx->uc_mcsize >=
|
||||
(sizeof(struct __darwin_x86_exception_state64) +
|
||||
sizeof(struct __darwin_x86_thread_state64))) {
|
||||
xnuthreadstate2linux(&g.uc, &g.uc.uc_mcontext,
|
||||
&xnuctx->uc_mcontext->__ss);
|
||||
}
|
||||
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_mcontext64)) {
|
||||
xnussefpustate2linux(&g.uc.__fpustate, &xnuctx->uc_mcontext->__fs);
|
||||
}
|
||||
}
|
||||
if (xnuctx->uc_mcsize >= (sizeof(struct __darwin_x86_exception_state64) +
|
||||
sizeof(struct __darwin_x86_thread_state64))) {
|
||||
xnuthreadstate2linux(&g.uc, &g.uc.uc_mcontext,
|
||||
&xnuctx->uc_mcontext->__ss);
|
||||
}
|
||||
if (xnuinfo) {
|
||||
g.si.si_signo = xnuinfo->si_signo;
|
||||
g.si.si_errno = xnuinfo->si_errno;
|
||||
g.si.si_code = xnuinfo->si_code;
|
||||
if (xnuinfo->si_pid) {
|
||||
g.si.si_pid = xnuinfo->si_pid;
|
||||
g.si.si_uid = xnuinfo->si_uid;
|
||||
g.si.si_status = xnuinfo->si_status;
|
||||
} else {
|
||||
g.si.si_addr = (void *)xnuinfo->si_addr;
|
||||
}
|
||||
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_mcontext64)) {
|
||||
xnussefpustate2linux(&g.uc.__fpustate, &xnuctx->uc_mcontext->__fs);
|
||||
}
|
||||
((sigaction_f)(_base + rva))(sig, &g.si, &g.uc);
|
||||
if (xnuctx) {
|
||||
xnuctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp;
|
||||
xnuctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags;
|
||||
xnuctx->uc_stack.ss_size = g.uc.uc_stack.ss_size;
|
||||
if (xnuctx->uc_mcontext) {
|
||||
if (xnuctx->uc_mcsize >=
|
||||
sizeof(struct __darwin_x86_exception_state64)) {
|
||||
linuxexceptionstate2xnu(&xnuctx->uc_mcontext->__es,
|
||||
&g.uc.uc_mcontext);
|
||||
}
|
||||
if (xnuctx->uc_mcsize >=
|
||||
(sizeof(struct __darwin_x86_exception_state64) +
|
||||
sizeof(struct __darwin_x86_thread_state64))) {
|
||||
linuxthreadstate2xnu(&xnuctx->uc_mcontext->__ss, &g.uc,
|
||||
&g.uc.uc_mcontext);
|
||||
}
|
||||
if (xnuctx->uc_mcsize >= sizeof(struct __darwin_mcontext64)) {
|
||||
linuxssefpustate2xnu(&xnuctx->uc_mcontext->__fs, &g.uc.__fpustate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xnuinfo) {
|
||||
g.si.si_signo = xnuinfo->si_signo;
|
||||
g.si.si_errno = xnuinfo->si_errno;
|
||||
g.si.si_code = xnuinfo->si_code;
|
||||
if (xnuinfo->si_pid) {
|
||||
g.si.si_pid = xnuinfo->si_pid;
|
||||
g.si.si_uid = xnuinfo->si_uid;
|
||||
g.si.si_status = xnuinfo->si_status;
|
||||
} else {
|
||||
g.si.si_addr = (void *)xnuinfo->si_addr;
|
||||
}
|
||||
}
|
||||
__sigenter(sig, &g.si, &g.uc);
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(0x20000b8 /* sigreturn */), "D"(xnuctx), "S"(infostyle)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/struct/utsname.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -32,6 +33,7 @@
|
|||
#include "libc/nexgen32e/stackframe.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/memtrack.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
@ -39,17 +41,11 @@
|
|||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
STATIC_YOINK("ftoa");
|
||||
STATIC_YOINK("ntoa");
|
||||
STATIC_YOINK("stoa");
|
||||
|
||||
/**
|
||||
* @fileoverview Abnormal termination handling & GUI debugging.
|
||||
* @see libc/onkill.c
|
||||
*/
|
||||
|
||||
struct siginfo;
|
||||
|
||||
static const char kGregOrder[17] forcealign(1) = {
|
||||
13, 11, 8, 14, 12, 9, 10, 15, 16, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
};
|
||||
|
@ -59,7 +55,8 @@ static const char kGregNames[17][4] forcealign(1) = {
|
|||
"RSI", "RBP", "RBX", "RDX", "RAX", "RCX", "RSP", "RIP",
|
||||
};
|
||||
|
||||
static const char kGodHatesFlags[12] forcealign(1) = "CVPRAKZSTIDO";
|
||||
static const char kCpuFlags[12] forcealign(1) = "CVPRAKZSTIDO";
|
||||
static const char kFpuExceptions[6] forcealign(1) = "IDZOUP";
|
||||
static const char kCrashSigNames[8][5] forcealign(1) = {
|
||||
"QUIT", "FPE", "ILL", "SEGV", "TRAP", "ABRT", "BUS"};
|
||||
|
||||
|
@ -88,20 +85,36 @@ relegated static void ShowFunctionCalls(int fd, ucontext_t *ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
relegated static void DescribeCpuFlags(int fd, unsigned flags) {
|
||||
relegated static char *AddFlag(char *p, int b, const char *s) {
|
||||
if (b) p = stpcpy(p, s);
|
||||
return p;
|
||||
}
|
||||
|
||||
relegated static void DescribeCpuFlags(int fd, int flags, int x87sw,
|
||||
int mxcsr) {
|
||||
unsigned i;
|
||||
char buf[64], *p;
|
||||
p = buf;
|
||||
for (i = 0; i < ARRAYLEN(kGodHatesFlags); ++i) {
|
||||
for (i = 0; i < ARRAYLEN(kCpuFlags); ++i) {
|
||||
if (flags & 1) {
|
||||
*p++ = ' ';
|
||||
*p++ = kGodHatesFlags[i];
|
||||
*p++ = kCpuFlags[i];
|
||||
*p++ = 'F';
|
||||
}
|
||||
flags >>= 1;
|
||||
}
|
||||
p = stpcpy(p, " IOPL");
|
||||
*p++ = '0' + (flags & 3);
|
||||
for (i = 0; i < ARRAYLEN(kFpuExceptions); ++i) {
|
||||
if ((x87sw | mxcsr) & (1 << i)) {
|
||||
*p++ = ' ';
|
||||
*p++ = kFpuExceptions[i];
|
||||
*p++ = 'E';
|
||||
}
|
||||
}
|
||||
p = AddFlag(p, x87sw & FPU_SF, " SF");
|
||||
p = AddFlag(p, x87sw & FPU_C0, " C0");
|
||||
p = AddFlag(p, x87sw & FPU_C1, " C1");
|
||||
p = AddFlag(p, x87sw & FPU_C2, " C2");
|
||||
p = AddFlag(p, x87sw & FPU_C3, " C3");
|
||||
write(fd, buf, p - buf);
|
||||
}
|
||||
|
||||
|
@ -111,8 +124,8 @@ relegated static void ShowGeneralRegisters(int fd, ucontext_t *ctx) {
|
|||
write(fd, "\r\n", 2);
|
||||
for (i = 0, j = 0, k = 0; i < ARRAYLEN(kGregNames); ++i) {
|
||||
if (j > 0) write(fd, " ", 1);
|
||||
(dprintf)(fd, "%-3s %016lx", kGregNames[(unsigned)kGregOrder[i]],
|
||||
ctx->uc_mcontext.gregs[(unsigned)kGregOrder[i]]);
|
||||
dprintf(fd, "%-3s %016lx", kGregNames[(unsigned)kGregOrder[i]],
|
||||
ctx->uc_mcontext.gregs[(unsigned)kGregOrder[i]]);
|
||||
if (++j == 3) {
|
||||
j = 0;
|
||||
if (ctx->uc_mcontext.fpregs) {
|
||||
|
@ -120,12 +133,15 @@ relegated static void ShowGeneralRegisters(int fd, ucontext_t *ctx) {
|
|||
} else {
|
||||
memset(&st, 0, sizeof(st));
|
||||
}
|
||||
(dprintf)(fd, " %s(%zu) %Lf", "ST", k, st);
|
||||
dprintf(fd, " %s(%zu) %Lf", "ST", k, st);
|
||||
++k;
|
||||
write(fd, "\r\n", 2);
|
||||
}
|
||||
}
|
||||
DescribeCpuFlags(fd, ctx->uc_mcontext.gregs[REG_EFL]);
|
||||
DescribeCpuFlags(
|
||||
fd, ctx->uc_mcontext.gregs[REG_EFL],
|
||||
ctx->uc_mcontext.fpregs ? ctx->uc_mcontext.fpregs->swd : 0,
|
||||
ctx->uc_mcontext.fpregs ? ctx->uc_mcontext.fpregs->mxcsr : 0);
|
||||
}
|
||||
|
||||
relegated static void ShowSseRegisters(int fd, ucontext_t *ctx) {
|
||||
|
@ -133,11 +149,11 @@ relegated static void ShowSseRegisters(int fd, ucontext_t *ctx) {
|
|||
if (ctx->uc_mcontext.fpregs) {
|
||||
write(fd, "\r\n\r\n", 4);
|
||||
for (i = 0; i < 8; ++i) {
|
||||
(dprintf)(fd, VEIL("r", "%s%-2zu %016lx%016lx %s%-2d %016lx%016lx\r\n"),
|
||||
"XMM", i + 0, ctx->uc_mcontext.fpregs->xmm[i + 0].u64[1],
|
||||
ctx->uc_mcontext.fpregs->xmm[i + 0].u64[0], "XMM", i + 8,
|
||||
ctx->uc_mcontext.fpregs->xmm[i + 8].u64[1],
|
||||
ctx->uc_mcontext.fpregs->xmm[i + 8].u64[0]);
|
||||
dprintf(fd, "%s%-2zu %016lx%016lx %s%-2d %016lx%016lx\r\n", "XMM", i + 0,
|
||||
ctx->uc_mcontext.fpregs->xmm[i + 0].u64[1],
|
||||
ctx->uc_mcontext.fpregs->xmm[i + 0].u64[0], "XMM", i + 8,
|
||||
ctx->uc_mcontext.fpregs->xmm[i + 8].u64[1],
|
||||
ctx->uc_mcontext.fpregs->xmm[i + 8].u64[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,13 +180,12 @@ relegated static void ShowCrashReport(int err, int fd, int sig,
|
|||
struct utsname names;
|
||||
strcpy(hostname, "unknown");
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
(dprintf)(
|
||||
fd, VEIL("r", "\r\n%serror%s: Uncaught SIG%s on %s\r\n %s\r\n %s\r\n"),
|
||||
RED2, RESET, TinyStrSignal(sig), hostname, getauxval(AT_EXECFN),
|
||||
strerror(err));
|
||||
dprintf(fd, "\r\n%serror%s: Uncaught SIG%s on %s\r\n %s\r\n %s\r\n", RED2,
|
||||
RESET, TinyStrSignal(sig), hostname, getauxval(AT_EXECFN),
|
||||
strerror(err));
|
||||
if (uname(&names) != -1) {
|
||||
(dprintf)(fd, VEIL("r", " %s %s %s %s\r\n"), names.sysname, names.nodename,
|
||||
names.release, names.version);
|
||||
dprintf(fd, " %s %s %s %s\r\n", names.sysname, names.nodename,
|
||||
names.release, names.version);
|
||||
}
|
||||
ShowFunctionCalls(fd, ctx);
|
||||
if (ctx) {
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
// @note therefore item/values are reordered w.r.t. link order
|
||||
// @note therefore no section relative addressing
|
||||
.macro .rodata.str1.1
|
||||
.section .rodata.str1.1,"aSM",@progbits,1
|
||||
.section .rodata.str1.1,"aMS",@progbits,1
|
||||
.align 1
|
||||
.endm
|
||||
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
#include "libc/macros.h"
|
||||
#include "libc/notice.inc"
|
||||
|
||||
.initbss 300,_init___argv
|
||||
/ Global variable holding _start(argv) parameter.
|
||||
.initbss 300,_init_argv
|
||||
// Global variable holding _start(argv) parameter.
|
||||
__argv: .quad 0
|
||||
.endobj __argv,globl
|
||||
.previous
|
||||
|
||||
.init.start 300,_init___argv
|
||||
.init.start 300,_init_argv
|
||||
mov %r13,%rax
|
||||
stosq
|
||||
.init.end 300,_init___argv
|
||||
.init.end 300,_init_argv
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
#include "libc/macros.h"
|
||||
#include "libc/notice.inc"
|
||||
|
||||
.initbss 300,_init___auxv
|
||||
/ Global variable holding _start(auxv) parameter.
|
||||
.initbss 300,_init_auxv
|
||||
// Global variable holding _start(auxv) parameter.
|
||||
__auxv: .quad 0
|
||||
.endobj __auxv,globl
|
||||
.previous
|
||||
|
||||
.init.start 300,_init___auxv
|
||||
.init.start 300,_init_auxv
|
||||
mov %r15,%rax
|
||||
stosq
|
||||
.init.end 300,_init___auxv
|
||||
.init.end 300,_init_auxv
|
||||
|
|
|
@ -24,9 +24,13 @@
|
|||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
textwindows wontreturn void sys_abort_nt(void) {
|
||||
int rva;
|
||||
siginfo_t info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.si_signo = SIGABRT;
|
||||
__sigenter(SIGABRT, &info, NULL);
|
||||
rva = __sighandrvas[SIGABRT];
|
||||
if (rva >= kSigactionMinRva) {
|
||||
((sigaction_f)(_base + rva))(SIGABRT, &info, NULL);
|
||||
}
|
||||
_Exit(128 + SIGABRT);
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
|
|||
* Allocates and clears PC-compatible memory and copies image.
|
||||
*/
|
||||
SystemTable->BootServices->AllocatePages(
|
||||
EfiConventionalMemory, AllocateAddress,
|
||||
AllocateAddress, EfiConventionalMemory,
|
||||
MAX(2 * 1024 * 1024, 1024 * 1024 + (_end - _base)) / 4096, 0);
|
||||
SystemTable->BootServices->SetMem(0, 0x80000, 0);
|
||||
SystemTable->BootServices->CopyMem((void *)(1024 * 1024), _base,
|
||||
|
|
|
@ -19,13 +19,13 @@
|
|||
#include "libc/macros.h"
|
||||
#include "libc/notice.inc"
|
||||
|
||||
.initbss 300,_init___argc
|
||||
/ Global variable holding _start(argc) parameter.
|
||||
.initbss 300,_init_argc
|
||||
// Global variable holding _start(argc) parameter.
|
||||
__argc: .quad 0
|
||||
.endobj __argc,globl
|
||||
.previous
|
||||
|
||||
.init.start 300,_init___argc
|
||||
.init.start 300,_init_argc
|
||||
mov %r12,%rax
|
||||
stosq
|
||||
.init.end 300,_init___argc
|
||||
.init.end 300,_init_argc
|
||||
|
|
|
@ -58,8 +58,12 @@
|
|||
B: FPU Busy ───────────┐│ │ │ ││││││││
|
||||
││┌┴┐┌┼┐││││││││
|
||||
│↓│ │↓↓↓││││││││*/
|
||||
#define FPU_IE 0b0000000000100000000000001
|
||||
#define FPU_ZE 0b0000000000100000000000100
|
||||
#define FPU_IE 0b0000000000000000000000001
|
||||
#define FPU_DE 0b0000000000000000000000010
|
||||
#define FPU_ZE 0b0000000000000000000000100
|
||||
#define FPU_OE 0b0000000000000000000001000
|
||||
#define FPU_UE 0b0000000000000000000010000
|
||||
#define FPU_PE 0b0000000000000000000100000
|
||||
#define FPU_SF 0b0000000000000000001000000
|
||||
#define FPU_C0 0b0000000000000000100000000
|
||||
#define FPU_C1 0b0000000000000001000000000
|
||||
|
|
|
@ -66,7 +66,20 @@ static noasan textwindows void SetTrueColor(void) {
|
|||
}
|
||||
|
||||
static noasan textwindows void MakeLongDoubleLongAgain(void) {
|
||||
int x87cw = 0x037f; /* let's hope win32 won't undo this */
|
||||
/* 8087 FPU Control Word
|
||||
IM: Invalid Operation ───────────────┐
|
||||
DM: Denormal Operand ───────────────┐│
|
||||
ZM: Zero Divide ───────────────────┐││
|
||||
OM: Overflow ─────────────────────┐│││
|
||||
UM: Underflow ───────────────────┐││││
|
||||
PM: Precision ──────────────────┐│││││
|
||||
PC: Precision Control ────────┐ ││││││
|
||||
{float,∅,double,long double} │ ││││││
|
||||
RC: Rounding Control ───────┐ │ ││││││
|
||||
{even, →-∞, →+∞, →0} │┌┤ ││││││
|
||||
┌┤││ ││││││
|
||||
d││││rr││││││*/
|
||||
int x87cw = 0b0000000000000000001101111111;
|
||||
asm volatile("fldcw\t%0" : /* no outputs */ : "m"(x87cw));
|
||||
}
|
||||
|
||||
|
|
|
@ -1792,12 +1792,12 @@ syscon misc SCSI_IOCTL_TAGGED_DISABLE 0x5384 0 0 0 0 0
|
|||
syscon misc SCSI_IOCTL_TAGGED_ENABLE 0x5383 0 0 0 0 0
|
||||
syscon misc SCSI_IOCTL_TEST_UNIT_READY 2 0 0 0 0 0
|
||||
|
||||
syscon misc CLD_CONTINUED 6 6 6 6 6 0 # unix consensus
|
||||
syscon misc CLD_DUMPED 3 3 3 3 3 0 # unix consensus
|
||||
syscon misc CLD_EXITED 1 1 1 1 1 0 # unix consensus
|
||||
syscon misc CLD_KILLED 2 2 2 2 2 0 # unix consensus
|
||||
syscon misc CLD_STOPPED 5 5 5 5 5 0 # unix consensus
|
||||
syscon misc CLD_TRAPPED 4 4 4 4 4 0 # unix consensus
|
||||
syscon misc CLD_CONTINUED 6 6 6 6 6 6 # unix consensus
|
||||
syscon misc CLD_DUMPED 3 3 3 3 3 3 # unix consensus
|
||||
syscon misc CLD_EXITED 1 1 1 1 1 1 # unix consensus
|
||||
syscon misc CLD_KILLED 2 2 2 2 2 2 # unix consensus
|
||||
syscon misc CLD_STOPPED 5 5 5 5 5 5 # unix consensus
|
||||
syscon misc CLD_TRAPPED 4 4 4 4 4 4 # unix consensus
|
||||
|
||||
syscon misc READ_10 40 0 0 0 0 0
|
||||
syscon misc READ_12 168 0 0 0 0 0
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,CLD_CONTINUED,6,6,6,6,6,0
|
||||
.syscon misc,CLD_CONTINUED,6,6,6,6,6,6
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,CLD_DUMPED,3,3,3,3,3,0
|
||||
.syscon misc,CLD_DUMPED,3,3,3,3,3,3
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,CLD_EXITED,1,1,1,1,1,0
|
||||
.syscon misc,CLD_EXITED,1,1,1,1,1,1
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,CLD_KILLED,2,2,2,2,2,0
|
||||
.syscon misc,CLD_KILLED,2,2,2,2,2,2
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,CLD_STOPPED,5,5,5,5,5,0
|
||||
.syscon misc,CLD_STOPPED,5,5,5,5,5,5
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#include "libc/sysv/consts/syscon.internal.h"
|
||||
.syscon misc,CLD_TRAPPED,4,4,4,4,4,0
|
||||
.syscon misc,CLD_TRAPPED,4,4,4,4,4,4
|
||||
|
|
|
@ -1,24 +1,11 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_SYSV_CONSTS_CLD_H_
|
||||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_CLD_H_
|
||||
#include "libc/runtime/symbolic.h"
|
||||
|
||||
#define CLD_CONTINUED SYMBOLIC(CLD_CONTINUED)
|
||||
#define CLD_DUMPED SYMBOLIC(CLD_DUMPED)
|
||||
#define CLD_EXITED SYMBOLIC(CLD_EXITED)
|
||||
#define CLD_KILLED SYMBOLIC(CLD_KILLED)
|
||||
#define CLD_STOPPED SYMBOLIC(CLD_STOPPED)
|
||||
#define CLD_TRAPPED SYMBOLIC(CLD_TRAPPED)
|
||||
#define CLD_CONTINUED 6
|
||||
#define CLD_DUMPED 3
|
||||
#define CLD_EXITED 1
|
||||
#define CLD_KILLED 2
|
||||
#define CLD_STOPPED 5
|
||||
#define CLD_TRAPPED 4
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const long CLD_CONTINUED;
|
||||
extern const long CLD_DUMPED;
|
||||
extern const long CLD_EXITED;
|
||||
extern const long CLD_KILLED;
|
||||
extern const long CLD_STOPPED;
|
||||
extern const long CLD_TRAPPED;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_CLD_H_ */
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
|
||||
|
||||
Cosmopolitan TinyMath
|
||||
|
||||
“Seymour Cray didn't care that 81.0/3.0 did not give exactly
|
||||
27.0 on the CDC 6000 class machines; and he was universally
|
||||
respected for making the fastest machines around.
|
||||
──Linus Torvalds
|
||||
|
||||
|
||||
Your Cosmopolitan TinyMath library provides hardware-accelerated scalar
|
||||
transcendental mathematical functions that are superior to the portable
|
||||
standards-compliant math library, in terms of both performance and code
|
||||
size, by trading away focus on temporal concerns, like IEEE conformance
|
||||
or rounding errors at the femto-scale, or reproducible results across a
|
||||
broad array of niche machine languages.
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns arc cosine of 𝑥.
|
||||
//
|
||||
|
|
|
@ -17,8 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑥 with same sign as 𝑦.
|
||||
//
|
||||
// @param 𝑥 is double scalar in low half of %xmm0
|
||||
// @param 𝑦 is double scalar in low half of %xmm1
|
||||
// @return double scalar in low half of %xmm0
|
||||
copysign:
|
||||
.leafprologue
|
||||
.profilable
|
||||
|
|
|
@ -17,8 +17,12 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑥 with same sign as 𝑦.
|
||||
//
|
||||
// @param 𝑦 is float scalar in low quarter of %xmm0
|
||||
// @param 𝑥 is float scalar in low quarter of %xmm1
|
||||
// @return float scalar in low quarter of %xmm0
|
||||
copysignf:
|
||||
.leafprologue
|
||||
.profilable
|
||||
|
|
|
@ -18,8 +18,12 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑥 with same sign as 𝑦.
|
||||
//
|
||||
// @param 𝑥 is an 80-bit long double passed on stack in 16-bytes
|
||||
// @param 𝑦 is the power, also pushed on stack, in reverse order
|
||||
// @return result on FPU stack in %st
|
||||
copysignl:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑒^x.
|
||||
//
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 10^x.
|
||||
//
|
||||
|
|
|
@ -17,17 +17,21 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 10^x.
|
||||
//
|
||||
// @param 𝑥 is an 80-bit long double passed on stack in 16-bytes
|
||||
// @return result of exponentiation on FPU stack in %st
|
||||
exp10l:
|
||||
push %rbp
|
||||
exp10l: push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
fldt 16(%rbp)
|
||||
fxam # isinf(x)
|
||||
fstsw %ax
|
||||
mov %ah,%al
|
||||
and $0x45,%ah
|
||||
cmp $5,%ah
|
||||
je 1f
|
||||
fldl2t
|
||||
fmulp %st,%st(1)
|
||||
fld %st
|
||||
|
@ -38,8 +42,13 @@ exp10l:
|
|||
fld1
|
||||
faddp
|
||||
fscale
|
||||
fstp %st(1)
|
||||
0: fstp %st(1)
|
||||
pop %rbp
|
||||
ret
|
||||
1: test $2,%al # signbit(x)
|
||||
jz 0b
|
||||
fstp %st
|
||||
fldz
|
||||
jmp 0b
|
||||
.endfn exp10l,globl
|
||||
.alias exp10l,pow10l
|
||||
|
|
|
@ -17,13 +17,11 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 2^𝑥.
|
||||
//
|
||||
// @param 𝑥 is a double passed in the lower quadword of %xmm0
|
||||
// @return result in lower quadword of %xmm0
|
||||
exp2:
|
||||
ezlea exp2l,ax
|
||||
exp2: ezlea exp2l,ax
|
||||
jmp _d2ld2
|
||||
.endfn exp2,globl
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 2^𝑥.
|
||||
//
|
||||
|
@ -27,17 +26,26 @@ exp2l: push %rbp
|
|||
mov %rsp,%rbp
|
||||
.profilable
|
||||
fldt 16(%rbp)
|
||||
fxam # isinf(x)
|
||||
fstsw %ax
|
||||
mov %ah,%al
|
||||
and $0x45,%ah
|
||||
cmp $5,%ah
|
||||
je 1f
|
||||
fld %st
|
||||
frndint
|
||||
fsubr %st,%st(1)
|
||||
fxch
|
||||
f2xm1
|
||||
fadds .Lone(%rip)
|
||||
fld1
|
||||
faddp
|
||||
fscale
|
||||
fstp %st(1)
|
||||
pop %rbp
|
||||
0: pop %rbp
|
||||
ret
|
||||
1: test $2,%al # signbit(x)
|
||||
jz 0b
|
||||
fstp %st
|
||||
fldz
|
||||
jmp 0b
|
||||
.endfn exp2l,globl
|
||||
|
||||
.rodata.cst4
|
||||
.Lone: .float 1.0
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑒^x.
|
||||
//
|
||||
|
@ -27,6 +26,12 @@ expl: push %rbp
|
|||
mov %rsp,%rbp
|
||||
.profilable
|
||||
fldt 16(%rbp)
|
||||
fxam # isinf(x)
|
||||
fstsw %ax
|
||||
mov %ah,%al
|
||||
and $0x45,%ah
|
||||
cmp $5,%ah
|
||||
je 1f
|
||||
fldl2e
|
||||
fmulp %st,%st(1)
|
||||
fld %st
|
||||
|
@ -38,6 +43,11 @@ expl: push %rbp
|
|||
faddp
|
||||
fscale
|
||||
fstp %st(1)
|
||||
pop %rbp
|
||||
0: pop %rbp
|
||||
ret
|
||||
1: test $2,%al # signbit(x)
|
||||
jz 0b
|
||||
fstp %st
|
||||
fldz
|
||||
jmp 0b
|
||||
.endfn expl,globl
|
||||
|
|
|
@ -17,13 +17,11 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑒^x-1.
|
||||
//
|
||||
// @param 𝑥 is double scalar in low half of %xmm0
|
||||
// @return double scalar in low half of %xmm0
|
||||
expm1:
|
||||
ezlea expm1l,ax
|
||||
expm1: ezlea expm1l,ax
|
||||
jmp _d2ld2
|
||||
.endfn expm1,globl
|
||||
|
|
|
@ -16,18 +16,23 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑒^x-1.
|
||||
//
|
||||
// @param 𝑥 is an 80-bit long double passed on stack in 16-bytes
|
||||
// @return result of exponentiation on FPU stack in %st
|
||||
expm1l:
|
||||
push %rbp
|
||||
expm1l: push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
fldt 16(%rbp)
|
||||
fxam # isinf(x)
|
||||
fstsw %ax
|
||||
mov %ah,%al
|
||||
and $0x45,%ah
|
||||
cmp $5,%ah
|
||||
je 1f
|
||||
fldl2e
|
||||
fmulp %st,%st(1)
|
||||
fld %st
|
||||
|
@ -40,11 +45,15 @@ expm1l:
|
|||
fxch %st(2)
|
||||
fscale
|
||||
fstp %st(1)
|
||||
fsubs .Lone(%rip)
|
||||
fld1
|
||||
fsubrp
|
||||
faddp %st,%st(1)
|
||||
pop %rbp
|
||||
0: pop %rbp
|
||||
ret
|
||||
1: test $2,%al # signbit(x)
|
||||
jz 0b
|
||||
fstp %st
|
||||
fld1
|
||||
3: fchs
|
||||
jmp 0b
|
||||
.endfn expm1l,globl
|
||||
|
||||
.rodata.cst4
|
||||
.Lone: .float 1.0
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns absolute value of 𝑥.
|
||||
//
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// fmod [sic] does (𝑥 rem 𝑦) w/ round()-style rounding.
|
||||
//
|
||||
|
|
|
@ -18,8 +18,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// fmod [sic] does (𝑥 rem 𝑦) w/ round()-style rounding.
|
||||
//
|
||||
// @param 𝑥 is an 80-bit long double passed on stack in 16-bytes
|
||||
// @param 𝑦 is the power, also pushed on stack, in reverse order
|
||||
// @return remainder ∈ (-|𝑦|,|𝑦|) in %st
|
||||
// @define 𝑥-truncl(𝑥/𝑦)*𝑦
|
||||
// @see emod()
|
||||
fmodl: push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
|
@ -32,4 +38,7 @@ fmodl: push %rbp
|
|||
fstp %st(1)
|
||||
pop %rbp
|
||||
ret
|
||||
1: int3
|
||||
pop %rbp
|
||||
ret
|
||||
.endfn fmodl,globl
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑥 × 2ʸ.
|
||||
//
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑥 × 2ʸ.
|
||||
//
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns natural logarithm of 𝑥.
|
||||
//
|
||||
|
|
|
@ -17,18 +17,16 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns log(𝟷+𝑥).
|
||||
//
|
||||
// @param 𝑥 is double scalar in low half of %xmm0
|
||||
// @return double scalar in low half of %xmm0
|
||||
log1p:
|
||||
push %rbp
|
||||
log1p: push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
push %rax
|
||||
vmovsd %xmm0,(%rsp)
|
||||
movsd %xmm0,(%rsp)
|
||||
fldl (%rsp)
|
||||
fld %st
|
||||
fabs
|
||||
|
@ -41,7 +39,7 @@ log1p:
|
|||
fxch
|
||||
fyl2xp1
|
||||
fstpl (%rsp)
|
||||
vmovsd (%rsp),%xmm0
|
||||
movsd (%rsp),%xmm0
|
||||
0: leave
|
||||
ret
|
||||
1: fld1
|
||||
|
@ -50,12 +48,12 @@ log1p:
|
|||
fxch
|
||||
fyl2x
|
||||
fstpl (%rsp)
|
||||
vmovsd (%rsp),%xmm0
|
||||
movsd (%rsp),%xmm0
|
||||
jmp 0b
|
||||
.endfn log1p,globl
|
||||
|
||||
.rodata.cst16
|
||||
.LC16: .long 205731576
|
||||
.long 2515933592
|
||||
.long 16381
|
||||
.LC16: .long 0x0c4336f8
|
||||
.long 0x95f61998
|
||||
.long 0x3ffd
|
||||
.long 0
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns log(𝟷+𝑥).
|
||||
//
|
||||
|
@ -27,11 +26,11 @@ log1pf: push %rbp
|
|||
mov %rsp,%rbp
|
||||
.profilable
|
||||
push %rax
|
||||
vmovss %xmm0,-4(%rbp)
|
||||
movss %xmm0,-4(%rbp)
|
||||
flds -4(%rbp)
|
||||
fld %st
|
||||
fabs
|
||||
fldt .LC16(%rip)
|
||||
fldt .Lnnan(%rip)
|
||||
fxch
|
||||
fcomip %st(1),%st
|
||||
fstp %st
|
||||
|
@ -40,7 +39,7 @@ log1pf: push %rbp
|
|||
fxch
|
||||
fyl2xp1
|
||||
1: fstps -4(%rbp)
|
||||
vmovss -4(%rbp),%xmm0
|
||||
movss -4(%rbp),%xmm0
|
||||
leave
|
||||
ret
|
||||
2: fld1
|
||||
|
@ -52,7 +51,7 @@ log1pf: push %rbp
|
|||
.endfn log1pf,globl
|
||||
|
||||
.rodata.cst16
|
||||
.LC16: .long 205731576
|
||||
.long 2515933592
|
||||
.long 16381
|
||||
.Lnnan: .long 0x0c4336f8
|
||||
.long 0x95f61998
|
||||
.long 0x3ffd
|
||||
.long 0
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Calculates log₂𝑥.
|
||||
//
|
||||
|
|
|
@ -17,15 +17,13 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Calculates log₂𝑥.
|
||||
//
|
||||
// @param 𝑥 is an 80-bit long double passed on stack in 16-bytes
|
||||
// @return result in %st
|
||||
// @see ilogbl()
|
||||
log2l:
|
||||
push %rbp
|
||||
log2l: push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
fld1
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns natural logarithm of 𝑥.
|
||||
//
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑥^𝑦.
|
||||
//
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns 𝑥^𝑦.
|
||||
//
|
||||
|
@ -25,6 +24,7 @@
|
|||
// @param 𝑦 is the power, also pushed on stack, in reverse order
|
||||
// @return result of exponentiation on FPU stack in %st
|
||||
// @note Sun's fdlibm needs 2kLOC to do this for RISC lool
|
||||
// @define exp2l(fmodl(y*log2l(x),1))*exp2l(y)
|
||||
powl: push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns sine of 𝑥.
|
||||
//
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns square root of 𝑥.
|
||||
//
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns square root of 𝑥.
|
||||
//
|
||||
|
|
|
@ -29,8 +29,9 @@ int xwrite(int, const void *, uint64_t);
|
|||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
void xdie(void) wontreturn;
|
||||
char *xdtoa(double) _XMAL;
|
||||
char *xdtoaf(float) _XMAL;
|
||||
char *xdtoa(long double) _XMAL;
|
||||
char *xdtoal(long double) _XMAL;
|
||||
char *xasprintf(const char *, ...) printfesque(1) paramsnonnull((1)) _XMAL;
|
||||
char *xvasprintf(const char *, va_list) _XPNN _XMAL;
|
||||
char *xgetline(struct FILE *) _XPNN mallocesque;
|
||||
|
|
|
@ -16,17 +16,18 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
|
||||
/**
|
||||
* Converts double to string w/ high-accuracy the easy way.
|
||||
* Converts double to string the easy way.
|
||||
*
|
||||
* @return string that needs to be free'd
|
||||
*/
|
||||
char *xdtoa(long double d) {
|
||||
char *xdtoa(double d) {
|
||||
char *p = xmalloc(32);
|
||||
g_xfmt_p(p, &d, 16, 32, 2);
|
||||
g_dfmt_p(p, &d, DBL_DIG, 32, 2);
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
|
@ -27,6 +28,6 @@
|
|||
*/
|
||||
char *xdtoaf(float d) {
|
||||
char *p = xmalloc(32);
|
||||
g_ffmt_p(p, &d, 7, 32, 2);
|
||||
g_ffmt_p(p, &d, FLT_DIG, 32, 2);
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
|
@ -16,29 +16,18 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
.source __FILE__
|
||||
#include "libc/math.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/gdtoa/gdtoa.h"
|
||||
|
||||
fld1: fld1
|
||||
ret
|
||||
.endfn fld1,globl
|
||||
|
||||
fldl2t: fldl2t
|
||||
ret
|
||||
.endfn fldl2t,globl
|
||||
|
||||
fldlg2: fldlg2
|
||||
ret
|
||||
.endfn fldlg2,globl
|
||||
|
||||
fldl2e: fldl2e
|
||||
ret
|
||||
.endfn fldl2e,globl
|
||||
|
||||
fldln2: fldln2
|
||||
ret
|
||||
.endfn fldln2,globl
|
||||
|
||||
fldpi: fldpi
|
||||
ret
|
||||
.endfn fldpi,globl
|
||||
/**
|
||||
* Converts double to string the easy way.
|
||||
*
|
||||
* @return string that needs to be free'd
|
||||
*/
|
||||
char *xdtoal(long double d) {
|
||||
char *p = xmalloc(32);
|
||||
g_xfmt_p(p, &d, 16, 32, 2);
|
||||
return p;
|
||||
}
|
|
@ -19,12 +19,17 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "third_party/xed/x86.h"
|
||||
|
||||
struct sigaction oldsa;
|
||||
|
||||
volatile bool gotsigint;
|
||||
|
||||
|
@ -34,12 +39,11 @@ void OnSigInt(int sig) {
|
|||
|
||||
void SetUp(void) {
|
||||
gotsigint = false;
|
||||
/* TODO(jart): Windows needs huge signal overhaul */
|
||||
if (IsWindows()) exit(0);
|
||||
}
|
||||
|
||||
TEST(sigaction, test) {
|
||||
/* TODO(jart): Why does RHEL5 behave differently? */
|
||||
/* TODO(jart): Windows needs huge signal overhaul */
|
||||
if (IsWindows()) return;
|
||||
int pid, status;
|
||||
sigset_t block, ignore, oldmask;
|
||||
struct sigaction saint = {.sa_handler = OnSigInt};
|
||||
|
@ -48,7 +52,7 @@ TEST(sigaction, test) {
|
|||
EXPECT_NE(-1, sigprocmask(SIG_BLOCK, &block, &oldmask));
|
||||
sigfillset(&ignore);
|
||||
sigdelset(&ignore, SIGINT);
|
||||
EXPECT_NE(-1, sigaction(SIGINT, &saint, NULL));
|
||||
EXPECT_NE(-1, sigaction(SIGINT, &saint, &oldsa));
|
||||
ASSERT_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
EXPECT_NE(-1, kill(getppid(), SIGINT));
|
||||
|
@ -64,13 +68,45 @@ TEST(sigaction, test) {
|
|||
EXPECT_EQ(0, WEXITSTATUS(status));
|
||||
EXPECT_EQ(0, WTERMSIG(status));
|
||||
EXPECT_NE(-1, sigprocmask(SIG_SETMASK, &oldmask, NULL));
|
||||
EXPECT_NE(-1, sigaction(SIGINT, &oldsa, NULL));
|
||||
}
|
||||
|
||||
TEST(sigaction, raise) {
|
||||
if (IsWindows()) return;
|
||||
struct sigaction saint = {.sa_handler = OnSigInt};
|
||||
EXPECT_NE(-1, sigaction(SIGINT, &saint, NULL));
|
||||
EXPECT_NE(-1, sigaction(SIGINT, &saint, &oldsa));
|
||||
ASSERT_FALSE(gotsigint);
|
||||
EXPECT_NE(-1, raise(SIGINT));
|
||||
ASSERT_TRUE(gotsigint);
|
||||
EXPECT_NE(-1, sigaction(SIGINT, &oldsa, NULL));
|
||||
}
|
||||
|
||||
volatile int trapeax;
|
||||
|
||||
void OnTrap(int sig, struct siginfo *si, struct ucontext *ctx) {
|
||||
trapeax = ctx->uc_mcontext.rax;
|
||||
}
|
||||
|
||||
TEST(sigaction, debugBreak_handlerCanReadCpuState) {
|
||||
struct sigaction saint = {.sa_sigaction = OnTrap, .sa_flags = SA_SIGINFO};
|
||||
EXPECT_NE(-1, sigaction(SIGTRAP, &saint, &oldsa));
|
||||
asm("int3" : /* no outputs */ : "a"(0x31337));
|
||||
EXPECT_EQ(0x31337, trapeax);
|
||||
EXPECT_NE(-1, sigaction(SIGTRAP, &oldsa, NULL));
|
||||
}
|
||||
|
||||
void OnFpe(int sig, struct siginfo *si, struct ucontext *ctx) {
|
||||
struct XedDecodedInst xedd;
|
||||
xed_decoded_inst_zero_set_mode(&xedd, XED_MACHINE_MODE_LONG_64);
|
||||
xed_instruction_length_decode(&xedd, (void *)ctx->uc_mcontext.rip, 15);
|
||||
ctx->uc_mcontext.rip += xedd.length;
|
||||
ctx->uc_mcontext.rax = 42;
|
||||
ctx->uc_mcontext.rdx = 0;
|
||||
}
|
||||
|
||||
TEST(sigaction, sigFpe_handlerCanEditProcessStateAndRecoverExecution) {
|
||||
struct sigaction saint = {.sa_sigaction = OnFpe, .sa_flags = SA_SIGINFO};
|
||||
EXPECT_NE(-1, sigaction(SIGFPE, &saint, &oldsa));
|
||||
volatile long x = 0;
|
||||
EXPECT_EQ(42, 666 / x); /* systems engineering trumps math */
|
||||
EXPECT_NE(-1, sigaction(SIGFPE, &oldsa, NULL));
|
||||
}
|
||||
|
|
|
@ -38,7 +38,8 @@ TEST_LIBC_CALLS_DIRECTDEPS = \
|
|||
LIBC_SYSV \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_UNICODE \
|
||||
LIBC_X
|
||||
LIBC_X \
|
||||
THIRD_PARTY_XED
|
||||
|
||||
TEST_LIBC_CALLS_DEPS := \
|
||||
$(call uniq,$(foreach x,$(TEST_LIBC_CALLS_DIRECTDEPS),$($(x))))
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ $MODE = dbg ]; then
|
||||
exit # TODO
|
||||
fi
|
||||
|
||||
# smoke test userspace binary emulation
|
||||
CMD="o/$MODE/tool/build/blinkenlights.com.dbg o/$MODE/examples/hello.com"
|
||||
if OUTPUT="$($CMD)"; then
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ $MODE = dbg ]; then
|
||||
exit # TODO
|
||||
fi
|
||||
|
||||
# smoke test booting on bare metal and printing data to serial uart
|
||||
CMD="o/$MODE/tool/build/blinkenlights.com.dbg -r o/$MODE/examples/hello.com"
|
||||
if OUTPUT="$($CMD)"; then
|
||||
|
|
|
@ -28,3 +28,28 @@ TEST(atan2l, test) {
|
|||
EXPECT_STREQ("-2.95", gc(xasprintf("%.2f", atan2(b, a))));
|
||||
EXPECT_STREQ("-2.95", gc(xasprintf("%.2Lf", atan2l(b, a))));
|
||||
}
|
||||
|
||||
TEST(atan2, testSpecialCases) {
|
||||
ASSERT_STREQ("NAN", gc(xdtoa(atan2(NAN, 0))));
|
||||
ASSERT_STREQ("NAN", gc(xdtoa(atan2(0, NAN))));
|
||||
ASSERT_STREQ("0", gc(xdtoa(atan2(+0., +0.))));
|
||||
ASSERT_STREQ("0", gc(xdtoa(atan2(+0., +1.))));
|
||||
ASSERT_STREQ("0", gc(xdtoa(atan2(+0., +2.))));
|
||||
ASSERT_STREQ("0", gc(xdtoa(atan2(1, INFINITY))));
|
||||
ASSERT_STREQ("3.141592653589793", gc(xdtoal(atan2(+0., -0.))));
|
||||
ASSERT_STREQ("3.141592653589793", gc(xdtoal(atan2(+0., -1.))));
|
||||
ASSERT_STREQ("3.141592653589793", gc(xdtoal(atan2(+0., -2.))));
|
||||
ASSERT_STREQ("-1.570796326794897", gc(xdtoal(atan2(-1., -0.))));
|
||||
ASSERT_STREQ("-1.570796326794897", gc(xdtoal(atan2(-1., +0.))));
|
||||
ASSERT_STREQ("-1.570796326794897", gc(xdtoal(atan2(-2., -0.))));
|
||||
ASSERT_STREQ("-1.570796326794897", gc(xdtoal(atan2(-2., +0.))));
|
||||
ASSERT_STREQ("1.570796326794897", gc(xdtoal(atan2(+1., -0.))));
|
||||
ASSERT_STREQ("1.570796326794897", gc(xdtoal(atan2(+1., +0.))));
|
||||
ASSERT_STREQ("1.570796326794897", gc(xdtoal(atan2(+2., -0.))));
|
||||
ASSERT_STREQ("1.570796326794897", gc(xdtoal(atan2(+2., +0.))));
|
||||
ASSERT_STREQ("1.570796326794897", gc(xdtoal(atan2(INFINITY, 1))));
|
||||
ASSERT_STREQ("1.570796326794897", gc(xdtoal(atan2(INFINITY, -1))));
|
||||
ASSERT_STREQ("3.141592653589793", gc(xdtoal(atan2(1, -INFINITY))));
|
||||
ASSERT_STREQ("2.356194490192345", gc(xdtoal(atan2(INFINITY, -INFINITY))));
|
||||
ASSERT_STREQ(".7853981633974483", gc(xdtoal(atan2(INFINITY, INFINITY))));
|
||||
}
|
||||
|
|
45
test/libc/tinymath/atanl_test.c
Normal file
45
test/libc/tinymath/atanl_test.c
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
void SetUp(void) {
|
||||
/* 8087 FPU Control Word
|
||||
IM: Invalid Operation ───────────────┐
|
||||
DM: Denormal Operand ───────────────┐│
|
||||
ZM: Zero Divide ───────────────────┐││
|
||||
OM: Overflow ─────────────────────┐│││
|
||||
UM: Underflow ───────────────────┐││││
|
||||
PM: Precision ──────────────────┐│││││
|
||||
PC: Precision Control ────────┐ ││││││
|
||||
{float,∅,double,long double} │ ││││││
|
||||
RC: Rounding Control ───────┐ │ ││││││
|
||||
{even, →-∞, →+∞, →0} │┌┤ ││││││
|
||||
┌┤││ ││││││
|
||||
d││││rr││││││*/
|
||||
int x87cw = 0b0000000000000000001101100001;
|
||||
asm volatile("fldcw\t%0" : /* no outputs */ : "m"(x87cw));
|
||||
}
|
||||
|
||||
TEST(atanl, testLongDouble) {
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(atanl(NAN))));
|
||||
EXPECT_STREQ(".7853981583974483", gc(xdtoal(atanl(.99999999))));
|
||||
}
|
73
test/libc/tinymath/copysign_test.c
Normal file
73
test/libc/tinymath/copysign_test.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
TEST(copysign, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoa(copysign(0, +0))));
|
||||
EXPECT_STREQ("-0", gc(xdtoa(copysign(0, -0.))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(copysign(0, +1))));
|
||||
EXPECT_STREQ("-0", gc(xdtoa(copysign(-0., -1))));
|
||||
EXPECT_STREQ("2", gc(xdtoa(copysign(2, +1))));
|
||||
EXPECT_STREQ("-2", gc(xdtoa(copysign(-2, -1))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(copysign(NAN, +1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(copysign(NAN, -1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(copysign(INFINITY, +1))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoa(copysign(INFINITY, -1))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(copysign(-NAN, +1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(copysign(-NAN, -1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(copysign(-INFINITY, +1))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoa(copysign(-INFINITY, -1))));
|
||||
}
|
||||
|
||||
TEST(copysignl, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoal(copysignl(0, +0))));
|
||||
EXPECT_STREQ("-0", gc(xdtoal(copysignl(0, -0.))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(copysignl(0, +1))));
|
||||
EXPECT_STREQ("-0", gc(xdtoal(copysignl(-0., -1))));
|
||||
EXPECT_STREQ("2", gc(xdtoal(copysignl(2, +1))));
|
||||
EXPECT_STREQ("-2", gc(xdtoal(copysignl(-2, -1))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(copysignl(NAN, +1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(copysignl(NAN, -1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(copysignl(INFINITY, +1))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoal(copysignl(INFINITY, -1))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(copysignl(-NAN, +1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(copysignl(-NAN, -1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(copysignl(-INFINITY, +1))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoal(copysignl(-INFINITY, -1))));
|
||||
}
|
||||
|
||||
TEST(copysignf, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoaf(copysignf(0, +0))));
|
||||
EXPECT_STREQ("-0", gc(xdtoaf(copysignf(0, -0.))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(copysignf(0, +1))));
|
||||
EXPECT_STREQ("-0", gc(xdtoaf(copysignf(-0., -1))));
|
||||
EXPECT_STREQ("2", gc(xdtoaf(copysignf(2, +1))));
|
||||
EXPECT_STREQ("-2", gc(xdtoaf(copysignf(-2, -1))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(copysignf(NAN, +1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(copysignf(NAN, -1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(copysignf(INFINITY, +1))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoaf(copysignf(INFINITY, -1))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(copysignf(-NAN, +1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(copysignf(-NAN, -1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(copysignf(-INFINITY, +1))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoaf(copysignf(-INFINITY, -1))));
|
||||
}
|
56
test/libc/tinymath/exp10_test.c
Normal file
56
test/libc/tinymath/exp10_test.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define exp10l(x) exp10l(VEIL("t", (long double)(x)))
|
||||
#define exp10(x) exp10(VEIL("x", (double)(x)))
|
||||
#define exp10f(x) exp10f(VEIL("x", (float)(x)))
|
||||
|
||||
TEST(exp10l, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoal(exp10l(0))));
|
||||
EXPECT_STREQ("1", gc(xdtoal(exp10l(-0.))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(exp10l(INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(exp10l(-INFINITY))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(exp10l(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(exp10l(-132098844872390))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(exp10l(132098844872390))));
|
||||
}
|
||||
|
||||
TEST(exp10, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoa(exp10(0))));
|
||||
EXPECT_STREQ("1", gc(xdtoa(exp10(-0.))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(exp10(INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(exp10(-INFINITY))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(exp10(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(exp10(-132098844872390))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(exp10(132098844872390))));
|
||||
}
|
||||
|
||||
TEST(exp10f, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoaf(exp10f(0))));
|
||||
EXPECT_STREQ("1", gc(xdtoaf(exp10f(-0.))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(exp10f(INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(exp10f(-INFINITY))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(exp10f(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(exp10f(-132098844872390))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(exp10f(132098844872390))));
|
||||
}
|
56
test/libc/tinymath/exp2_test.c
Normal file
56
test/libc/tinymath/exp2_test.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define exp2l(x) exp2l(VEIL("t", (long double)(x)))
|
||||
#define exp2(x) exp2(VEIL("x", (double)(x)))
|
||||
#define exp2f(x) exp2f(VEIL("x", (float)(x)))
|
||||
|
||||
TEST(exp2l, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoal(exp2l(0))));
|
||||
EXPECT_STREQ("1", gc(xdtoal(exp2l(-0.))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(exp2l(INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(exp2l(-INFINITY))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(exp2l(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(exp2l(-132098844872390))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(exp2l(132098844872390))));
|
||||
}
|
||||
|
||||
TEST(exp2, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoa(exp2(0))));
|
||||
EXPECT_STREQ("1", gc(xdtoa(exp2(-0.))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(exp2(INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(exp2(-INFINITY))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(exp2(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(exp2(-132098844872390))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(exp2(132098844872390))));
|
||||
}
|
||||
|
||||
TEST(exp2f, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoaf(exp2f(0))));
|
||||
EXPECT_STREQ("1", gc(xdtoaf(exp2f(-0.))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(exp2f(INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(exp2f(-INFINITY))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(exp2f(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(exp2f(-132098844872390))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(exp2f(132098844872390))));
|
||||
}
|
|
@ -22,7 +22,41 @@
|
|||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define expl(x) expl(VEIL("t", (long double)(x)))
|
||||
#define exp(x) exp(VEIL("x", (double)(x)))
|
||||
#define expf(x) expf(VEIL("x", (float)(x)))
|
||||
|
||||
TEST(expl, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoal(expl(0))));
|
||||
EXPECT_STREQ("1", gc(xdtoal(expl(-0.))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(expl(INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(expl(-INFINITY))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(expl(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(expl(-132098844872390))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(expl(132098844872390))));
|
||||
}
|
||||
|
||||
TEST(exp, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoa(exp(0))));
|
||||
EXPECT_STREQ("1", gc(xdtoa(exp(-0.))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(exp(INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(exp(-INFINITY))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(exp(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(exp(-132098844872390))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(exp(132098844872390))));
|
||||
}
|
||||
|
||||
TEST(expf, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoaf(expf(0))));
|
||||
EXPECT_STREQ("1", gc(xdtoaf(expf(-0.))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(expf(INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(expf(-INFINITY))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(expf(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(expf(-132098844872390))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(expf(132098844872390))));
|
||||
}
|
||||
|
||||
TEST(exp, fun) {
|
||||
ASSERT_STREQ("7.389056", gc(xasprintf("%f", exp(2.0))));
|
||||
ASSERT_STREQ("6.389056", gc(xasprintf("%f", expm1(2.0))));
|
||||
ASSERT_STREQ("6.389056", gc(xasprintf("%f", exp(2.0) - 1.0)));
|
||||
|
|
58
test/libc/tinymath/expm1_test.c
Normal file
58
test/libc/tinymath/expm1_test.c
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define expm1l(x) expm1l(VEIL("t", (long double)(x)))
|
||||
#define expm1(x) expm1(VEIL("x", (double)(x)))
|
||||
#define expm1f(x) expm1f(VEIL("x", (float)(x)))
|
||||
|
||||
TEST(expm1l, test) {
|
||||
EXPECT_STREQ("1.718281828459045", gc(xdtoal(expm1l(1))));
|
||||
EXPECT_STREQ("1.718281828459045", gc(xdtoal(expl(1) - 1)));
|
||||
EXPECT_STREQ("0", gc(xdtoal(expm1l(0))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(expm1l(-0.))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(expm1l(NAN))));
|
||||
EXPECT_STREQ("-1", gc(xdtoal(expm1l(-INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(expm1l(INFINITY))));
|
||||
/* EXPECT_STREQ("-INFINITY", gc(xdtoal(expm1l(-132098844872390)))); */
|
||||
/* EXPECT_STREQ("INFINITY", gc(xdtoal(expm1l(132098844872390)))); */
|
||||
}
|
||||
|
||||
TEST(expm1, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoa(expm1(0))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(expm1(-0.))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(expm1(NAN))));
|
||||
EXPECT_STREQ("-1", gc(xdtoa(expm1(-INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(INFINITY))));
|
||||
/* EXPECT_STREQ("-INFINITY", gc(xdtoa(expm1(-132098844872390)))); */
|
||||
/* EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(132098844872390)))); */
|
||||
}
|
||||
|
||||
TEST(expm1f, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoaf(expm1f(0))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(expm1f(-0.))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(expm1f(NAN))));
|
||||
EXPECT_STREQ("-1", gc(xdtoaf(expm1f(-INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(expm1f(INFINITY))));
|
||||
/* EXPECT_STREQ("-INFINITY", gc(xdtoaf(expm1f(-132098844872390)))); */
|
||||
/* EXPECT_STREQ("INFINITY", gc(xdtoaf(expm1f(132098844872390)))); */
|
||||
}
|
|
@ -17,9 +17,39 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define fabsl(x) fabsl(VEIL("t", (long double)(x)))
|
||||
#define fabs(x) fabs(VEIL("x", (double)(x)))
|
||||
#define fabsf(x) fabsf(VEIL("x", (float)(x)))
|
||||
|
||||
TEST(fabsl, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoal(fabsl(-0.))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(fabsl(-0.))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(fabsl(NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(fabsl(INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(fabsl(-INFINITY))));
|
||||
}
|
||||
|
||||
TEST(fabs, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoa(fabs(-0.))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(fabs(-0.))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(fabs(NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(fabs(INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(fabs(-INFINITY))));
|
||||
}
|
||||
|
||||
TEST(fabsf, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoaf(fabsf(-0.))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(fabsf(-0.))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(fabsf(NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(fabsf(INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(fabsf(-INFINITY))));
|
||||
}
|
||||
|
||||
TEST(fabs, stuff) {
|
||||
EXPECT_LDBL_EQ(3.14, fabs(3.14));
|
||||
EXPECT_LDBL_EQ(3.14, fabs(-3.14));
|
||||
EXPECT_EQ(1, !!isnan(fabs(NAN)));
|
||||
|
|
73
test/libc/tinymath/fmod_test.c
Normal file
73
test/libc/tinymath/fmod_test.c
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
int rando;
|
||||
|
||||
void SetUp(void) {
|
||||
rando = rand() & 0xffff;
|
||||
}
|
||||
|
||||
TEST(fmodl, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoal(fmodl(0, rando))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(fmodl(1, NAN))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(fmodl(NAN, 1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(fmodl(INFINITY, 1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(fmodl(1, 0))));
|
||||
EXPECT_STREQ("8", gc(xdtoal(fmodl(8, 32))));
|
||||
EXPECT_STREQ("8e+100", gc(xdtoal(fmodl(8e100, 32e100))));
|
||||
EXPECT_STREQ("5.319372648326541e+255",
|
||||
gc(xdtoal(ldexpl(6381956970095103, 797))));
|
||||
EXPECT_STREQ(".09287409360354737",
|
||||
gc(xdtoal(fmodl(ldexpl(6381956970095103, 797), M_2_PI))));
|
||||
}
|
||||
|
||||
TEST(fmod, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoa(fmod(0, rando))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(fmod(1, NAN))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(fmod(NAN, 1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(fmod(INFINITY, 1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(fmod(1, 0))));
|
||||
EXPECT_STREQ("8", gc(xdtoa(fmod(8, 32))));
|
||||
EXPECT_STREQ("8e+100", gc(xdtoa(fmod(8e100, 32e100))));
|
||||
EXPECT_STREQ("5.31937264832654e+255",
|
||||
gc(xdtoa(ldexp(6381956970095103, 797))));
|
||||
EXPECT_STREQ(".0928740936035474",
|
||||
gc(xdtoa(fmod(ldexp(6381956970095103, 797), M_2_PI))));
|
||||
}
|
||||
|
||||
TEST(fmodf, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoaf(fmodf(0, rando))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(fmodf(1, NAN))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(fmodf(NAN, 1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(fmodf(INFINITY, 1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(fmodf(1, 0))));
|
||||
EXPECT_STREQ("8", gc(xdtoaf(fmodf(8, 32))));
|
||||
EXPECT_STREQ("8e+20", gc(xdtoaf(fmodf(8e20, 32e20))));
|
||||
}
|
||||
|
||||
BENCH(fmod, bench) {
|
||||
EZBENCH2("fmod eze", donothing, fmodl(8, 32));
|
||||
EZBENCH2("fmod big", donothing, fmodl(5.319372648326541e+255, M_2_PI));
|
||||
}
|
|
@ -21,6 +21,11 @@
|
|||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define hypotl(x, y) \
|
||||
hypotl(VEIL("t", (long double)(x)), VEIL("t", (long double)(y)))
|
||||
#define hypot(x, y) hypot(VEIL("x", (double)(x)), VEIL("x", (double)(y)))
|
||||
#define hypotf(x, y) hypotf(VEIL("x", (float)(x)), VEIL("x", (float)(y)))
|
||||
|
||||
TEST(hypot, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoa(hypot(0, 0))));
|
||||
EXPECT_STREQ("3", gc(xdtoa(hypot(3, 0))));
|
||||
|
@ -33,12 +38,12 @@ TEST(hypot, test) {
|
|||
EXPECT_STREQ("5", gc(xdtoa(hypot(4, -3))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypot(-3, -4))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypot(-4, -3))));
|
||||
EXPECT_STREQ("1.414213562373095", gc(xdtoa(hypot(1, 1))));
|
||||
EXPECT_STREQ("1.414213562373095", gc(xdtoa(hypot(1, -1))));
|
||||
EXPECT_STREQ("1.414213562373095", gc(xdtoa(hypot(-1, 1))));
|
||||
EXPECT_STREQ("1.414213626012708", gc(xdtoa(hypot(1.0000001, .99999999))));
|
||||
EXPECT_STREQ("1.414213626012708", gc(xdtoa(hypot(.99999999, 1.0000001))));
|
||||
EXPECT_STREQ("1.414213562373095e+154", gc(xdtoa(hypot(1e154, 1e154))));
|
||||
EXPECT_STREQ("1.4142135623731", gc(xdtoa(hypot(1, 1))));
|
||||
EXPECT_STREQ("1.4142135623731", gc(xdtoa(hypot(1, -1))));
|
||||
EXPECT_STREQ("1.4142135623731", gc(xdtoa(hypot(-1, 1))));
|
||||
EXPECT_STREQ("1.41421362601271", gc(xdtoa(hypot(1.0000001, .99999999))));
|
||||
EXPECT_STREQ("1.41421362601271", gc(xdtoa(hypot(.99999999, 1.0000001))));
|
||||
EXPECT_STREQ("1.4142135623731e+154", gc(xdtoa(hypot(1e154, 1e154))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(hypot(0, NAN))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(hypot(NAN, 0))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(hypot(NAN, NAN))));
|
||||
|
@ -61,12 +66,12 @@ TEST(hypotf, test) {
|
|||
EXPECT_STREQ("5", gc(xdtoa(hypotf(4, -3))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotf(-3, -4))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotf(-4, -3))));
|
||||
EXPECT_STREQ("1.414214", gc(xdtoaf(hypotf(1, 1))));
|
||||
EXPECT_STREQ("1.414214", gc(xdtoaf(hypotf(1, -1))));
|
||||
EXPECT_STREQ("1.414214", gc(xdtoaf(hypotf(-1, 1))));
|
||||
EXPECT_STREQ("1.414214", gc(xdtoaf(hypotf(1.000001, 0.999999))));
|
||||
EXPECT_STREQ("1.414214", gc(xdtoaf(hypotf(0.999999, 1.000001))));
|
||||
EXPECT_STREQ("1.414214e+38", gc(xdtoaf(hypotf(1e38, 1e38))));
|
||||
EXPECT_STREQ("1.41421", gc(xdtoaf(hypotf(1, 1))));
|
||||
EXPECT_STREQ("1.41421", gc(xdtoaf(hypotf(1, -1))));
|
||||
EXPECT_STREQ("1.41421", gc(xdtoaf(hypotf(-1, 1))));
|
||||
EXPECT_STREQ("1.41421", gc(xdtoaf(hypotf(1.000001, 0.999999))));
|
||||
EXPECT_STREQ("1.41421", gc(xdtoaf(hypotf(0.999999, 1.000001))));
|
||||
EXPECT_STREQ("1.41421e+38", gc(xdtoaf(hypotf(1e38, 1e38))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(hypotf(0, NAN))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(hypotf(NAN, 0))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(hypotf(NAN, NAN))));
|
||||
|
@ -78,31 +83,31 @@ TEST(hypotf, test) {
|
|||
}
|
||||
|
||||
TEST(hypotll, test) {
|
||||
EXPECT_STREQ("0", gc(xdtoa(hypotl(0, 0))));
|
||||
EXPECT_STREQ("3", gc(xdtoa(hypotl(3, 0))));
|
||||
EXPECT_STREQ("3", gc(xdtoa(hypotl(0, 3))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotl(3, 4))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotl(4, 3))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotl(3, -4))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotl(-4, 3))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotl(-3, 4))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotl(4, -3))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotl(-3, -4))));
|
||||
EXPECT_STREQ("5", gc(xdtoa(hypotl(-4, -3))));
|
||||
EXPECT_STREQ("1.414213562373095", gc(xdtoa(hypotl(1, 1))));
|
||||
EXPECT_STREQ("1.414213562373095", gc(xdtoa(hypotl(1, -1))));
|
||||
EXPECT_STREQ("1.414213562373095", gc(xdtoa(hypotl(-1, 1))));
|
||||
EXPECT_STREQ("1.414213626012708", gc(xdtoa(hypotl(1.0000001, .99999999))));
|
||||
EXPECT_STREQ("1.414213626012708", gc(xdtoa(hypotl(.99999999, 1.0000001))));
|
||||
EXPECT_STREQ("1.414213562373095e+4931", gc(xdtoa(hypotl(1e4931L, 1e4931L))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(hypotl(0, NAN))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(hypotl(NAN, 0))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(hypotl(NAN, NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(hypotl(INFINITY, 0))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(hypotl(0, INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(hypotl(INFINITY, NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(hypotl(NAN, INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(hypotl(INFINITY, INFINITY))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(hypotl(0, 0))));
|
||||
EXPECT_STREQ("3", gc(xdtoal(hypotl(3, 0))));
|
||||
EXPECT_STREQ("3", gc(xdtoal(hypotl(0, 3))));
|
||||
EXPECT_STREQ("5", gc(xdtoal(hypotl(3, 4))));
|
||||
EXPECT_STREQ("5", gc(xdtoal(hypotl(4, 3))));
|
||||
EXPECT_STREQ("5", gc(xdtoal(hypotl(3, -4))));
|
||||
EXPECT_STREQ("5", gc(xdtoal(hypotl(-4, 3))));
|
||||
EXPECT_STREQ("5", gc(xdtoal(hypotl(-3, 4))));
|
||||
EXPECT_STREQ("5", gc(xdtoal(hypotl(4, -3))));
|
||||
EXPECT_STREQ("5", gc(xdtoal(hypotl(-3, -4))));
|
||||
EXPECT_STREQ("5", gc(xdtoal(hypotl(-4, -3))));
|
||||
EXPECT_STREQ("1.414213562373095", gc(xdtoal(hypotl(1, 1))));
|
||||
EXPECT_STREQ("1.414213562373095", gc(xdtoal(hypotl(1, -1))));
|
||||
EXPECT_STREQ("1.414213562373095", gc(xdtoal(hypotl(-1, 1))));
|
||||
EXPECT_STREQ("1.414213626012708", gc(xdtoal(hypotl(1.0000001, .99999999))));
|
||||
EXPECT_STREQ("1.414213626012708", gc(xdtoal(hypotl(.99999999, 1.0000001))));
|
||||
EXPECT_STREQ("1.414213562373095e+4931", gc(xdtoal(hypotl(1e4931L, 1e4931L))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(hypotl(0, NAN))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(hypotl(NAN, 0))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(hypotl(NAN, NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(hypotl(INFINITY, 0))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(hypotl(0, INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(hypotl(INFINITY, NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(hypotl(NAN, INFINITY))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(hypotl(INFINITY, INFINITY))));
|
||||
}
|
||||
|
||||
BENCH(hypot, bench) {
|
||||
|
|
|
@ -17,12 +17,83 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/rand/rand.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
int rando;
|
||||
|
||||
void SetUp(void) {
|
||||
rando = rand() & 0xffff;
|
||||
}
|
||||
|
||||
TEST(ldexpl, test) {
|
||||
EXPECT_EQ(rando, ldexpl(rando, 0));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(ldexpl(NAN, 0))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(ldexpl(-NAN, 0))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(ldexpl(INFINITY, 0))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoal(ldexpl(-INFINITY, 0))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(ldexpl(NAN, 1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(ldexpl(-NAN, 1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(ldexpl(INFINITY, 1))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoal(ldexpl(-INFINITY, 1))));
|
||||
EXPECT_STREQ("16384", gc(xdtoal(log2l(LDBL_MAX))));
|
||||
EXPECT_STREQ(".00390625", gc(xdtoal(ldexpl(1, -8))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(ldexpl(0, -8))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(ldexpl(0, 8))));
|
||||
EXPECT_STREQ("256", gc(xdtoal(ldexpl(1, 8))));
|
||||
EXPECT_STREQ("512", gc(xdtoal(ldexpl(2, 8))));
|
||||
EXPECT_STREQ("768", gc(xdtoal(ldexpl(3, 8))));
|
||||
EXPECT_STREQ("6.997616471358197e+3461", gc(xdtoal(ldexpl(1, 11500))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(ldexpl(1, 999999))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(ldexpl(1, -999999))));
|
||||
}
|
||||
|
||||
TEST(ldexp, test) {
|
||||
EXPECT_EQ(rando, ldexp(rando, 0));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(ldexp(NAN, 0))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(ldexp(-NAN, 0))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(ldexp(INFINITY, 0))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoa(ldexp(-INFINITY, 0))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(ldexp(NAN, 1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(ldexp(-NAN, 1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(ldexp(INFINITY, 1))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoa(ldexp(-INFINITY, 1))));
|
||||
EXPECT_STREQ("16384", gc(xdtoa(log2l(LDBL_MAX))));
|
||||
EXPECT_STREQ(".00390625", gc(xdtoa(ldexp(1, -8))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(ldexp(0, -8))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(ldexp(0, 8))));
|
||||
EXPECT_STREQ("256", gc(xdtoa(ldexp(1, 8))));
|
||||
EXPECT_STREQ("512", gc(xdtoa(ldexp(2, 8))));
|
||||
EXPECT_STREQ("768", gc(xdtoa(ldexp(3, 8))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(ldexp(1, 999999))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(ldexp(1, -999999))));
|
||||
}
|
||||
|
||||
TEST(ldexpf, test) {
|
||||
EXPECT_EQ(rando, ldexpf(rando, 0));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(ldexpf(NAN, 0))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(ldexpf(-NAN, 0))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(ldexpf(INFINITY, 0))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoaf(ldexpf(-INFINITY, 0))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(ldexpf(NAN, 1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(ldexpf(-NAN, 1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(ldexpf(INFINITY, 1))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoaf(ldexpf(-INFINITY, 1))));
|
||||
EXPECT_STREQ("16384", gc(xdtoaf(log2l(LDBL_MAX))));
|
||||
EXPECT_STREQ(".00390625", gc(xdtoaf(ldexpf(1, -8))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(ldexpf(0, -8))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(ldexpf(0, 8))));
|
||||
EXPECT_STREQ("256", gc(xdtoaf(ldexpf(1, 8))));
|
||||
EXPECT_STREQ("512", gc(xdtoaf(ldexpf(2, 8))));
|
||||
EXPECT_STREQ("768", gc(xdtoaf(ldexpf(3, 8))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(ldexpf(1, 999999))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(ldexpf(1, -999999))));
|
||||
}
|
||||
|
||||
TEST(ldexp, stuff) {
|
||||
volatile int twopow = 5;
|
||||
volatile double pi = 3.14;
|
||||
ASSERT_STREQ("100.48", gc(xasprintf("%.2f", ldexp(pi, twopow))));
|
||||
|
|
47
test/libc/tinymath/log1p_test.c
Normal file
47
test/libc/tinymath/log1p_test.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
TEST(log1pl, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoal(log1pl(1.71828182845904523536L))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(log1pl(NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(log1pl(INFINITY))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoal(log1pl(-1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(log1pl(-2))));
|
||||
}
|
||||
|
||||
TEST(log1p, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoa(log1p(M_E - 1))));
|
||||
EXPECT_STREQ("2", gc(xdtoa(log1p(M_E * M_E - 1))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(log1p(NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(log1p(INFINITY))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoa(log1p(-1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(log1p(-2))));
|
||||
}
|
||||
|
||||
TEST(log1pf, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoaf(log1pf(M_E - 1))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(log1pf(NAN))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(log1pf(INFINITY))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoaf(log1pf(-1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(log1pf(-2))));
|
||||
}
|
56
test/libc/tinymath/log2_test.c
Normal file
56
test/libc/tinymath/log2_test.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
TEST(log2l, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoal(log2l(2))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(log2l(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(log2l(1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(log2l(INFINITY))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoal(log2l(0))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoal(log2l(-0.))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(log2l(-1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(log2l(-2))));
|
||||
}
|
||||
|
||||
TEST(log2, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoa(log2(2))));
|
||||
EXPECT_STREQ("2", gc(xdtoa(log2(2 * 2))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(log2(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(log2(1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(log2(INFINITY))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoa(log2(0))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoa(log2(-0.))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(log2(-1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(log2(-2))));
|
||||
}
|
||||
|
||||
TEST(log2f, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoaf(log2f(2))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(log2f(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(log2f(1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(log2f(INFINITY))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoaf(log2f(0))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoaf(log2f(-0.))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(log2f(-1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(log2f(-2))));
|
||||
}
|
56
test/libc/tinymath/log_test.c
Normal file
56
test/libc/tinymath/log_test.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
TEST(logl, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoal(logl(2.71828182845904523536L))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoal(logl(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(logl(1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(logl(INFINITY))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoal(logl(0))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoal(logl(-0.))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(logl(-1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoal(logl(-2))));
|
||||
}
|
||||
|
||||
TEST(log, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoa(log(M_E))));
|
||||
EXPECT_STREQ("2", gc(xdtoa(log(M_E * M_E))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoa(log(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoa(log(1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(log(INFINITY))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoa(log(0))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoa(log(-0.))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(log(-1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoa(log(-2))));
|
||||
}
|
||||
|
||||
TEST(logf, test) {
|
||||
EXPECT_STREQ("1", gc(xdtoaf(logf(M_E))));
|
||||
EXPECT_STREQ("NAN", gc(xdtoaf(logf(NAN))));
|
||||
EXPECT_STREQ("0", gc(xdtoaf(logf(1))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoaf(logf(INFINITY))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoaf(logf(0))));
|
||||
EXPECT_STREQ("-INFINITY", gc(xdtoaf(logf(-0.))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(logf(-1))));
|
||||
EXPECT_STREQ("-NAN", gc(xdtoaf(logf(-2))));
|
||||
}
|
|
@ -16,39 +16,47 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
double powa(double x, double y) {
|
||||
return exp2(fmod(y * log2(x), 1)) * exp2(y);
|
||||
}
|
||||
|
||||
TEST(powl, testLongDouble) {
|
||||
EXPECT_TRUE(isnan(powl(-1, 1.1)));
|
||||
EXPECT_STREQ("1e+4932", gc(xdtoal(powl(10, 4932))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoal(powl(10, 4933))));
|
||||
EXPECT_STREQ("0", gc(xdtoal(powl(10, -5000))));
|
||||
EXPECT_STREQ("1.063382396627933e+37", gc(xdtoal(powl(2, 123))));
|
||||
/* .4248496805467504836322459796959084815827285786480897 */
|
||||
EXPECT_STARTSWITH(".4248496805467504", gc(xdtoa(powl(0.7, 2.4))));
|
||||
EXPECT_STARTSWITH(".4248496805467504", gc(xdtoal(powl(0.7, 2.4))));
|
||||
}
|
||||
|
||||
TEST(powl, testDouble) {
|
||||
EXPECT_STARTSWITH(".4248496805467504", gc(xdtoa(pow(0.7, 2.4))));
|
||||
EXPECT_STREQ("1e+308", gc(xdtoa(pow(10, 308))));
|
||||
EXPECT_STREQ("INFINITY", gc(xdtoa(pow(10, 309))));
|
||||
EXPECT_STARTSWITH(".42484968054675", gc(xdtoa(pow(0.7, 2.4))));
|
||||
}
|
||||
|
||||
TEST(powl, testFloat) {
|
||||
EXPECT_STARTSWITH(".4248496", gc(xdtoa(powf(0.7f, 2.4f))));
|
||||
}
|
||||
|
||||
static long double do_powl(void) {
|
||||
return CONCEAL("t", powl(CONCEAL("t", 0.7), CONCEAL("t", 0.2)));
|
||||
}
|
||||
|
||||
static double do_pow(void) {
|
||||
return CONCEAL("x", pow(CONCEAL("x", 0.7), CONCEAL("x", 0.2)));
|
||||
}
|
||||
|
||||
static float do_powf(void) {
|
||||
return CONCEAL("x", powf(CONCEAL("x", 0.7f), CONCEAL("x", 0.2f)));
|
||||
}
|
||||
|
||||
BENCH(powl, bench) {
|
||||
EZBENCH2("powl", donothing, do_powl()); /* ~61ns */
|
||||
EZBENCH2("pow", donothing, do_pow()); /* ~64ns */
|
||||
EZBENCH2("powf", donothing, do_powf()); /* ~64ns */
|
||||
double _pow(double, double) asm("pow");
|
||||
float _powf(float, float) asm("powf");
|
||||
long double _powl(long double, long double) asm("powl");
|
||||
EZBENCH2("pow", donothing, _pow(.7, .2)); /* ~51ns */
|
||||
EZBENCH2("powf", donothing, _powf(.7, .2)); /* ~52ns */
|
||||
EZBENCH2("powl", donothing, _powl(.7, .2)); /* ~53ns */
|
||||
}
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define roundl(x) roundl(VEIL("t", (long double)(x)))
|
||||
#define round(x) round(VEIL("x", (double)(x)))
|
||||
#define roundf(x) roundf(VEIL("x", (float)(x)))
|
||||
|
||||
FIXTURE(intrin, disableHardwareExtensions) {
|
||||
memset((/*unconst*/ void *)kCpuids, 0, sizeof(kCpuids));
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue