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:
Justine Tunney 2021-02-25 18:30:17 -08:00
parent cdc54ea1fd
commit 40291c9db3
109 changed files with 2316 additions and 520 deletions

View file

@ -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

View file

@ -95,7 +95,7 @@ CONFIG_COPTS += \
$(SANITIZER)
TARGET_ARCH ?= \
-march=native
-msse3
OVERRIDE_CCFLAGS += \
-fno-pie

View file

@ -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)

View 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;
}

View file

@ -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_

View file

@ -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);

View file

@ -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));

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View 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
View 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;
}

View file

@ -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);
}

View file

@ -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
View 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();
}
}

View file

@ -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");

View file

@ -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);
}
}

View file

@ -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(&copy, act, sizeof(copy));
ap = &copy;
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 {

View 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.
*/
}

View 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.
*/
}

View 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.
*/
}

View file

@ -49,7 +49,7 @@ struct siginfo {
};
char __ignoreme[128 - 2 * sizeof(int32_t) - sizeof(int64_t)];
};
} forcealign(8);
};
typedef struct siginfo siginfo_t;

View file

@ -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 */

View file

@ -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);
}
}

View file

@ -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
View 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
View 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();
}
}

View file

@ -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) {

View file

@ -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);
}
}

View file

@ -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)

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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}
drr*/
int x87cw = 0b0000000000000000001101111111;
asm volatile("fldcw\t%0" : /* no outputs */ : "m"(x87cw));
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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_ */

View file

@ -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.

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns arc cosine of 𝑥.
//

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns 𝑒^x.
//

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns 10^x.
//

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns absolute value of 𝑥.
//

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// fmod [sic] does (𝑥 rem 𝑦) w/ round()-style rounding.
//

View file

@ -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

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns 𝑥 × 2ʸ.
//

View file

@ -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ʸ.
//

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns natural logarithm of 𝑥.
//

View file

@ -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

View file

@ -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

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Calculates log𝑥.
//

View file

@ -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

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns natural logarithm of 𝑥.
//

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns 𝑥^𝑦.
//

View file

@ -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

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns sine of 𝑥.
//

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns square root of 𝑥.
//

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.h"
.source __FILE__
// Returns square root of 𝑥.
//

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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))))

View file

@ -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

View file

@ -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

View file

@ -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))));
}

View 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}
drr*/
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))));
}

View 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))));
}

View 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))));
}

View 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))));
}

View file

@ -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)));

View 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)))); */
}

View file

@ -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)));

View 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));
}

View file

@ -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) {

View file

@ -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))));

View 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))));
}

View 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))));
}

View 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))));
}

View file

@ -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 */
}

View file

@ -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