summaryrefslogtreecommitdiffstats
path: root/src/recompiler/Sun
diff options
context:
space:
mode:
Diffstat (limited to 'src/recompiler/Sun')
-rw-r--r--src/recompiler/Sun/Makefile.kup0
-rw-r--r--src/recompiler/Sun/config-host.h46
-rw-r--r--src/recompiler/Sun/config.h44
-rw-r--r--src/recompiler/Sun/crt/stdio.h73
-rw-r--r--src/recompiler/Sun/deftoimp.sed37
-rw-r--r--src/recompiler/Sun/e_powl-amd64.S371
-rw-r--r--src/recompiler/Sun/e_powl-x86.S413
-rw-r--r--src/recompiler/Sun/kvm.h28
-rw-r--r--src/recompiler/Sun/testmath.c828
9 files changed, 1840 insertions, 0 deletions
diff --git a/src/recompiler/Sun/Makefile.kup b/src/recompiler/Sun/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/recompiler/Sun/Makefile.kup
diff --git a/src/recompiler/Sun/config-host.h b/src/recompiler/Sun/config-host.h
new file mode 100644
index 00000000..a18a147e
--- /dev/null
+++ b/src/recompiler/Sun/config-host.h
@@ -0,0 +1,46 @@
+/* $Id: config-host.h $ */
+/** @file
+ * Sun host config - maintained by hand
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+#if defined(RT_ARCH_AMD64)
+# define HOST_X86_64 1
+# define HOST_LONG_BITS 64
+#else
+# define HOST_I386 1
+# define HOST_LONG_BITS 32
+#endif
+
+#ifndef IPRT_NO_CRT
+# ifdef RT_OS_WINDOWS
+# define CONFIG_WIN32 1
+# elif defined(RT_OS_OS2)
+# define CONFIG_OS2
+# elif defined(RT_OS_DARWIN)
+# define CONFIG_DARWIN
+# elif defined(RT_OS_FREEBSD) || defined(RT_OS_NETBSD) || defined(RT_OS_OPENBSD)
+# define HAVE_MACHINE_BSWAP_H
+/*# define CONFIG_BSD*/
+# elif defined(RT_OS_SOLARIS)
+# define CONFIG_SOLARIS
+# else
+# define HAVE_BYTESWAP_H 1
+# endif
+#endif
+#define QEMU_VERSION "0.13.0"
+#define CONFIG_UNAME_RELEASE ""
+#define CONFIG_QEMU_SHAREDIR "."
+
diff --git a/src/recompiler/Sun/config.h b/src/recompiler/Sun/config.h
new file mode 100644
index 00000000..173b660d
--- /dev/null
+++ b/src/recompiler/Sun/config.h
@@ -0,0 +1,44 @@
+/* $Id: config.h $ */
+/** @file
+ * Sun config - Maintained by hand
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "config-host.h"
+#define CONFIG_QEMU_PREFIX "/usr/gnemul/qemu-i386"
+#define TARGET_ARCH "i386"
+#define TARGET_I386 1
+#define CONFIG_SOFTMMU 1
+#define TARGET_PHYS_ADDR_BITS 64
+
+#ifdef VBOX_WITH_64_BITS_GUESTS
+# if defined(__x86_64__) || defined (VBOX_ENABLE_VBOXREM64)
+# define TARGET_X86_64
+# endif
+#endif
+
+/* Uncomment to see all phys memory accesses */
+/* #define VBOX_DEBUG_PHYS */
+/* Uncomment to see emulated CPU state changes */
+/* #define VBOX_DUMP_STATE */
+/* Uncomment to see QEMU logging, goes to /tmp/vbox-qemu.log */
+/* #define DEBUG_ALL_LOGGING */
+/* Uncomment to see generated code */
+/* #define DEBUG_DISAS */
+
+#if 0 /*defined(RT_ARCH_AMD64) && defined(VBOX_STRICT)*/
+# define VBOX_CHECK_ADDR(ptr) do { if ((uintptr_t)(ptr) >= _4G) __asm__("int3"); } while (0)
+#else
+# define VBOX_CHECK_ADDR(ptr) do { } while (0)
+#endif
diff --git a/src/recompiler/Sun/crt/stdio.h b/src/recompiler/Sun/crt/stdio.h
new file mode 100644
index 00000000..5c73fb1a
--- /dev/null
+++ b/src/recompiler/Sun/crt/stdio.h
@@ -0,0 +1,73 @@
+/* $Id: stdio.h $ */
+/** @file
+ * Our minimal stdio
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___Sun_stdio_h
+#define ___Sun_stdio_h
+
+#ifndef LOG_GROUP
+# define UNDO_LOG_GROUP
+#endif
+
+#include <VBox/log.h>
+
+#ifdef UNDO_LOG_GROUP
+# undef UNDO_LOG_GROUP
+# undef LOG_GROUP
+#endif
+
+#ifndef LOG_USE_C99
+# error "LOG_USE_C99 isn't defined."
+#endif
+
+RT_C_DECLS_BEGIN
+
+typedef struct FILE FILE;
+
+#if defined(RT_OS_SOLARIS)
+/** @todo Check solaris' floatingpoint.h as to why we do this */
+# define _FILEDEFED
+#endif
+
+DECLINLINE(int) fprintf(FILE *ignored, const char *pszFormat, ...)
+{
+/** @todo We don't support wrapping calls taking a va_list yet. It's not worth it yet,
+ * since there are only a couple of cases where this fprintf implementation is used.
+ * (The macro below will deal with the majority of the fprintf calls.) */
+#if 0 /*def LOG_ENABLED*/
+ if (LogIsItEnabled(NULL, 0, LOG_GROUP_REM_PRINTF))
+ {
+ va_list va;
+ va_start(va, pszFormat);
+ RTLogLoggerExV(NULL, 0, LOG_GROUP_REM_PRINTF, pszFormat, va);
+ va_end(va);
+ }
+#endif
+ return 0;
+}
+
+#define fflush(file) RTLogFlush(NULL)
+#define printf(...) LogIt(0, LOG_GROUP_REM_PRINTF, (__VA_ARGS__))
+#define fprintf(logfile, ...) LogIt(0, LOG_GROUP_REM_PRINTF, (__VA_ARGS__))
+
+#ifdef DEBUG_TMP_LOGGING
+# error "DEBUG_TMP_LOGGING doesn't work with the Sun/crt/stdio.h wrapper."
+#endif
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/src/recompiler/Sun/deftoimp.sed b/src/recompiler/Sun/deftoimp.sed
new file mode 100644
index 00000000..3e35efa1
--- /dev/null
+++ b/src/recompiler/Sun/deftoimp.sed
@@ -0,0 +1,37 @@
+# $Id: deftoimp.sed $
+## @file
+# SED script for generating a dummy .so from a windows .def file.
+#
+
+#
+# Copyright (C) 2006-2019 Oracle Corporation
+#
+# This file is part of VirtualBox Open Source Edition (OSE), as
+# available from http://www.virtualbox.org. This file is free software;
+# you can redistribute it and/or modify it under the terms of the GNU
+# General Public License (GPL) as published by the Free Software
+# Foundation, in version 2 as it comes in the "COPYING" file of the
+# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+#
+
+s/;.*$//g
+s/^[[:space:]][[:space:]]*//g
+s/[[:space:]][[:space:]]*$//g
+/^$/d
+
+# Handle text after EXPORTS
+/EXPORTS/,//{
+s/^EXPORTS$//
+/^$/b end
+
+s/^\(.*\)$/EXPORT\nvoid \1(void);\nvoid \1(void){}/
+b end
+}
+d
+b end
+
+
+# next expression
+:end
+
diff --git a/src/recompiler/Sun/e_powl-amd64.S b/src/recompiler/Sun/e_powl-amd64.S
new file mode 100644
index 00000000..5e0353e7
--- /dev/null
+++ b/src/recompiler/Sun/e_powl-amd64.S
@@ -0,0 +1,371 @@
+/* ix87 specific implementation of pow function.
+ Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004 Free Software Foundation
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+/*#include <machine/asm.h>*/
+#include <iprt/cdefs.h>
+
+#define ALIGNARG(log2) 1<<log2
+#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
+#define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
+#define ASM_GLOBAL_DIRECTIVE .global
+
+#define C_LABEL(name) name:
+#define C_SYMBOL_NAME(name) name
+
+#define ENTRY(name) \
+ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
+ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \
+ .align ALIGNARG(4); \
+ C_LABEL(name)
+
+#undef END
+#define END(name) \
+ ASM_SIZE_DIRECTIVE(name)
+
+
+#ifdef __ELF__
+ .section .rodata
+#else
+ .text
+#endif
+
+ .align ALIGNARG(4)
+ ASM_TYPE_DIRECTIVE(infinity,@object)
+inf_zero:
+infinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
+ ASM_SIZE_DIRECTIVE(infinity)
+ ASM_TYPE_DIRECTIVE(zero,@object)
+zero: .double 0.0
+ ASM_SIZE_DIRECTIVE(zero)
+ ASM_TYPE_DIRECTIVE(minf_mzero,@object)
+minf_mzero:
+minfinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff
+mzero:
+ .byte 0, 0, 0, 0, 0, 0, 0, 0x80
+ ASM_SIZE_DIRECTIVE(minf_mzero)
+ ASM_TYPE_DIRECTIVE(one,@object)
+one: .double 1.0
+ ASM_SIZE_DIRECTIVE(one)
+ ASM_TYPE_DIRECTIVE(limit,@object)
+limit: .double 0.29
+ ASM_SIZE_DIRECTIVE(limit)
+ ASM_TYPE_DIRECTIVE(p63,@object)
+p63:
+ .byte 0, 0, 0, 0, 0, 0, 0xe0, 0x43
+ ASM_SIZE_DIRECTIVE(p63)
+
+//#ifdef PIC
+//#define MO(op) op##(%rip)
+//#else
+#define MO(op) op
+//#endif
+
+ .text
+/*ENTRY(__ieee754_powl)*/
+ENTRY(RT_NOCRT(powl))
+
+ fldt 24(%rsp) // y
+ fxam
+
+
+ fnstsw
+ movb %ah, %dl
+ andb $0x45, %ah
+ cmpb $0x40, %ah // is y == 0 ?
+ je 11f
+
+ cmpb $0x05, %ah // is y == ±inf ?
+ je 12f
+
+ cmpb $0x01, %ah // is y == NaN ?
+ je 30f
+
+ fldt 8(%rsp) // x : y
+
+ fxam
+ fnstsw
+ movb %ah, %dh
+ andb $0x45, %ah
+ cmpb $0x40, %ah
+ je 20f // x is ±0
+
+ cmpb $0x05, %ah
+ je 15f // x is ±inf
+
+ fxch // y : x
+
+ /* fistpll raises invalid exception for |y| >= 1L<<63. */
+ fldl MO(p63) // 1L<<63 : y : x
+ fld %st(1) // y : 1L<<63 : y : x
+ fabs // |y| : 1L<<63 : y : x
+ fcomip %st(1), %st // 1L<<63 : y : x
+ fstp %st(0) // y : x
+ jnc 2f
+
+ /* First see whether `y' is a natural number. In this case we
+ can use a more precise algorithm. */
+ fld %st // y : y : x
+ fistpll -8(%rsp) // y : x
+ fildll -8(%rsp) // int(y) : y : x
+ fucomip %st(1),%st // y : x
+ jne 2f
+
+ /* OK, we have an integer value for y. */
+ mov -8(%rsp),%eax
+ mov -4(%rsp),%edx
+ orl $0, %edx
+ fstp %st(0) // x
+ jns 4f // y >= 0, jump
+ fdivrl MO(one) // 1/x (now referred to as x)
+ negl %eax
+ adcl $0, %edx
+ negl %edx
+4: fldl MO(one) // 1 : x
+ fxch
+
+6: shrdl $1, %edx, %eax
+ jnc 5f
+ fxch
+ fmul %st(1) // x : ST*x
+ fxch
+5: fmul %st(0), %st // x*x : ST*x
+ shrl $1, %edx
+ movl %eax, %ecx
+ orl %edx, %ecx
+ jnz 6b
+ fstp %st(0) // ST*x
+ ret
+
+ /* y is ±NAN */
+30: fldt 8(%rsp) // x : y
+ fldl MO(one) // 1.0 : x : y
+ fucomip %st(1),%st // x : y
+ je 31f
+ fxch // y : x
+31: fstp %st(1)
+ ret
+
+ .align ALIGNARG(4)
+2: /* y is a real number. */
+ fxch // x : y
+ fldl MO(one) // 1.0 : x : y
+ fld %st(1) // x : 1.0 : x : y
+ fsub %st(1) // x-1 : 1.0 : x : y
+ fabs // |x-1| : 1.0 : x : y
+ fcompl MO(limit) // 1.0 : x : y
+ fnstsw
+ fxch // x : 1.0 : y
+ test $4500,%eax
+ jz 7f
+ fsub %st(1) // x-1 : 1.0 : y
+ fyl2xp1 // log2(x) : y
+ jmp 8f
+
+7: fyl2x // log2(x) : y
+8: fmul %st(1) // y*log2(x) : y
+ fxam
+ fnstsw
+ andb $0x45, %ah
+ cmpb $0x05, %ah // is y*log2(x) == ±inf ?
+ je 28f
+ fst %st(1) // y*log2(x) : y*log2(x)
+ frndint // int(y*log2(x)) : y*log2(x)
+ fsubr %st, %st(1) // int(y*log2(x)) : fract(y*log2(x))
+ fxch // fract(y*log2(x)) : int(y*log2(x))
+ f2xm1 // 2^fract(y*log2(x))-1 : int(y*log2(x))
+ faddl MO(one) // 2^fract(y*log2(x)) : int(y*log2(x))
+ fscale // 2^fract(y*log2(x))*2^int(y*log2(x)) : int(y*log2(x))
+ fstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x))
+ ret
+
+28: fstp %st(1) // y*log2(x)
+ fldl MO(one) // 1 : y*log2(x)
+ fscale // 2^(y*log2(x)) : y*log2(x)
+ fstp %st(1) // 2^(y*log2(x))
+ ret
+
+ // pow(x,±0) = 1
+ .align ALIGNARG(4)
+11: fstp %st(0) // pop y
+ fldl MO(one)
+ ret
+
+ // y == ±inf
+ .align ALIGNARG(4)
+12: fstp %st(0) // pop y
+ fldt 8(%rsp) // x
+ fabs
+ fcompl MO(one) // < 1, == 1, or > 1
+ fnstsw
+ andb $0x45, %ah
+ cmpb $0x45, %ah
+ je 13f // jump if x is NaN
+
+ cmpb $0x40, %ah
+ je 14f // jump if |x| == 1
+
+ shlb $1, %ah
+ xorb %ah, %dl
+ andl $2, %edx
+#ifdef PIC
+ lea inf_zero(%rip),%rcx
+ fldl (%rcx, %rdx, 4)
+#else
+ fldl inf_zero(,%rdx, 4)
+#endif
+ ret
+
+ .align ALIGNARG(4)
+14: fldl MO(one)
+ ret
+
+ .align ALIGNARG(4)
+13: fldt 8(%rsp) // load x == NaN
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±inf
+15: fstp %st(0) // y
+ testb $2, %dh
+ jz 16f // jump if x == +inf
+
+ // We must find out whether y is an odd integer.
+ fld %st // y : y
+ fistpll -8(%rsp) // y
+ fildll -8(%rsp) // int(y) : y
+ fucomip %st(1),%st
+ ffreep %st // <empty>
+ jne 17f
+
+ // OK, the value is an integer, but is it odd?
+ mov -8(%rsp), %eax
+ mov -4(%rsp), %edx
+ andb $1, %al
+ jz 18f // jump if not odd
+ // It's an odd integer.
+ shrl $31, %edx
+#ifdef PIC
+ lea minf_mzero(%rip),%rcx
+ fldl (%rcx, %rdx, 8)
+#else
+ fldl minf_mzero(,%rdx, 8)
+#endif
+ ret
+
+ .align ALIGNARG(4)
+16: fcompl MO(zero)
+ fnstsw
+ shrl $5, %eax
+ andl $8, %eax
+#ifdef PIC
+ lea inf_zero(%rip),%rcx
+ fldl (%rcx, %rax, 1)
+#else
+ fldl inf_zero(,%rax, 1)
+#endif
+ ret
+
+ .align ALIGNARG(4)
+17: shll $30, %edx // sign bit for y in right position
+18: shrl $31, %edx
+#ifdef PIC
+ lea inf_zero(%rip),%rcx
+ fldl (%rcx, %rdx, 8)
+#else
+ fldl inf_zero(,%rdx, 8)
+#endif
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±0
+20: fstp %st(0) // y
+ testb $2, %dl
+ jz 21f // y > 0
+
+ // x is ±0 and y is < 0. We must find out whether y is an odd integer.
+ testb $2, %dh
+ jz 25f
+
+ fld %st // y : y
+ fistpll -8(%rsp) // y
+ fildll -8(%rsp) // int(y) : y
+ fucomip %st(1),%st
+ ffreep %st // <empty>
+ jne 26f
+
+ // OK, the value is an integer, but is it odd?
+ mov -8(%rsp),%eax
+ mov -4(%rsp),%edx
+ andb $1, %al
+ jz 27f // jump if not odd
+ // It's an odd integer.
+ // Raise divide-by-zero exception and get minus infinity value.
+ fldl MO(one)
+ fdivl MO(zero)
+ fchs
+ ret
+
+25: fstp %st(0)
+26:
+27: // Raise divide-by-zero exception and get infinity value.
+ fldl MO(one)
+ fdivl MO(zero)
+ ret
+
+ .align ALIGNARG(4)
+ // x is ±0 and y is > 0. We must find out whether y is an odd integer.
+21: testb $2, %dh
+ jz 22f
+
+ fld %st // y : y
+ fistpll -8(%rsp) // y
+ fildll -8(%rsp) // int(y) : y
+ fucomip %st(1),%st
+ ffreep %st // <empty>
+ jne 23f
+
+ // OK, the value is an integer, but is it odd?
+ mov -8(%rsp),%eax
+ mov -4(%rsp),%edx
+ andb $1, %al
+ jz 24f // jump if not odd
+ // It's an odd integer.
+ fldl MO(mzero)
+ ret
+
+22: fstp %st(0)
+23:
+24: fldl MO(zero)
+ ret
+
+/*END(__ieee754_powl)*/
+END(RT_NOCRT(powl))
+
diff --git a/src/recompiler/Sun/e_powl-x86.S b/src/recompiler/Sun/e_powl-x86.S
new file mode 100644
index 00000000..cbc99256
--- /dev/null
+++ b/src/recompiler/Sun/e_powl-x86.S
@@ -0,0 +1,413 @@
+/* ix87 specific implementation of pow function.
+ Copyright (C) 1996, 1997, 1998, 1999, 2001, 2004, 2005
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+/*
+ * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
+ * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
+ * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
+ * a choice of LGPL license versions is made available with the language indicating
+ * that LGPLv2 or any later version may be used, or where a choice of which version
+ * of the LGPL is applied is otherwise unspecified.
+ */
+
+/*#include <machine/asm.h>*/
+#include <iprt/cdefs.h>
+
+#ifdef __MINGW32__
+# define ASM_TYPE_DIRECTIVE(name,typearg)
+# define ASM_SIZE_DIRECTIVE(name)
+# define cfi_adjust_cfa_offset(a)
+# define C_LABEL(name) _ ## name:
+# define C_SYMBOL_NAME(name) _ ## name
+# define ASM_GLOBAL_DIRECTIVE .global
+# define ALIGNARG(log2) 1<<log2
+#elif __APPLE__
+# define ASM_TYPE_DIRECTIVE(name,typearg)
+# define ASM_SIZE_DIRECTIVE(name)
+# define cfi_adjust_cfa_offset(a)
+# define C_LABEL(name) _ ## name:
+# define C_SYMBOL_NAME(name) _ ## name
+# define ASM_GLOBAL_DIRECTIVE .globl
+# define ALIGNARG(log2) log2
+#else
+# define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg;
+# define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
+# define C_LABEL(name) name:
+# define C_SYMBOL_NAME(name) name
+# /* figure this one out. */
+# define cfi_adjust_cfa_offset(a)
+# define ASM_GLOBAL_DIRECTIVE .global
+# define ALIGNARG(log2) 1<<log2
+#endif
+
+#define ENTRY(name) \
+ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \
+ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \
+ .align ALIGNARG(4); \
+ C_LABEL(name)
+
+#undef END
+#define END(name) \
+ ASM_SIZE_DIRECTIVE(name)
+
+#ifdef __ELF__
+ .section .rodata
+#else
+ .text
+#endif
+
+ .align ALIGNARG(4)
+ ASM_TYPE_DIRECTIVE(infinity,@object)
+inf_zero:
+infinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x7f
+ ASM_SIZE_DIRECTIVE(infinity)
+ ASM_TYPE_DIRECTIVE(zero,@object)
+zero: .double 0.0
+ ASM_SIZE_DIRECTIVE(zero)
+ ASM_TYPE_DIRECTIVE(minf_mzero,@object)
+minf_mzero:
+minfinity:
+ .byte 0, 0, 0, 0, 0, 0, 0xf0, 0xff
+mzero:
+ .byte 0, 0, 0, 0, 0, 0, 0, 0x80
+ ASM_SIZE_DIRECTIVE(minf_mzero)
+ ASM_TYPE_DIRECTIVE(one,@object)
+one: .double 1.0
+ ASM_SIZE_DIRECTIVE(one)
+ ASM_TYPE_DIRECTIVE(limit,@object)
+limit: .double 0.29
+ ASM_SIZE_DIRECTIVE(limit)
+ ASM_TYPE_DIRECTIVE(p63,@object)
+p63: .byte 0, 0, 0, 0, 0, 0, 0xe0, 0x43
+ ASM_SIZE_DIRECTIVE(p63)
+
+#ifdef PIC
+#define MO(op) op##@GOTOFF(%ecx)
+#define MOX(op,x,f) op##@GOTOFF(%ecx,x,f)
+#else
+#define MO(op) op
+#define MOX(op,x,f) op(,x,f)
+#endif
+
+ .text
+//ENTRY(__ieee754_powl)
+ENTRY(RT_NOCRT(powl))
+#ifdef RT_OS_DARWIN /* 16-byte long double with 8 byte alignment requirements */
+ fldt 20(%esp) // y
+#else
+ fldt 16(%esp) // y
+#endif
+ fxam
+
+#ifdef PIC
+ LOAD_PIC_REG (cx)
+#endif
+
+ fnstsw
+ movb %ah, %dl
+ andb $0x45, %ah
+ cmpb $0x40, %ah // is y == 0 ?
+ je .L11
+
+ cmpb $0x05, %ah // is y == ±inf ?
+ je .L12
+
+ cmpb $0x01, %ah // is y == NaN ?
+ je .L30
+
+ fldt 4(%esp) // x : y
+
+ subl $8,%esp
+ cfi_adjust_cfa_offset (8)
+
+ fxam
+ fnstsw
+ movb %ah, %dh
+ andb $0x45, %ah
+ cmpb $0x40, %ah
+ je .L20 // x is ±0
+
+ cmpb $0x05, %ah
+ je .L15 // x is ±inf
+
+ fxch // y : x
+
+ /* fistpll raises invalid exception for |y| >= 1L<<63. */
+ fld %st // y : y : x
+ fabs // |y| : y : x
+ fcompl MO(p63) // y : x
+ fnstsw
+ sahf
+ jnc .L2
+
+ /* First see whether `y' is a natural number. In this case we
+ can use a more precise algorithm. */
+ fld %st // y : y : x
+ fistpll (%esp) // y : x
+ fildll (%esp) // int(y) : y : x
+ fucomp %st(1) // y : x
+ fnstsw
+ sahf
+ jne .L2
+
+ /* OK, we have an integer value for y. */
+ popl %eax
+ cfi_adjust_cfa_offset (-4)
+ popl %edx
+ cfi_adjust_cfa_offset (-4)
+ orl $0, %edx
+ fstp %st(0) // x
+ jns .L4 // y >= 0, jump
+ fdivrl MO(one) // 1/x (now referred to as x)
+ negl %eax
+ adcl $0, %edx
+ negl %edx
+.L4: fldl MO(one) // 1 : x
+ fxch
+
+.L6: shrdl $1, %edx, %eax
+ jnc .L5
+ fxch
+ fmul %st(1) // x : ST*x
+ fxch
+.L5: fmul %st(0), %st // x*x : ST*x
+ shrl $1, %edx
+ movl %eax, %ecx
+ orl %edx, %ecx
+ jnz .L6
+ fstp %st(0) // ST*x
+ ret
+
+ /* y is ±NAN */
+.L30: fldt 4(%esp) // x : y
+ fldl MO(one) // 1.0 : x : y
+ fucomp %st(1) // x : y
+ fnstsw
+ sahf
+ je .L31
+ fxch // y : x
+.L31: fstp %st(1)
+ ret
+
+ cfi_adjust_cfa_offset (8)
+ .align ALIGNARG(4)
+.L2: /* y is a real number. */
+ fxch // x : y
+ fldl MO(one) // 1.0 : x : y
+ fld %st(1) // x : 1.0 : x : y
+ fsub %st(1) // x-1 : 1.0 : x : y
+ fabs // |x-1| : 1.0 : x : y
+ fcompl MO(limit) // 1.0 : x : y
+ fnstsw
+ fxch // x : 1.0 : y
+ sahf
+ ja .L7
+ fsub %st(1) // x-1 : 1.0 : y
+ fyl2xp1 // log2(x) : y
+ jmp .L8
+
+.L7: fyl2x // log2(x) : y
+.L8: fmul %st(1) // y*log2(x) : y
+ fxam
+ fnstsw
+ andb $0x45, %ah
+ cmpb $0x05, %ah // is y*log2(x) == ±inf ?
+ je .L28
+ fst %st(1) // y*log2(x) : y*log2(x)
+ frndint // int(y*log2(x)) : y*log2(x)
+ fsubr %st, %st(1) // int(y*log2(x)) : fract(y*log2(x))
+ fxch // fract(y*log2(x)) : int(y*log2(x))
+ f2xm1 // 2^fract(y*log2(x))-1 : int(y*log2(x))
+ faddl MO(one) // 2^fract(y*log2(x)) : int(y*log2(x))
+ fscale // 2^fract(y*log2(x))*2^int(y*log2(x)) : int(y*log2(x))
+ addl $8, %esp
+ cfi_adjust_cfa_offset (-8)
+ fstp %st(1) // 2^fract(y*log2(x))*2^int(y*log2(x))
+ ret
+
+ cfi_adjust_cfa_offset (8)
+.L28: fstp %st(1) // y*log2(x)
+ fldl MO(one) // 1 : y*log2(x)
+ fscale // 2^(y*log2(x)) : y*log2(x)
+ addl $8, %esp
+ cfi_adjust_cfa_offset (-8)
+ fstp %st(1) // 2^(y*log2(x))
+ ret
+
+ // pow(x,±0) = 1
+ .align ALIGNARG(4)
+.L11: fstp %st(0) // pop y
+ fldl MO(one)
+ ret
+
+ // y == ±inf
+ .align ALIGNARG(4)
+.L12: fstp %st(0) // pop y
+ fldt 4(%esp) // x
+ fabs
+ fcompl MO(one) // < 1, == 1, or > 1
+ fnstsw
+ andb $0x45, %ah
+ cmpb $0x45, %ah
+ je .L13 // jump if x is NaN
+
+ cmpb $0x40, %ah
+ je .L14 // jump if |x| == 1
+
+ shlb $1, %ah
+ xorb %ah, %dl
+ andl $2, %edx
+ fldl MOX(inf_zero, %edx, 4)
+ ret
+
+ .align ALIGNARG(4)
+.L14: fldl MO(one)
+ ret
+
+ .align ALIGNARG(4)
+.L13: fldt 4(%esp) // load x == NaN
+ ret
+
+ cfi_adjust_cfa_offset (8)
+ .align ALIGNARG(4)
+ // x is ±inf
+.L15: fstp %st(0) // y
+ testb $2, %dh
+ jz .L16 // jump if x == +inf
+
+ // We must find out whether y is an odd integer.
+ fld %st // y : y
+ fistpll (%esp) // y
+ fildll (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ sahf
+ jne .L17
+
+ // OK, the value is an integer, but is it odd?
+ popl %eax
+ cfi_adjust_cfa_offset (-4)
+ popl %edx
+ cfi_adjust_cfa_offset (-4)
+ andb $1, %al
+ jz .L18 // jump if not odd
+ // It's an odd integer.
+ shrl $31, %edx
+ fldl MOX(minf_mzero, %edx, 8)
+ ret
+
+ cfi_adjust_cfa_offset (8)
+ .align ALIGNARG(4)
+.L16: fcompl MO(zero)
+ addl $8, %esp
+ cfi_adjust_cfa_offset (-8)
+ fnstsw
+ shrl $5, %eax
+ andl $8, %eax
+ fldl MOX(inf_zero, %eax, 1)
+ ret
+
+ cfi_adjust_cfa_offset (8)
+ .align ALIGNARG(4)
+.L17: shll $30, %edx // sign bit for y in right position
+ addl $8, %esp
+ cfi_adjust_cfa_offset (-8)
+.L18: shrl $31, %edx
+ fldl MOX(inf_zero, %edx, 8)
+ ret
+
+ cfi_adjust_cfa_offset (8)
+ .align ALIGNARG(4)
+ // x is ±0
+.L20: fstp %st(0) // y
+ testb $2, %dl
+ jz .L21 // y > 0
+
+ // x is ±0 and y is < 0. We must find out whether y is an odd integer.
+ testb $2, %dh
+ jz .L25
+
+ fld %st // y : y
+ fistpll (%esp) // y
+ fildll (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ sahf
+ jne .L26
+
+ // OK, the value is an integer, but is it odd?
+ popl %eax
+ cfi_adjust_cfa_offset (-4)
+ popl %edx
+ cfi_adjust_cfa_offset (-4)
+ andb $1, %al
+ jz .L27 // jump if not odd
+ // It's an odd integer.
+ // Raise divide-by-zero exception and get minus infinity value.
+ fldl MO(one)
+ fdivl MO(zero)
+ fchs
+ ret
+
+ cfi_adjust_cfa_offset (8)
+.L25: fstp %st(0)
+.L26: addl $8, %esp
+ cfi_adjust_cfa_offset (-8)
+.L27: // Raise divide-by-zero exception and get infinity value.
+ fldl MO(one)
+ fdivl MO(zero)
+ ret
+
+ cfi_adjust_cfa_offset (8)
+ .align ALIGNARG(4)
+ // x is ±0 and y is > 0. We must find out whether y is an odd integer.
+.L21: testb $2, %dh
+ jz .L22
+
+ fld %st // y : y
+ fistpll (%esp) // y
+ fildll (%esp) // int(y) : y
+ fucompp // <empty>
+ fnstsw
+ sahf
+ jne .L23
+
+ // OK, the value is an integer, but is it odd?
+ popl %eax
+ cfi_adjust_cfa_offset (-4)
+ popl %edx
+ cfi_adjust_cfa_offset (-4)
+ andb $1, %al
+ jz .L24 // jump if not odd
+ // It's an odd integer.
+ fldl MO(mzero)
+ ret
+
+ cfi_adjust_cfa_offset (8)
+.L22: fstp %st(0)
+.L23: addl $8, %esp // Don't use 2 x pop
+ cfi_adjust_cfa_offset (-8)
+.L24: fldl MO(zero)
+ ret
+
+END(RT_NOCRT(powl))
+//END(__ieee754_powl)
diff --git a/src/recompiler/Sun/kvm.h b/src/recompiler/Sun/kvm.h
new file mode 100644
index 00000000..0403e3e4
--- /dev/null
+++ b/src/recompiler/Sun/kvm.h
@@ -0,0 +1,28 @@
+/* $Id: kvm.h $ */
+/** @file
+ * VBox Recompiler - kvm stub header.
+ */
+
+/*
+ * Copyright (C) 2011-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___kvm_stub_h___
+#define ___kvm_stub_h___
+
+#define kvm_enabled() false
+#define kvm_update_guest_debug(a, b) AssertFailed()
+#define kvm_set_phys_mem(a, b, c) AssertFailed()
+#define kvm_arch_get_registers(a) AssertFailed()
+#define cpu_synchronize_state(a) do { } while (0)
+
+#endif
+
diff --git a/src/recompiler/Sun/testmath.c b/src/recompiler/Sun/testmath.c
new file mode 100644
index 00000000..b1650753
--- /dev/null
+++ b/src/recompiler/Sun/testmath.c
@@ -0,0 +1,828 @@
+/* $Id: testmath.c $ */
+/** @file
+ * Testcase for the no-crt math stuff.
+ */
+
+/*
+ * Copyright (C) 2006-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#ifndef MATHTEST_STANDALONE
+# include <iprt/assert.h>
+# include <math.h>
+# undef printf
+# define printf RTAssertMsg2Weak
+#else
+# include <stdio.h>
+# include <math.h>
+#endif
+
+/* gcc starting with version 4.3 uses the MPFR library which results in more accurate results. gcc-4.3.1 seems to emit the less accurate result. So just allow both results. */
+#define SIN180a -0.8011526357338304777463731115L
+#define SIN180b -0.801152635733830477871L
+
+static void bitch(const char *pszWhat, const long double *plrdResult, const long double *plrdExpected)
+{
+ const unsigned char *pach1 = (const unsigned char *)plrdResult;
+ const unsigned char *pach2 = (const unsigned char *)plrdExpected;
+#ifndef MATHTEST_STANDALONE
+ printf("error: %s - %d instead of %d\n", pszWhat, (int)(*plrdResult * 100000), (int)(*plrdExpected * 100000));
+#else
+ printf("error: %s - %.25f instead of %.25f\n", pszWhat, (double)*plrdResult, (double)*plrdExpected);
+#endif
+ printf(" %02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x\n", pach1[0], pach1[1], pach1[2], pach1[3], pach1[4], pach1[5], pach1[6], pach1[7], pach1[8], pach1[9]);
+ printf(" %02x%02x%02x%02x-%02x%02x%02x%02x-%02x%02x\n", pach2[0], pach2[1], pach2[2], pach2[3], pach2[4], pach2[5], pach2[6], pach2[7], pach2[8], pach2[9]);
+}
+
+static void bitchll(const char *pszWhat, long long llResult, long long llExpected)
+{
+#if defined(__MINGW32__) && !defined(Assert)
+ printf("error: %s - %I64d instead of %I64d\n", pszWhat, llResult, llExpected);
+#else
+ printf("error: %s - %lld instead of %lld\n", pszWhat, llResult, llExpected);
+#endif
+}
+
+static void bitchl(const char *pszWhat, long lResult, long lExpected)
+{
+ printf("error: %s - %ld instead of %ld\n", pszWhat, lResult, lExpected);
+}
+
+extern int testsin(void)
+{
+ return sinl(180.0L) == SIN180a || sinl(180.0L) == SIN180b;
+}
+
+extern int testremainder(void)
+{
+ static double s_rd1 = 2.5;
+ static double s_rd2 = 2.0;
+ static double s_rd3 = 0.5;
+ return remainder(s_rd1, s_rd2) == s_rd3;
+}
+
+static __inline__ void set_cw(unsigned cw)
+{
+ __asm __volatile("fldcw %0" : : "m" (cw));
+}
+
+static __inline__ unsigned get_cw(void)
+{
+ unsigned cw;
+ __asm __volatile("fstcw %0" : "=m" (cw));
+ return cw & 0xffff;
+}
+
+static long double check_lrd(const long double lrd, const unsigned long long ull, const unsigned short us)
+{
+ static volatile long double lrd2;
+ lrd2 = lrd;
+ if ( *(unsigned long long *)&lrd2 != ull
+ || ((unsigned short *)&lrd2)[4] != us)
+ {
+#if defined(__MINGW32__) && !defined(Assert)
+ printf("%I64x:%04x instead of %I64x:%04x\n", *(unsigned long long *)&lrd2, ((unsigned short *)&lrd2)[4], ull, us);
+#else
+ printf("%llx:%04x instead of %llx:%04x\n", *(unsigned long long *)&lrd2, ((unsigned short *)&lrd2)[4], ull, us);
+#endif
+ __asm__("int $3\n");
+ }
+ return lrd;
+}
+
+
+static long double make_lrd(const unsigned long long ull, const unsigned short us)
+{
+ union
+ {
+ long double lrd;
+ struct
+ {
+ unsigned long long ull;
+ unsigned short us;
+ } i;
+ } u;
+
+ u.i.ull = ull;
+ u.i.us = us;
+ return u.lrd;
+}
+
+static long double check_lrd_cw(const long double lrd, const unsigned long long ull, const unsigned short us, const unsigned cw)
+{
+ set_cw(cw);
+ if (cw != get_cw())
+ {
+ printf("get_cw() -> %#x expected %#x\n", get_cw(), cw);
+ __asm__("int $3\n");
+ }
+ return check_lrd(lrd, ull, us);
+}
+
+static long double make_lrd_cw(unsigned long long ull, unsigned short us, unsigned cw)
+{
+ set_cw(cw);
+ return check_lrd_cw(make_lrd(ull, us), ull, us, cw);
+}
+
+extern int testmath(void)
+{
+ unsigned cErrors = 0;
+ long double lrdResult;
+ long double lrdExpect;
+ long double lrd;
+#define CHECK(operation, expect) \
+ do { \
+ lrdExpect = expect; \
+ lrdResult = operation; \
+ if (lrdResult != lrdExpect) \
+ { \
+ bitch(#operation, &lrdResult, &lrdExpect); \
+ cErrors++; \
+ } \
+ } while (0)
+
+ long long llResult;
+ long long llExpect;
+#define CHECKLL(operation, expect) \
+ do { \
+ llExpect = expect; \
+ llResult = operation; \
+ if (llResult != llExpect) \
+ { \
+ bitchll(#operation, llResult, llExpect); \
+ cErrors++; \
+ } \
+ } while (0)
+
+ long lResult;
+ long lExpect;
+#define CHECKL(operation, expect) \
+ do { \
+ lExpect = expect; \
+ lResult = operation; \
+ if (lResult != lExpect) \
+ { \
+ bitchl(#operation, lResult, lExpect); \
+ cErrors++; \
+ } \
+ } while (0)
+
+ CHECK(atan2l(1.0L, 1.0L), 0.785398163397448309603L);
+ CHECK(atan2l(2.3L, 3.3L), 0.608689307327411694890L);
+
+ CHECK(ceill(1.9L), 2.0L);
+ CHECK(ceill(4.5L), 5.0L);
+ CHECK(ceill(3.3L), 4.0L);
+ CHECK(ceill(6.1L), 7.0L);
+
+ CHECK(floorl(1.9L), 1.0L);
+ CHECK(floorl(4.5L), 4.0L);
+ CHECK(floorl(7.3L), 7.0L);
+ CHECK(floorl(1234.1L), 1234.0L);
+ CHECK(floor(1233.1), 1233.0);
+ CHECK(floor(1239.98989898), 1239.0);
+ CHECK(floorf(9999.999), 9999.0);
+
+ CHECK(ldexpl(1.0L, 1), 2.0L);
+ CHECK(ldexpl(1.0L, 10), 1024.0L);
+ CHECK(ldexpl(2.25L, 10), 2304.0L);
+
+ CHECKLL(llrintl(1.0L), 1);
+ CHECKLL(llrintl(1.3L), 1);
+ CHECKLL(llrintl(1.5L), 2);
+ CHECKLL(llrintl(1.9L), 2);
+ CHECKLL(llrintf(123.34), 123);
+ CHECKLL(llrintf(-123.50), -124);
+ CHECKLL(llrint(42.42), 42);
+ CHECKLL(llrint(-2147483648.12343), -2147483648LL);
+#if !defined(RT_ARCH_AMD64)
+ CHECKLL(lrint(-21474836499.12343), -2147483648LL);
+ CHECKLL(lrint(-2147483649932412.12343), -2147483648LL);
+#else
+ CHECKLL(lrint(-21474836499.12343), -21474836499L);
+ CHECKLL(lrint(-2147483649932412.12343), -2147483649932412L);
+#endif
+
+// __asm__("int $3");
+ CHECKL(lrintl(make_lrd_cw(000000000000000000ULL,000000,0x027f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x027f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x027f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x067f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x067f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x0a7f)), 1L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x0a7f)), 1L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x0e7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x3ffe,0x0e7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x027f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x027f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x067f)), -1L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x067f)), -1L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x0a7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x0a7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x0e7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0xbffe,0x0e7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x027f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x027f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x067f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x067f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x0a7f)), 1L);
+ CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x0a7f)), 1L);
+ CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x0e7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x9249249249249000ULL,0x3ffc,0x0e7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x027f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x027f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x067f)), -1L);
+ CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x067f)), -1L);
+ CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x0a7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x0a7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x0e7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0xe38e38e38e38e000ULL,0xbffb,0x0e7f)), 0L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x027f)), 32768L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x027f)), 32768L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x067f)), 32768L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x067f)), 32768L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x0a7f)), 32768L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x0a7f)), 32768L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x0e7f)), 32768L);
+ CHECKL(lrintl(make_lrd_cw(0x8000000000000000ULL,0x400e,0x0e7f)), 32768L);
+#if !defined(RT_ARCH_AMD64)
+ /* c90 says that the constant is 2147483648 (which is not representable as a signed 32-bit
+ * value). To that constant you've then applied the negation operation. c90 doesn't have
+ * negative constants, only positive ones that have been negated. */
+ CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x027f)), (long)(-2147483647L - 1));
+ CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x027f)), (long)(-2147483647L - 1));
+ CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x067f)), (long)(-2147483647L - 1));
+ CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x067f)), (long)(-2147483647L - 1));
+ CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x0a7f)), (long)(-2147483647L - 1));
+ CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x0a7f)), (long)(-2147483647L - 1));
+ CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x0e7f)), (long)(-2147483647L - 1));
+ CHECKL(lrintl(make_lrd_cw(0xad78ebc5ac620000ULL,0xc041,0x0e7f)), (long)(-2147483647L - 1));
+#endif
+ set_cw(0x27f);
+
+ CHECK(logl(2.7182818284590452353602874713526625L), 1.0);
+
+ CHECK(remainderl(1.0L, 1.0L), 0.0);
+ CHECK(remainderl(1.0L, 1.5L), -0.5);
+ CHECK(remainderl(42.0L, 34.25L), 7.75);
+ CHECK(remainderf(43.0, 34.25), 8.75);
+ CHECK(remainder(44.25, 34.25), 10.00);
+ double rd1 = 44.25;
+ double rd2 = 34.25;
+ CHECK(remainder(rd1, rd2), 10.00);
+ CHECK(remainder(2.5, 2.0), 0.5);
+ CHECK(remainder(2.5, 2.0), 0.5);
+ CHECK(remainder(2.5, 2.0), 0.5);
+ CHECKLL(testremainder(), 1);
+
+
+ /* Only works in extended precision, while double precision is default on BSD (including Darwin) */
+ set_cw(0x37f);
+ CHECK(rintl(1.0L), 1.0);
+ CHECK(rintl(1.4L), 1.0);
+ CHECK(rintl(1.3L), 1.0);
+ CHECK(rintl(0.9L), 1.0);
+ CHECK(rintl(3123.1232L), 3123.0);
+ CHECK(rint(3985.13454), 3985.0);
+ CHECK(rintf(9999.999), 10000.0);
+ set_cw(0x27f);
+
+ CHECK(sinl(1.0L), 0.84147098480789650664L);
+#if 0
+ lrd = 180.0L;
+ CHECK(sinl(lrd), -0.801152635733830477871L);
+#else
+ lrd = 180.0L;
+ lrdExpect = SIN180a;
+ lrdResult = sinl(lrd);
+ if (lrdResult != lrdExpect)
+ {
+ lrdExpect = SIN180b;
+ if (lrdResult != lrdExpect)
+ {
+ bitch("sinl(lrd)", &lrdResult, &lrdExpect);
+ cErrors++;
+ }
+ }
+#endif
+#if 0
+ CHECK(sinl(180.0L), SIN180);
+#else
+ lrdExpect = SIN180a;
+ lrdResult = sinl(180.0L);
+ if (lrdResult != lrdExpect)
+ {
+ lrdExpect = SIN180b;
+ if (lrdResult != lrdExpect)
+ {
+ bitch("sinl(180.0L)", &lrdResult, &lrdExpect);
+ cErrors++;
+ }
+ }
+#endif
+ CHECKLL(testsin(), 1);
+
+ CHECK(sqrtl(1.0L), 1.0);
+ CHECK(sqrtl(4.0L), 2.0);
+ CHECK(sqrtl(1525225.0L), 1235.0);
+
+ CHECK(tanl(0.0L), 0.0);
+ CHECK(tanl(0.7853981633974483096156608458198757L), 1.0);
+
+ CHECK(powl(0.0, 0.0), 1.0);
+ CHECK(powl(2.0, 2.0), 4.0);
+ CHECK(powl(3.0, 3.0), 27.0);
+
+ return cErrors;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+#if 0
+
+#define floatx_to_int32 floatx80_to_int32
+#define floatx_to_int64 floatx80_to_int64
+#define floatx_to_int32_round_to_zero floatx80_to_int32_round_to_zero
+#define floatx_to_int64_round_to_zero floatx80_to_int64_round_to_zero
+#define floatx_abs floatx80_abs
+#define floatx_chs floatx80_chs
+#define floatx_round_to_int(foo, bar) floatx80_round_to_int(foo, NULL)
+#define floatx_compare floatx80_compare
+#define floatx_compare_quiet floatx80_compare_quiet
+#undef sin
+#undef cos
+#undef sqrt
+#undef pow
+#undef log
+#undef tan
+#undef atan2
+#undef floor
+#undef ceil
+#undef ldexp
+#define sin sinl
+#define cos cosl
+#define sqrt sqrtl
+#define pow powl
+#define log logl
+#define tan tanl
+#define atan2 atan2l
+#define floor floorl
+#define ceil ceill
+#define ldexp ldexpl
+
+
+typedef long double CPU86_LDouble;
+
+typedef union {
+ long double d;
+ struct {
+ unsigned long long lower;
+ unsigned short upper;
+ } l;
+} CPU86_LDoubleU;
+
+/* the following deal with x86 long double-precision numbers */
+#define MAXEXPD 0x7fff
+#define EXPBIAS 16383
+#define EXPD(fp) (fp.l.upper & 0x7fff)
+#define SIGND(fp) ((fp.l.upper) & 0x8000)
+#define MANTD(fp) (fp.l.lower)
+#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
+
+typedef long double floatx80;
+#define STATUS_PARAM , void *pv
+
+static floatx80 floatx80_round_to_int( floatx80 a STATUS_PARAM)
+{
+ return rintl(a);
+}
+
+
+
+struct myenv
+{
+ unsigned int fpstt; /* top of stack index */
+ unsigned int fpus;
+ unsigned int fpuc;
+ unsigned char fptags[8]; /* 0 = valid, 1 = empty */
+ union {
+#ifdef USE_X86LDOUBLE
+ CPU86_LDouble d __attribute__((aligned(16)));
+#else
+ CPU86_LDouble d;
+#endif
+ } fpregs[8];
+
+} my_env, env_org, env_res, *env = &my_env;
+
+
+#define ST0 (env->fpregs[env->fpstt].d)
+#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7].d)
+#define ST1 ST(1)
+#define MAXTAN 9223372036854775808.0
+
+
+static inline void fpush(void)
+{
+ env->fpstt = (env->fpstt - 1) & 7;
+ env->fptags[env->fpstt] = 0; /* validate stack entry */
+}
+
+static inline void fpop(void)
+{
+ env->fptags[env->fpstt] = 1; /* invalidate stack entry */
+ env->fpstt = (env->fpstt + 1) & 7;
+}
+
+static void helper_f2xm1(void)
+{
+ ST0 = pow(2.0,ST0) - 1.0;
+}
+
+static void helper_fyl2x(void)
+{
+ CPU86_LDouble fptemp;
+
+ fptemp = ST0;
+ if (fptemp>0.0){
+ fptemp = log(fptemp)/log(2.0); /* log2(ST) */
+ ST1 *= fptemp;
+ fpop();
+ } else {
+ env->fpus &= (~0x4700);
+ env->fpus |= 0x400;
+ }
+}
+
+static void helper_fptan(void)
+{
+ CPU86_LDouble fptemp;
+
+ fptemp = ST0;
+ if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
+ env->fpus |= 0x400;
+ } else {
+ ST0 = tan(fptemp);
+ fpush();
+ ST0 = 1.0;
+ env->fpus &= (~0x400); /* C2 <-- 0 */
+ /* the above code is for |arg| < 2**52 only */
+ }
+}
+
+static void helper_fpatan(void)
+{
+ CPU86_LDouble fptemp, fpsrcop;
+
+ fpsrcop = ST1;
+ fptemp = ST0;
+ ST1 = atan2(fpsrcop,fptemp);
+ fpop();
+}
+
+static void helper_fxtract(void)
+{
+ CPU86_LDoubleU temp;
+ unsigned int expdif;
+
+ temp.d = ST0;
+ expdif = EXPD(temp) - EXPBIAS;
+ /*DP exponent bias*/
+ ST0 = expdif;
+ fpush();
+ BIASEXPONENT(temp);
+ ST0 = temp.d;
+}
+
+static void helper_fprem1(void)
+{
+ CPU86_LDouble dblq, fpsrcop, fptemp;
+ CPU86_LDoubleU fpsrcop1, fptemp1;
+ int expdif;
+ int q;
+
+ fpsrcop = ST0;
+ fptemp = ST1;
+ fpsrcop1.d = fpsrcop;
+ fptemp1.d = fptemp;
+ expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
+ if (expdif < 53) {
+ dblq = fpsrcop / fptemp;
+ dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
+ ST0 = fpsrcop - fptemp*dblq;
+ q = (int)dblq; /* cutting off top bits is assumed here */
+ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
+ /* (C0,C1,C3) <-- (q2,q1,q0) */
+ env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
+ env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
+ env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
+ } else {
+ env->fpus |= 0x400; /* C2 <-- 1 */
+ fptemp = pow(2.0, expdif-50);
+ fpsrcop = (ST0 / ST1) / fptemp;
+ /* fpsrcop = integer obtained by rounding to the nearest */
+ fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?
+ floor(fpsrcop): ceil(fpsrcop);
+ ST0 -= (ST1 * fpsrcop * fptemp);
+ }
+}
+
+static void helper_fprem(void)
+{
+#if 0
+LogFlow(("helper_fprem: ST0=%.*Rhxs ST1=%.*Rhxs fpus=%#x\n", sizeof(ST0), &ST0, sizeof(ST1), &ST1, env->fpus));
+
+ __asm__ __volatile__("fldt (%2)\n"
+ "fldt (%1)\n"
+ "fprem \n"
+ "fnstsw (%0)\n"
+ "fstpt (%1)\n"
+ "fstpt (%2)\n"
+ : : "r" (&env->fpus), "r" (&ST0), "r" (&ST1) : "memory");
+
+LogFlow(("helper_fprem: -> ST0=%.*Rhxs fpus=%#x c\n", sizeof(ST0), &ST0, env->fpus));
+#else
+ CPU86_LDouble dblq, fpsrcop, fptemp;
+ CPU86_LDoubleU fpsrcop1, fptemp1;
+ int expdif;
+ int q;
+
+ fpsrcop = ST0;
+ fptemp = ST1;
+ fpsrcop1.d = fpsrcop;
+ fptemp1.d = fptemp;
+
+ expdif = EXPD(fpsrcop1) - EXPD(fptemp1);
+ if ( expdif < 53 ) {
+ dblq = fpsrcop / fptemp;
+ dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);
+ ST0 = fpsrcop - fptemp*dblq;
+ q = (int)dblq; /* cutting off top bits is assumed here */
+ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
+ /* (C0,C1,C3) <-- (q2,q1,q0) */
+ env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */
+ env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */
+ env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */
+ } else {
+ env->fpus |= 0x400; /* C2 <-- 1 */
+ fptemp = pow(2.0, expdif-50);
+ fpsrcop = (ST0 / ST1) / fptemp;
+ /* fpsrcop = integer obtained by chopping */
+ fpsrcop = (fpsrcop < 0.0)?
+ -(floor(fabs(fpsrcop))): floor(fpsrcop);
+ ST0 -= (ST1 * fpsrcop * fptemp);
+ }
+#endif
+}
+
+static void helper_fyl2xp1(void)
+{
+ CPU86_LDouble fptemp;
+
+ fptemp = ST0;
+ if ((fptemp+1.0)>0.0) {
+ fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */
+ ST1 *= fptemp;
+ fpop();
+ } else {
+ env->fpus &= (~0x4700);
+ env->fpus |= 0x400;
+ }
+}
+
+static void helper_fsqrt(void)
+{
+ CPU86_LDouble fptemp;
+
+ fptemp = ST0;
+ if (fptemp<0.0) {
+ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
+ env->fpus |= 0x400;
+ }
+ ST0 = sqrt(fptemp);
+}
+
+static void helper_fsincos(void)
+{
+ CPU86_LDouble fptemp;
+
+ fptemp = ST0;
+ if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
+ env->fpus |= 0x400;
+ } else {
+ ST0 = sin(fptemp);
+ fpush();
+ ST0 = cos(fptemp);
+ env->fpus &= (~0x400); /* C2 <-- 0 */
+ /* the above code is for |arg| < 2**63 only */
+ }
+}
+
+static void helper_frndint(void)
+{
+ ST0 = floatx_round_to_int(ST0, &env->fp_status);
+}
+
+static void helper_fscale(void)
+{
+ ST0 = ldexp (ST0, (int)(ST1));
+}
+
+static void helper_fsin(void)
+{
+ CPU86_LDouble fptemp;
+
+ fptemp = ST0;
+ if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
+ env->fpus |= 0x400;
+ } else {
+ ST0 = sin(fptemp);
+ env->fpus &= (~0x400); /* C2 <-- 0 */
+ /* the above code is for |arg| < 2**53 only */
+ }
+}
+
+static void helper_fcos(void)
+{
+ CPU86_LDouble fptemp;
+
+ fptemp = ST0;
+ if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {
+ env->fpus |= 0x400;
+ } else {
+ ST0 = cos(fptemp);
+ env->fpus &= (~0x400); /* C2 <-- 0 */
+ /* the above code is for |arg5 < 2**63 only */
+ }
+}
+
+static void helper_fxam_ST0(void)
+{
+ CPU86_LDoubleU temp;
+ int expdif;
+
+ temp.d = ST0;
+
+ env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */
+ if (SIGND(temp))
+ env->fpus |= 0x200; /* C1 <-- 1 */
+
+ /* XXX: test fptags too */
+ expdif = EXPD(temp);
+ if (expdif == MAXEXPD) {
+#ifdef USE_X86LDOUBLE
+ if (MANTD(temp) == 0x8000000000000000ULL)
+#else
+ if (MANTD(temp) == 0)
+#endif
+ env->fpus |= 0x500 /*Infinity*/;
+ else
+ env->fpus |= 0x100 /*NaN*/;
+ } else if (expdif == 0) {
+ if (MANTD(temp) == 0)
+ env->fpus |= 0x4000 /*Zero*/;
+ else
+ env->fpus |= 0x4400 /*Denormal*/;
+ } else {
+ env->fpus |= 0x400;
+ }
+}
+
+
+void check_env(void)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ CPU86_LDoubleU my, res;
+ my.d = env->fpregs[i].d;
+ res.d = env_res.fpregs[i].d;
+
+ if ( my.l.lower != res.l.lower
+ || my.l.upper != res.l.upper)
+ printf("register %i: %#018llx:%#06x\n"
+ " expected %#018llx:%#06x\n",
+ i,
+ my.l.lower, my.l.upper,
+ res.l.lower, res.l.upper);
+ }
+ for (i = 0; i < 8; i++)
+ if (env->fptags[i] != env_res.fptags[i])
+ printf("tag %i: %d != %d\n", i, env->fptags[i], env_res.fptags[i]);
+ if (env->fpstt != env_res.fpstt)
+ printf("fpstt: %#06x != %#06x\n", env->fpstt, env_res.fpstt);
+ if (env->fpuc != env_res.fpuc)
+ printf("fpuc: %#06x != %#06x\n", env->fpuc, env_res.fpuc);
+ if (env->fpus != env_res.fpus)
+ printf("fpus: %#06x != %#06x\n", env->fpus, env_res.fpus);
+}
+#endif /* not used. */
+
+#if 0 /* insert this into helper.c */
+/* FPU helpers */
+CPU86_LDoubleU my_st[8];
+unsigned int my_fpstt;
+unsigned int my_fpus;
+unsigned int my_fpuc;
+unsigned char my_fptags[8];
+
+void hlp_fpu_enter(void)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ my_st[i].d = env->fpregs[i].d;
+ my_fpstt = env->fpstt;
+ my_fpus = env->fpus;
+ my_fpuc = env->fpuc;
+ memcpy(&my_fptags, &env->fptags, sizeof(my_fptags));
+}
+
+void hlp_fpu_leave(const char *psz)
+{
+ int i;
+ Log(("/*code*/ \n"));
+ for (i = 0; i < 8; i++)
+ Log(("/*code*/ *(unsigned long long *)&env_org.fpregs[%d] = %#018llxULL; ((unsigned short *)&env_org.fpregs[%d])[4] = %#06x; env_org.fptags[%d]=%d;\n",
+ i, my_st[i].l.lower, i, my_st[i].l.upper, i, my_fptags[i]));
+ Log(("/*code*/ env_org.fpstt=%#x;\n", my_fpstt));
+ Log(("/*code*/ env_org.fpus=%#x;\n", my_fpus));
+ Log(("/*code*/ env_org.fpuc=%#x;\n", my_fpuc));
+ for (i = 0; i < 8; i++)
+ {
+ CPU86_LDoubleU u;
+ u.d = env->fpregs[i].d;
+ Log(("/*code*/ *(unsigned long long *)&env_res.fpregs[%d] = %#018llxULL; ((unsigned short *)&env_res.fpregs[%d])[4] = %#06x; env_res.fptags[%d]=%d;\n",
+ i, u.l.lower, i, u.l.upper, i, env->fptags[i]));
+ }
+ Log(("/*code*/ env_res.fpstt=%#x;\n", env->fpstt));
+ Log(("/*code*/ env_res.fpus=%#x;\n", env->fpus));
+ Log(("/*code*/ env_res.fpuc=%#x;\n", env->fpuc));
+
+ Log(("/*code*/ my_env = env_org;\n"));
+ Log(("/*code*/ %s();\n", psz));
+ Log(("/*code*/ check_env();\n"));
+}
+#endif /* helper.c */
+
+extern void testmath2(void )
+{
+#if 0
+#include "/tmp/code.h"
+#endif
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef MATHTEST_STANDALONE
+
+void test_fops(double a, double b)
+{
+ printf("a=%f b=%f a+b=%f\n", a, b, a + b);
+ printf("a=%f b=%f a-b=%f\n", a, b, a - b);
+ printf("a=%f b=%f a*b=%f\n", a, b, a * b);
+ printf("a=%f b=%f a/b=%f\n", a, b, a / b);
+ printf("a=%f b=%f fmod(a, b)=%f\n", a, b, (double)fmod(a, b));
+ printf("a=%f sqrt(a)=%f\n", a, (double)sqrtl(a));
+ printf("a=%f sin(a)=%f\n", a, (double)sinl(a));
+ printf("a=%f cos(a)=%f\n", a, (double)cos(a));
+ printf("a=%f tan(a)=%f\n", a, (double)tanl(a));
+ printf("a=%f log(a)=%f\n", a, (double)log(a));
+ printf("a=%f exp(a)=%f\n", a, (double)exp(a));
+ printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
+ /* just to test some op combining */
+ printf("a=%f asin(sinl(a))=%f\n", a, (double)asin(sinl(a)));
+ printf("a=%f acos(cos(a))=%f\n", a, (double)acos(cos(a)));
+ printf("a=%f atan(tanl(a))=%f\n", a, (double)atan(tanl(a)));
+}
+
+int main()
+{
+ unsigned cErrors = testmath();
+
+ testmath2();
+ test_fops(2, 3);
+ test_fops(1.4, -5);
+
+ printf("cErrors=%u\n", cErrors);
+ return cErrors;
+}
+#endif
+