diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index a74abdbd..eec2e7ed 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.26) -project(libc CXX) +project(libc CXX ASM) set(LIBC_SOURCES ctype.cpp @@ -10,6 +10,7 @@ set(LIBC_SOURCES stdlib.cpp string.cpp unistd.cpp + math.S ) add_custom_target(libc-headers diff --git a/libc/include/math.h b/libc/include/math.h new file mode 100644 index 00000000..672291ef --- /dev/null +++ b/libc/include/math.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +__BEGIN_DECLS + +long double floorl(long double); + +__END_DECLS diff --git a/libc/math.S b/libc/math.S new file mode 100644 index 00000000..6ef1b16d --- /dev/null +++ b/libc/math.S @@ -0,0 +1,26 @@ + +.global floorl; +floorl: + fldt 8(%rsp) + + fnstenv -28(%rsp) /* store fpu environment */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x400,%edx /* round towards -oo */ + orl -28(%rsp),%edx + andl $0xf7ff,%edx + movl %edx,-32(%rsp) + fldcw -32(%rsp) /* load modified control word */ + + frndint /* round */ + + /* Preserve "invalid" exceptions from sNaN input. */ + fnstsw + andl $0x1, %eax + orl %eax, -24(%rsp) + + fldenv -28(%rsp) /* restore original environment */ + + ret \ No newline at end of file