From d7fa4cfb8b960e6a81f00976f4bb7dbf09ca2aa0 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Mon, 14 May 2018 11:30:24 +0200 Subject: [PATCH] hw: enable eager FPU context switch for ARM * Add an ieee754 FPU test * Remove simple fpu test Fix #2822 --- repos/base-hw/include/spec/arndale/vm_state.h | 5 + repos/base-hw/include/spec/imx53/vm_state.h | 7 + repos/base-hw/lib/mk/spec/arm_v6/core-hw.inc | 2 + repos/base-hw/lib/mk/spec/arm_v7/core-hw.inc | 2 + .../lib/mk/spec/arndale/bootstrap-hw.mk | 2 +- repos/base-hw/lib/mk/spec/arndale/core-hw.mk | 2 +- .../base-hw/lib/mk/spec/cortex_a9/core-hw.inc | 1 - .../base-hw/lib/mk/spec/panda/bootstrap-hw.mk | 2 +- repos/base-hw/lib/mk/spec/panda/core-hw.mk | 2 +- repos/base-hw/src/bootstrap/spec/arm/crt0.s | 16 + repos/base-hw/src/core/spec/arm/cpu_support.h | 10 +- .../src/core/spec/arm/exception_vector.s | 32 + repos/base-hw/src/core/spec/arm/fpu.h | 255 --- .../src/core/spec/arm/kernel/thread.cc | 14 +- repos/base-hw/src/core/spec/arm/vfpv2.s | 31 + repos/base-hw/src/core/spec/arm/vfpv3-d32.s | 34 + .../spec/arm_v7/trustzone/exception_vector.s | 14 +- .../arm_v7/virtualization/exception_vector.s | 19 +- repos/base-hw/src/core/spec/cortex_a15/cpu.h | 7 - repos/base-hw/src/core/spec/cortex_a9/cpu.h | 90 +- repos/base-hw/src/core/spec/cortex_a9/fpu.cc | 24 - .../src/core/spec/cortex_a9/kernel/cpu.cc | 2 - repos/base-hw/src/core/spec/x86_64/cpu.h | 5 - repos/base/mk/spec/arm_v6.mk | 2 +- repos/base/mk/spec/arm_v7a.mk | 2 +- repos/base/recipes/pkg/test-fpu/README | 1 - repos/base/recipes/pkg/test-fpu/archives | 2 - repos/base/recipes/pkg/test-fpu/hash | 1 - repos/base/recipes/pkg/test-fpu/runtime | 43 - repos/base/recipes/src/test-fpu/content.mk | 2 - repos/base/recipes/src/test-fpu/hash | 1 - repos/base/recipes/src/test-fpu/used_apis | 1 - repos/base/src/test/fpu/main.cc | 86 - repos/base/src/test/fpu/target.mk | 14 - repos/gems/run/depot_autopilot.run | 1 - repos/libports/run/ieee754.run | 1712 +++++++++++++++++ repos/libports/src/test/ieee754/component.cc | 15 + repos/libports/src/test/ieee754/target.mk | 4 + repos/libports/src/test/ieee754/tst-ieee754.c | 489 +++++ tool/autopilot.list | 1 + 40 files changed, 2427 insertions(+), 528 deletions(-) delete mode 100644 repos/base-hw/src/core/spec/arm/fpu.h create mode 100644 repos/base-hw/src/core/spec/arm/vfpv2.s create mode 100644 repos/base-hw/src/core/spec/arm/vfpv3-d32.s delete mode 100644 repos/base-hw/src/core/spec/cortex_a9/fpu.cc delete mode 100644 repos/base/recipes/pkg/test-fpu/README delete mode 100644 repos/base/recipes/pkg/test-fpu/archives delete mode 100644 repos/base/recipes/pkg/test-fpu/hash delete mode 100644 repos/base/recipes/pkg/test-fpu/runtime delete mode 100644 repos/base/recipes/src/test-fpu/content.mk delete mode 100644 repos/base/recipes/src/test-fpu/hash delete mode 100644 repos/base/recipes/src/test-fpu/used_apis delete mode 100644 repos/base/src/test/fpu/main.cc delete mode 100644 repos/base/src/test/fpu/target.mk create mode 100644 repos/libports/run/ieee754.run create mode 100644 repos/libports/src/test/ieee754/component.cc create mode 100644 repos/libports/src/test/ieee754/target.mk create mode 100755 repos/libports/src/test/ieee754/tst-ieee754.c diff --git a/repos/base-hw/include/spec/arndale/vm_state.h b/repos/base-hw/include/spec/arndale/vm_state.h index 4fe551255..1bcb22e9e 100644 --- a/repos/base-hw/include/spec/arndale/vm_state.h +++ b/repos/base-hw/include/spec/arndale/vm_state.h @@ -51,6 +51,11 @@ struct Genode::Vm_state : Genode::Cpu_state_modes Genode::uint32_t tls3; Genode::uint32_t cpacr; + /** + * Fpu registers + */ + Genode::uint32_t fpscr; + Genode::uint64_t d0_d31[32]; /** * Timer related registers diff --git a/repos/base-hw/include/spec/imx53/vm_state.h b/repos/base-hw/include/spec/imx53/vm_state.h index 61f510ad9..14aec20c7 100644 --- a/repos/base-hw/include/spec/imx53/vm_state.h +++ b/repos/base-hw/include/spec/imx53/vm_state.h @@ -31,6 +31,13 @@ struct Genode::Vm_state : Genode::Cpu_state_modes Genode::addr_t dfar; Genode::addr_t ttbr[2]; Genode::addr_t ttbrc; + + /** + * Fpu registers + */ + Genode::uint32_t fpscr; + Genode::uint64_t d0_d31[32]; + Genode::addr_t irq_injection; }; diff --git a/repos/base-hw/lib/mk/spec/arm_v6/core-hw.inc b/repos/base-hw/lib/mk/spec/arm_v6/core-hw.inc index a6c3ad887..23a82ad64 100644 --- a/repos/base-hw/lib/mk/spec/arm_v6/core-hw.inc +++ b/repos/base-hw/lib/mk/spec/arm_v6/core-hw.inc @@ -16,5 +16,7 @@ SRC_CC += spec/arm/kernel/thread_update_pd.cc SRC_CC += kernel/vm_thread_off.cc SRC_CC += kernel/kernel.cc +SRC_S += spec/arm/vfpv2.s + # include less specific configuration include $(BASE_DIR)/../base-hw/lib/mk/spec/arm/core-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arm_v7/core-hw.inc b/repos/base-hw/lib/mk/spec/arm_v7/core-hw.inc index 469e74828..3f5e7b77a 100644 --- a/repos/base-hw/lib/mk/spec/arm_v7/core-hw.inc +++ b/repos/base-hw/lib/mk/spec/arm_v7/core-hw.inc @@ -11,5 +11,7 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/spec/arm_v7 SRC_CC += spec/arm_v7/cpu.cc SRC_CC += spec/arm_v7/perf_counter.cc +SRC_S += spec/arm/vfpv3-d32.cc + # include less specific configuration include $(BASE_DIR)/../base-hw/lib/mk/spec/arm/core-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arndale/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/arndale/bootstrap-hw.mk index cab6b296b..9436de911 100644 --- a/repos/base-hw/lib/mk/spec/arndale/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/arndale/bootstrap-hw.mk @@ -13,6 +13,6 @@ NR_OF_CPUS = 2 # we need more specific compiler hints for some 'special' assembly code # override -march=armv7-a because it conflicts with -mcpu=cortex-a15 # -CC_MARCH = -mcpu=cortex-a15 +CC_MARCH = -mcpu=cortex-a15 -mfpu=vfpv3 -mfloat-abi=softfp include $(REP_DIR)/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arndale/core-hw.mk b/repos/base-hw/lib/mk/spec/arndale/core-hw.mk index 6d143f9ca..7ef450c08 100644 --- a/repos/base-hw/lib/mk/spec/arndale/core-hw.mk +++ b/repos/base-hw/lib/mk/spec/arndale/core-hw.mk @@ -25,7 +25,7 @@ NR_OF_CPUS = 2 # we need more specific compiler hints for some 'special' assembly code # override -march=armv7-a because it conflicts with -mcpu=cortex-a15 # -CC_MARCH = -mcpu=cortex-a15 +CC_MARCH = -mcpu=cortex-a15 -mfpu=vfpv3 -mfloat-abi=softfp # include less specific configuration include $(REP_DIR)/lib/mk/spec/exynos5/core-hw.inc diff --git a/repos/base-hw/lib/mk/spec/cortex_a9/core-hw.inc b/repos/base-hw/lib/mk/spec/cortex_a9/core-hw.inc index b78001b04..106f92d94 100644 --- a/repos/base-hw/lib/mk/spec/cortex_a9/core-hw.inc +++ b/repos/base-hw/lib/mk/spec/cortex_a9/core-hw.inc @@ -10,7 +10,6 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/spec/arm_gic # add C++ sources SRC_CC += spec/cortex_a9/kernel/cpu.cc -SRC_CC += spec/cortex_a9/fpu.cc SRC_CC += spec/cortex_a9/board.cc SRC_CC += spec/cortex_a9/timer.cc SRC_CC += spec/arm/smp/kernel/thread_update_pd.cc diff --git a/repos/base-hw/lib/mk/spec/panda/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/panda/bootstrap-hw.mk index ad70c610d..7c7dbe8e0 100644 --- a/repos/base-hw/lib/mk/spec/panda/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/panda/bootstrap-hw.mk @@ -9,6 +9,6 @@ SRC_CC += hw/spec/arm/arm_v7_cpu.cc SRC_CC += hw/spec/32bit/memory_map.cc SRC_S += bootstrap/spec/arm/crt0.s -CC_MARCH = -mcpu=cortex-a9 +CC_MARCH = -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/panda/core-hw.mk b/repos/base-hw/lib/mk/spec/panda/core-hw.mk index 0996879a2..080b6f0fe 100644 --- a/repos/base-hw/lib/mk/spec/panda/core-hw.mk +++ b/repos/base-hw/lib/mk/spec/panda/core-hw.mk @@ -13,7 +13,7 @@ SRC_CC += platform_services.cc NR_OF_CPUS += 2 -CC_MARCH = -mcpu=cortex-a9 +CC_MARCH = -mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=softfp # include less specific configuration include $(REP_DIR)/lib/mk/spec/cortex_a9/core-hw.inc diff --git a/repos/base-hw/src/bootstrap/spec/arm/crt0.s b/repos/base-hw/src/bootstrap/spec/arm/crt0.s index 9e19d4a64..377edbe59 100644 --- a/repos/base-hw/src/bootstrap/spec/arm/crt0.s +++ b/repos/base-hw/src/bootstrap/spec/arm/crt0.s @@ -62,6 +62,22 @@ add sp, r0, r1 + /**************** + ** Enable VFP ** + ****************/ + + mov r0, #0xf + lsl r0, #20 + mcr p15, 0, r0, c1, c0, 2 /* write to CPACR to enable VFP access */ + mcr p15, 0, r0, c7, c5, 4 /* deprecated ISB instruction <= ARMv6 */ + + vmrs r0, fpexc /* enable the VFP by read/write fpexc */ + mov r1, #1 /* enable bit 30 */ + lsl r1, #30 + orr r0, r1 + vmsr fpexc, r0 + + /************************************ ** Jump to high-level entry point ** ************************************/ diff --git a/repos/base-hw/src/core/spec/arm/cpu_support.h b/repos/base-hw/src/core/spec/arm/cpu_support.h index 903484f1a..499d1110a 100644 --- a/repos/base-hw/src/core/spec/arm/cpu_support.h +++ b/repos/base-hw/src/core/spec/arm/cpu_support.h @@ -58,7 +58,13 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu } }; - struct alignas(4) Context : Cpu_state + struct Fpu_context + { + uint32_t fpscr { 1UL << 24 }; /* VFP/SIMD - status/control register */ + uint64_t d0_d31[32]; /* VFP/SIMD - general purpose registers */ + }; + + struct alignas(4) Context : Cpu_state, Fpu_context { Context(bool privileged); }; @@ -146,8 +152,6 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu ** Dummies ** *************/ - bool retry_undefined_instr(Context&) { return false; } - /** * Return kernel name of the executing CPU */ diff --git a/repos/base-hw/src/core/spec/arm/exception_vector.s b/repos/base-hw/src/core/spec/arm/exception_vector.s index d77e2d54b..440db4ae6 100644 --- a/repos/base-hw/src/core/spec/arm/exception_vector.s +++ b/repos/base-hw/src/core/spec/arm/exception_vector.s @@ -115,6 +115,17 @@ stmia r0!, {r1-r3} /* save pc, cpsr and exception type */ clrex /* clear exclusive access needed for cmpxchg */ cps #SVC_MODE + + mov r1, #1 /* clear exception state of the VFP */ + lsl r1, #30 + vmsr fpexc, r1 + adr r1, _fpu_save + ldr r1, [r1] + blx r1 + + /* + * Go to kernel entry code + */ adr lr, _kernel_entry ldr lr, [lr] bx lr @@ -122,6 +133,9 @@ _kernel_entry: .long kernel + _fpu_save: + .long vfp_save_fpu_context + .section .text @@ -133,3 +147,21 @@ idle_thread_main: wfi b idle_thread_main + + + /***************************** + ** kernel to userland switch ** + *******************************/ + + .global kernel_to_user_context_switch + kernel_to_user_context_switch: + push { r0 } + mov r0, r1 + bl vfp_load_fpu_context + pop { r0 } + mov sp, r0 + ldr lr, [sp, #15*4] + ldr r1, [sp, #16*4] + msr spsr_cxsf, r1 + ldm sp, {r0-r14}^ + subs pc, lr, #0 diff --git a/repos/base-hw/src/core/spec/arm/fpu.h b/repos/base-hw/src/core/spec/arm/fpu.h deleted file mode 100644 index f9a44c8e8..000000000 --- a/repos/base-hw/src/core/spec/arm/fpu.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * \brief ARM-specific FPU driver for core - * \author Stefan Kalkowski - * \author Martin stein - * \date 2016-01-19 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CORE__SPEC__ARM__FPU_H_ -#define _CORE__SPEC__ARM__FPU_H_ - -#include - -namespace Genode { class Fpu; } - -/** - * FPU driver for the ARM VFPv3-D16 architecture - */ -class Genode::Fpu -{ - private: - - /** - * Floating-point Status and Control Register - */ - struct Fpscr : Register<32> - { - /** - * Read register value - */ - static access_t read() - { - /* FIXME: See annotation 1. */ - access_t v; - asm volatile ("mrc p10, 7, %[v], cr1, cr0, 0" : [v] "=r" (v) ::); - return v; - } - - /** - * Override register value - * - * \param v write value - */ - static void write(access_t const v) - { - /* FIXME: See annotation 1. */ - asm volatile ("mcr p10, 7, %[v], cr1, cr0, 0" :: [v] "r" (v) :); - } - }; - - /** - * Floating-Point Exception Control register - */ - struct Fpexc : Register<32> - { - struct En : Bitfield<30, 1> { }; - - /** - * Read register value - */ - static access_t read() - { - /* FIXME: See annotation 1. */ - access_t v; - asm volatile ("mrc p10, 7, %[v], cr8, cr0, 0" : [v] "=r" (v) ::); - return v; - } - - /** - * Override register value - * - * \param v write value - */ - static void write(access_t const v) - { - /* FIXME: See annotation 1. */ - asm volatile ("mcr p10, 7, %[v], cr8, cr0, 0" :: [v] "r" (v) :); - } - }; - - public: - - class Context - { - private: - - /* - * Noncopyable - */ - Context(Context const &); - Context &operator = (Context const &); - - friend class Fpu; - - struct - { - /* advanced FP/SIMD - system registers */ - uint32_t fpscr; - uint32_t fpexc; - - /* advanced FP/SIMD - general purpose registers d0-d15 */ - uint64_t d0, d1, d2, d3, d4, d5, d6, d7; - uint64_t d8, d9, d10, d11, d12, d13, d14, d15; - }; - - Fpu * _fpu = nullptr; - - public: - - Context() : fpexc(Fpexc::En::bits(1)) { } - - ~Context() { if (_fpu) _fpu->unset(*this); } - }; - - private: - - Context * _context = nullptr; - - /** - * Enable FPU - */ - void _enable() - { - Fpexc::access_t fpexc = Fpexc::read(); - Fpexc::En::set(fpexc, 1); - Fpexc::write(fpexc); - } - - /** - * Disable FPU - */ - void _disable() - { - Fpexc::access_t fpexc = Fpexc::read(); - Fpexc::En::set(fpexc, 0); - Fpexc::write(fpexc); - } - - /** - * Save FPU context - */ - void _save() - { - /* save system registers */ - _context->fpexc = Fpexc::read(); - _context->fpscr = Fpscr::read(); - - /* - * Save D0 - D15 - * - * FIXME: See annotation 2. - */ - void * const d0_d15_base = &_context->d0; - asm volatile ( - "stc p11, cr0, [%[d0_d15_base]], #128" - :: [d0_d15_base] "r" (d0_d15_base) : ); - } - - /** - * Load context to FPU - */ - void _load() - { - /* load system registers */ - Fpexc::write(_context->fpexc); - Fpscr::write(_context->fpscr); - - /* - * Load D0 - D15 - * - * FIXME: See annotation 2. - */ - void * const d0_d15_base = &_context->d0; - asm volatile ( - "ldc p11, cr0, [%[d0_d15_base]], #128" - :: [d0_d15_base] "r" (d0_d15_base) : ); - } - - /** - * Return wether the FPU is enabled - */ - bool _enabled() - { - Fpexc::access_t fpexc = Fpexc::read(); - return Fpexc::En::get(fpexc); - } - - public: - - /** - * Initialize FPU - */ - void init(); - - void switch_to(Context & context) - { - if (_context == &context) return; - _disable(); - } - - /** - * Return wether the FPU fault can be solved - * - * \param state CPU state of the user - */ - bool fault(Context & context) - { - if (_enabled()) { return false; } - _enable(); - if (_context != &context) { - if (_context) { - _save(); - _context->_fpu = nullptr; - } - _context = &context; - _context->_fpu = this; - _load(); - } - return true; - } - - /** - * Unset FPU context - */ - void unset(Context &context) { - if (_context == &context) _context = nullptr; } -}; - -/* - * Annotation 1 - * - * According to the ARMv7 manual this should be done via vmsr/vmrs instruction - * but it seems that binutils 2.22 doesn't fully support this yet. Hence, we - * use a co-processor instruction instead. The parameters to target the - * register this way can be determined via 'sys/arm/include/vfp.h' and - * 'sys/arm/arm/vfp.c' of the FreeBSD head branch as from 2014.04.17. - */ - -/* - * Annotation 2 - * - * According to the ARMv7 manual this should be done via vldm/vstm instruction - * but it seems that binutils 2.22 doesn't fully support this yet. Hence, we - * use a co-processor instruction instead. The parameters to target the - * register this way can be determined via 'sys/arm/arm/vfp.c' of the FreeBSD - * head branch as from 2014.04.17. - */ - -#endif /* _CORE__SPEC__ARM__FPU_H_ */ diff --git a/repos/base-hw/src/core/spec/arm/kernel/thread.cc b/repos/base-hw/src/core/spec/arm/kernel/thread.cc index 722c0f0fc..7cbab5c98 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/thread.cc @@ -19,6 +19,9 @@ using namespace Kernel; +extern "C" void kernel_to_user_context_switch(Cpu::Context*, Cpu::Fpu_context*); + + void Thread::exception(Cpu & cpu) { switch (regs->cpu_exception) { @@ -34,7 +37,6 @@ void Thread::exception(Cpu & cpu) _interrupt(cpu.id()); return; case Cpu::Context::UNDEFINED_INSTRUCTION: - if (_cpu->retry_undefined_instr(*regs)) { return; } Genode::warning(*this, ": undefined instruction at ip=", Genode::Hex(regs->ip)); _die(); @@ -106,14 +108,8 @@ void Thread::proceed(Cpu & cpu) cpu.switch_to(*regs, pd()->mmu_regs); regs->cpu_exception = cpu.stack_start(); - - asm volatile("mov sp, %0 \n" - "msr spsr_cxsf, %1 \n" - "mov lr, %2 \n" - "ldm sp, {r0-r14}^ \n" - "subs pc, lr, #0 \n" - :: "r" (static_cast(&*regs)), - "r" (regs->cpsr), "r" (regs->ip)); + kernel_to_user_context_switch((static_cast(&*regs)), + (static_cast(&*regs))); } diff --git a/repos/base-hw/src/core/spec/arm/vfpv2.s b/repos/base-hw/src/core/spec/arm/vfpv2.s new file mode 100644 index 000000000..0a8e6c8ed --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/vfpv2.s @@ -0,0 +1,31 @@ +/* + * \brief VFPv2 context load/store + * \author Stefan Kalkowski + * \date 2018-05-06 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +.section .text + +.global vfp_save_fpu_context +vfp_save_fpu_context: + vmrs r1, fpscr + stmia r0!, {r1} + vstm r0!, {d0-d15} + mov pc, lr + + +.global vfp_load_fpu_context +vfp_load_fpu_context: + push { r1, lr } + ldr r1, [r0] + vmsr fpscr, r1 + add r1, r0, #4 + vldm r1!, {d0-d15} + pop { r1, pc } diff --git a/repos/base-hw/src/core/spec/arm/vfpv3-d32.s b/repos/base-hw/src/core/spec/arm/vfpv3-d32.s new file mode 100644 index 000000000..671fb6bd3 --- /dev/null +++ b/repos/base-hw/src/core/spec/arm/vfpv3-d32.s @@ -0,0 +1,34 @@ +/* + * \brief VFPv3-D32 context load/store + * \author Stefan Kalkowski + * \date 2018-05-06 + */ + +/* + * Copyright (C) 2018 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +.section .text + +.global vfp_save_fpu_context +vfp_save_fpu_context: + push { r1, lr } + vmrs r1, fpscr + stmia r0!, {r1} + vstm r0!, {d0-d15} + vstm r0!, {d16-d31} + pop { r1, pc } + + +.global vfp_load_fpu_context +vfp_load_fpu_context: + push { r1, lr } + ldr r1, [r0] + vmsr fpscr, r1 + add r1, r0, #4 + vldm r1!, {d0-d15} + vldm r1!, {d16-d31} + pop { r1, pc } diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/exception_vector.s b/repos/base-hw/src/core/spec/arm_v7/trustzone/exception_vector.s index 0fd8fd2df..b159aec6b 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/exception_vector.s +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/exception_vector.s @@ -69,10 +69,14 @@ monitor_mode_exception_vector: _nonsecure_kernel_entry: ldr lr, [sp, #17*4] /* load kernel sp from vm context */ stmia r0!, {r1-r2} /* save spsr, and exception reason */ + mov r1, #1 /* clear exception state of the VFP */ + lsl r1, #30 + vmsr fpexc, r1 mrc p15, 0, r3, c6, c0, 0 /* move DFAR to r3 */ mrc p15, 0, r4, c2, c0, 0 /* move TTBR0 to r4 */ mrc p15, 0, r5, c2, c0, 1 /* move TTBR1 to r5 */ mrc p15, 0, r6, c2, c0, 2 /* move TTBRC to r6 */ + vmrs r7, fpscr /* move FPU ctrl to r7 */ mov r1, #0 mcr p15, 0, r1, c1, c1, 0 /* disable non-secure bit */ .irp mode,27,19,23,18,17 /* save mode specific registers */ @@ -81,7 +85,9 @@ monitor_mode_exception_vector: stmia r0!, {r1,sp,lr} /* store mode-specific sp and lr */ .endr stmia r0!, {r8-r12} /* save fiq r8-r12 */ - stmia r0!, {r3-r6} /* save MMU registers */ + stmia r0!, {r3-r7} /* save MMU registers */ + vstm r0!, {d0-d15} /* save FPU registers */ + vstm r0!, {d16-d31} cps #22 /* switch back to monitor mode */ mov r0, #0b111010011 /* spsr to SVC mode, irqs masked */ msr spsr_cxsf, r0 @@ -109,6 +115,12 @@ monitor_mode_enter_normal_world: msr spsr_cxfs, r2 /* load mode's spsr */ .endr ldmia r0!, {r8 - r12} /* load fiq r8-r12 */ + add r0, r0, #4*4 + ldr r1, [r0] + vmsr fpscr, r1 + add r1, r0, #4 + vldm r1!, {d0-d15} + vldm r1!, {d16-d31} cps #22 /* switch to monitor mode */ ldmia sp, {r0-lr}^ /* load user r0-r12,sp,lr */ str lr, [sp, #17*4] /* store kernel sp in vm context */ diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s b/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s index 0649cb423..fe7b8fede 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/exception_vector.s @@ -91,11 +91,16 @@ _host_to_vm: mcr p15, 0, r10, c6, c0, 0 /* write DFAR */ mcr p15, 0, r11, c6, c0, 2 /* write IFAR */ mcr p15, 0, r12, c13, c0, 1 /* write CIDR */ - ldm r0, {r1-r4} + ldm r0!, {r1-r4} mcr p15, 0, r1, c13, c0, 2 /* write TLS1 */ mcr p15, 0, r2, c13, c0, 3 /* write TLS2 */ mcr p15, 0, r3, c13, c0, 4 /* write TLS3 */ mcr p15, 0, r4, c1, c0, 2 /* write CPACR */ + ldr r1, [r0] + vmsr fpscr, r1 + add r1, r0, #4 + vldm r1!, {d0-d15} + vldm r1!, {d16-d31} ldmia sp, {r0-r12} /* load vm's r0-r12 */ eret @@ -106,6 +111,8 @@ _vm_to_host: mcrr p15, 6, r1, r1, c2 /* write VTTBR */ mcr p15, 4, r1, c1, c1, 0 /* write HCR register */ mcr p15, 4, r1, c1, c1, 3 /* write HSTR register */ + mov r1, #0xf + lsl r1, #20 mcr p15, 0, r1, c1, c0, 2 /* write CPACR */ mrs r1, ELR_hyp /* read ip */ mrs r2, spsr /* read cpsr */ @@ -130,7 +137,15 @@ _vm_to_host: mrc p15, 0, r10, c13, c0, 2 /* read TLS1 */ mrc p15, 0, r11, c13, c0, 3 /* read TLS2 */ mrc p15, 0, r12, c13, c0, 4 /* read TLS3 */ - stm r0, {r3-r12} + stm r0!, {r3-r12} + add r0, r0, #4 + mov r3, #1 /* clear fpu exception state */ + lsl r3, #30 + vmsr fpexc, r3 + vmrs r4, fpscr + stmia r0!, {r4} + vstm r0!, {d0-d15} + vstm r0!, {d16-d31} add r0, sp, #13*4 ldr r3, _vt_host_context_ptr ldr sp, [r3] diff --git a/repos/base-hw/src/core/spec/cortex_a15/cpu.h b/repos/base-hw/src/core/spec/cortex_a15/cpu.h index 0d725f4b9..90ec5433b 100644 --- a/repos/base-hw/src/core/spec/cortex_a15/cpu.h +++ b/repos/base-hw/src/core/spec/cortex_a15/cpu.h @@ -135,13 +135,6 @@ class Genode::Cpu : public Arm_v7_cpu if (mmu_context.id() && (Ttbr0_64bit::read() != mmu_context.ttbr0)) Ttbr0_64bit::write(mmu_context.ttbr0); } - - - /************* - ** Dummies ** - *************/ - - bool retry_undefined_instr(Context&) { return false; } }; #endif /* _CORE__SPEC__CORTEX_A15__CPU_H_ */ diff --git a/repos/base-hw/src/core/spec/cortex_a9/cpu.h b/repos/base-hw/src/core/spec/cortex_a9/cpu.h index b3af52308..0bc21f528 100644 --- a/repos/base-hw/src/core/spec/cortex_a9/cpu.h +++ b/repos/base-hw/src/core/spec/cortex_a9/cpu.h @@ -16,75 +16,43 @@ #define _CORE__SPEC__CORTEX_A9__CPU_H_ /* core includes */ -#include #include #include -namespace Genode { class Cpu; } +namespace Genode { struct Cpu; } -class Genode::Cpu : public Arm_v7_cpu +struct Genode::Cpu : Arm_v7_cpu { - protected: + /** + * Write back dirty cache lines and invalidate whole data cache + */ + void clean_invalidate_data_cache() + { + clean_invalidate_inner_data_cache(); + Board::l2_cache().clean_invalidate(); + } - Fpu _fpu { }; + /** + * Invalidate whole data cache + */ + void invalidate_data_cache() + { + invalidate_inner_data_cache(); + Board::l2_cache().invalidate(); + } - public: + /** + * Clean and invalidate data-cache for virtual region + * 'base' - 'base + size' + */ + void clean_invalidate_data_cache_by_virt_region(addr_t base, + size_t const size) + { + Arm_cpu::clean_invalidate_data_cache_by_virt_region(base, size); + Board::l2_cache().clean_invalidate(); + } - struct Context : Arm_cpu::Context, Fpu::Context - { - Context(bool privileged) - : Arm_cpu::Context(privileged) {} - }; - - /** - * Next cpu context to switch to - * - * \param context context to switch to - */ - void switch_to(Context & context, Mmu_context & mmu_context) - { - Arm_cpu::switch_to(context, mmu_context); - _fpu.switch_to(context); - } - - /** - * Return wether to retry an undefined user instruction after this call - * - * \param state CPU state of the user - */ - bool retry_undefined_instr(Context & context) { - return _fpu.fault(context); } - - /** - * Write back dirty cache lines and invalidate whole data cache - */ - void clean_invalidate_data_cache() - { - clean_invalidate_inner_data_cache(); - Board::l2_cache().clean_invalidate(); - } - - /** - * Invalidate whole data cache - */ - void invalidate_data_cache() - { - invalidate_inner_data_cache(); - Board::l2_cache().invalidate(); - } - - /** - * Clean and invalidate data-cache for virtual region - * 'base' - 'base + size' - */ - void clean_invalidate_data_cache_by_virt_region(addr_t base, - size_t const size) - { - Arm_cpu::clean_invalidate_data_cache_by_virt_region(base, size); - Board::l2_cache().clean_invalidate(); - } - - static unsigned executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); } + static unsigned executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); } }; #endif /* _CORE__SPEC__CORTEX_A9__CPU_H_ */ diff --git a/repos/base-hw/src/core/spec/cortex_a9/fpu.cc b/repos/base-hw/src/core/spec/cortex_a9/fpu.cc deleted file mode 100644 index efe4eb55e..000000000 --- a/repos/base-hw/src/core/spec/cortex_a9/fpu.cc +++ /dev/null @@ -1,24 +0,0 @@ -/* - * \brief CPU driver for core - * \author Martin stein - * \author Stefan Kalkowski - * \date 2016-01-19 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#include - -void Genode::Fpu::init() -{ - Cpu::Cpacr::access_t cpacr = Cpu::Cpacr::read(); - Cpu::Cpacr::Cp10::set(cpacr, 3); - Cpu::Cpacr::Cp11::set(cpacr, 3); - Cpu::Cpacr::write(cpacr); - _disable(); -} diff --git a/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc b/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc index 7ea1b13c9..a02942bfe 100644 --- a/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc @@ -23,8 +23,6 @@ void Kernel::Cpu::init(Kernel::Pic &pic) { - _fpu.init(); - { Lock::Guard guard(data_lock()); diff --git a/repos/base-hw/src/core/spec/x86_64/cpu.h b/repos/base-hw/src/core/spec/x86_64/cpu.h index fb58e2ffb..978cb8a63 100644 --- a/repos/base-hw/src/core/spec/x86_64/cpu.h +++ b/repos/base-hw/src/core/spec/x86_64/cpu.h @@ -116,11 +116,6 @@ class Genode::Cpu : public Hw::X86_64_cpu Fpu & fpu() { return _fpu; } - /** - * Return wether to retry an undefined user instruction after this call - */ - bool retry_undefined_instr(Context&) { return false; } - /** * Return kernel name of the executing CPU */ diff --git a/repos/base/mk/spec/arm_v6.mk b/repos/base/mk/spec/arm_v6.mk index 2c6bcd9c8..8c594527e 100644 --- a/repos/base/mk/spec/arm_v6.mk +++ b/repos/base/mk/spec/arm_v6.mk @@ -1,6 +1,6 @@ SPECS += arm REP_INC_DIR += include/spec/arm_v6 -CC_MARCH ?= -march=armv6k +CC_MARCH ?= -march=armv6k -mfpu=vfp -mfloat-abi=softfp include $(BASE_DIR)/mk/spec/arm.mk diff --git a/repos/base/mk/spec/arm_v7a.mk b/repos/base/mk/spec/arm_v7a.mk index f7c2496fd..3b3e88e33 100644 --- a/repos/base/mk/spec/arm_v7a.mk +++ b/repos/base/mk/spec/arm_v7a.mk @@ -1,5 +1,5 @@ SPECS += arm_v7 -CC_MARCH ?= -march=armv7-a +CC_MARCH ?= -march=armv7-a -mfpu=vfpv3 -mfloat-abi=softfp include $(BASE_DIR)/mk/spec/arm_v7.mk diff --git a/repos/base/recipes/pkg/test-fpu/README b/repos/base/recipes/pkg/test-fpu/README deleted file mode 100644 index 2c3efb8f2..000000000 --- a/repos/base/recipes/pkg/test-fpu/README +++ /dev/null @@ -1 +0,0 @@ -Test pseudo-parallel use of FPU if available diff --git a/repos/base/recipes/pkg/test-fpu/archives b/repos/base/recipes/pkg/test-fpu/archives deleted file mode 100644 index cb042a4e4..000000000 --- a/repos/base/recipes/pkg/test-fpu/archives +++ /dev/null @@ -1,2 +0,0 @@ -_/src/init -_/src/test-fpu diff --git a/repos/base/recipes/pkg/test-fpu/hash b/repos/base/recipes/pkg/test-fpu/hash deleted file mode 100644 index 117f7a140..000000000 --- a/repos/base/recipes/pkg/test-fpu/hash +++ /dev/null @@ -1 +0,0 @@ -2018-11-01 f8565783b90caaa5724a58e6ed7be9c999211fe3 diff --git a/repos/base/recipes/pkg/test-fpu/runtime b/repos/base/recipes/pkg/test-fpu/runtime deleted file mode 100644 index 40bb238ec..000000000 --- a/repos/base/recipes/pkg/test-fpu/runtime +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - [init -> test] FPU user started - [init -> test] FPU user started - [init -> test] FPU user started - [init -> test] FPU user started - [init -> test] FPU user started - [init -> test] FPU user started - [init -> test] FPU user started - [init -> test] FPU user started - [init -> test] FPU user started - [init -> test] FPU user started - [init -> test] test done - - calculation error - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/base/recipes/src/test-fpu/content.mk b/repos/base/recipes/src/test-fpu/content.mk deleted file mode 100644 index 5fc52cbac..000000000 --- a/repos/base/recipes/src/test-fpu/content.mk +++ /dev/null @@ -1,2 +0,0 @@ -SRC_DIR = src/test/fpu -include $(GENODE_DIR)/repos/base/recipes/src/content.inc diff --git a/repos/base/recipes/src/test-fpu/hash b/repos/base/recipes/src/test-fpu/hash deleted file mode 100644 index cc1527e9a..000000000 --- a/repos/base/recipes/src/test-fpu/hash +++ /dev/null @@ -1 +0,0 @@ -2018-11-01 fc82355e25add8ece1cfe7a4c93b8c42e4866049 diff --git a/repos/base/recipes/src/test-fpu/used_apis b/repos/base/recipes/src/test-fpu/used_apis deleted file mode 100644 index df967b96a..000000000 --- a/repos/base/recipes/src/test-fpu/used_apis +++ /dev/null @@ -1 +0,0 @@ -base diff --git a/repos/base/src/test/fpu/main.cc b/repos/base/src/test/fpu/main.cc deleted file mode 100644 index ebf6b866d..000000000 --- a/repos/base/src/test/fpu/main.cc +++ /dev/null @@ -1,86 +0,0 @@ -/* - * \brief Test pseudo-parallel use of FPU if available - * \author Martin Stein - * \date 2014-04-29 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Genode includes */ -#include -#include -#include -#include - -using namespace Genode; - -class Fpu_user : public Thread -{ - private: - - float _x; - Signal_transmitter _st; - Semaphore & _sem; - - void _calc(float volatile & x, float volatile & y) - { - for (unsigned j = 0; j < 100; j++) { - x *= (y * 1.357); - x /= (y * 1.246); - } - } - - public: - - Fpu_user(Env & env, float x, Signal_context_capability c, Semaphore &s) - : Thread(env, "fpu_user", sizeof(size_t)*2048), _x(x), _st(c), _sem(s) { - start(); } - - void entry() - { - log("FPU user started"); - - enum { TRIALS = 1000 }; - for (unsigned i = 0; i < TRIALS; i++) { - float volatile a = _x + (float)i * ((float)1 / TRIALS); - float volatile b = _x + (float)i * ((float)1 / TRIALS); - float volatile c = _x; - _calc(a, c); - _calc(b, c); - if (a != b) { - error("calculation error"); - break; - } - } - - _sem.up(); - _st.submit(); - } -}; - - -struct Main -{ - enum { FPU_USERS = 10 }; - - Semaphore sem { }; - Env & env; - Heap heap { env.ram(), env.rm() }; - Signal_handler
handler { env.ep(), *this, &Main::handle }; - - Main(Env & env) : env(env) { - for (unsigned i = 0; i < FPU_USERS; i++) - new (heap) Fpu_user(env, (i + 1) * 1.234, handler, sem); } - - void handle() { - if (sem.cnt() >= FPU_USERS) log("test done"); } -}; - - -void Component::construct(Genode::Env & env) { - static Main main(env); } diff --git a/repos/base/src/test/fpu/target.mk b/repos/base/src/test/fpu/target.mk deleted file mode 100644 index 754cf21f9..000000000 --- a/repos/base/src/test/fpu/target.mk +++ /dev/null @@ -1,14 +0,0 @@ -# -# \brief Test pseudo-parallel use of FPU if available -# \author Martin Stein -# \date 2012-04-25 -# - -# Set program name -TARGET = test-fpu - -# Add C++ sources -SRC_CC += main.cc - -# Add libraries -LIBS += base diff --git a/repos/gems/run/depot_autopilot.run b/repos/gems/run/depot_autopilot.run index 45b0e8652..6ae6610f5 100644 --- a/repos/gems/run/depot_autopilot.run +++ b/repos/gems/run/depot_autopilot.run @@ -44,7 +44,6 @@ set avail_test_pkgs { test-dynamic_config_slave test-expat test-fault_detection - test-fpu test-fs_log test-fs_packet test-fs_report diff --git a/repos/libports/run/ieee754.run b/repos/libports/run/ieee754.run new file mode 100644 index 000000000..165f68c3a --- /dev/null +++ b/repos/libports/run/ieee754.run @@ -0,0 +1,1712 @@ +# +# Raspberry PI 1 needs "undef exc" handling emulation code in the kernel +# for ieee754 full-compliant support +# +if {[have_spec rpi]} { + puts "Run script does not support Raspberry Pi 1" + exit 0 +} + +build "core init test/ieee754" +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +build_boot_image "core ld.lib.so init test-ieee754 libc.lib.so libm.lib.so vfs.lib.so" + +append qemu_args "-nographic " + +# increase expect output buffer, as we have a lot of lines +match_max -d 100000 + +set exit_line "exited with exit value" +run_genode_until $exit_line 30 +set serial_id [output_spawn_id] +while {true} { + global output + set old_output $output + grep_output $exit_line + set count [expr {[llength [split $output \n]] - 1}] + set output $old_output + if {$count >= 4} break + run_genode_until $exit_line 5 $serial_id +} + +set reference_output_arm { +FLT_RADIX = 2 +FLT_MANT_DIG = 24 +DBL_MANT_DIG = 53 +LDBL_MANT_DIG = 53 + +FLT_MIN_EXP = -125 +DBL_MIN_EXP = -1021 +LDBL_MIN_EXP = -1021 + +FLT_MAX_EXP = 128 +DBL_MAX_EXP = 1024 +LDBL_MAX_EXP = 1024 + +FLT_EPSILON = 1.19209e-07 = 0x1p-23 +DBL_EPSILON = 2.22045e-16 = 0x1p-52 +LDBL_EPSILON = 0 = 0x1p-52 + +FLT_MIN = 1.17549e-38 = 0x1p-126 +DBL_MIN = 2.22507e-308 = 0x1p-1022 +LDBL_MIN = 0 = 0x1p-1022 + +FLT_MAX = 3.40282e+38 = 0x1.fffffep+127 +DBL_MAX = 1.79769e+308 = 0x1.fffffffffffffp+1023 +LDBL_MAX = 8.98846e+307 = 0x1.fffffffffffffp+1023 + +sizeof(float) = 4 +sizeof(double) = 8 +sizeof(long double) = 8 + +x + y, with x = 9007199254740994.0 and y = 1.0 - 1/65536.0 (type double). +The IEEE-754 result is 9007199254740994 with double precision. +The IEEE-754 result is 9007199254740996 with extended precision. +The obtained result is 9007199254740994. + +NAN != NAN --> 1 (should be 1) +isnan(NAN) --> 1 (should be 1) +NAN >= 0.0 --> 0 (should be 0) +NAN <= 0.0 --> 0 (should be 0) + #3||#4 --> 0 (should be 0) +!(#3||#4) --> 1 (should be 1) + #3 + #4 --> 0 (should be 0) +!(#3 + #4) --> 1 (should be 1) +The FE_INVALID flag is not set for NAN >= 0. +The FE_INVALID flag is not set for NAN <= 0. +The FE_INVALID flag is not set for NAN > 0. +The FE_INVALID flag is not set for NAN < 0. + +x * y + z with FP_CONTRACT OFF is not fused. + +Rounding to nearest +Error, but let's do the test since it should be the default rounding mode. +(double) 0 = 0 +Signed zero tests (x is 0.0 and y is -0.0): + Test 1.0 / x != 1.0 / y returns 1 (should be 1). + Test 1.0 / x == 1.0 / +x returns 1 (should be 1). + Test 1.0 / x != 1.0 / +y returns 1 (should be 1). + Test 1.0 / x != 1.0 / -x returns 1 (should be 1). + Test 1.0 / x == 1.0 / -y returns 1 (should be 1). +0 + 0 = 0 +0 - 0 = 0 +0 + -0 = 0 +0 - -0 = 0 +-0 + 0 = 0 +-0 - 0 = -0 +-0 + -0 = -0 +-0 - -0 = 0 +1 + 1 = 2 +1 - 1 = 0 +1 + -1 = 0 +1 - -1 = 2 +0 * 0 = 0 +0 * -0 = -0 +-0 * 0 = -0 +-0 * -0 = 0 +Constant expression 1 + DBL_MIN = 1 +Variable expression 1 + DBL_MIN = 1 +Constant expression 1 - DBL_MIN = 1 +Variable expression 1 - DBL_MIN = 1 +1/3 in float : 0x1.555556p-2 +1/3 in double : 0x1.5555555555555p-2 +1/3 in long double : 0x1.5555555555555p-2 +Dec 1.1 = 0x1.199999999999ap+0 +FLT_MAX = 0x1.fffffep+127 +DBL_MAX = 0x1.fffffffffffffp+1023 +LDBL_MAX = 0x1.fffffffffffffp+1023 +FLT_EPSILON = 0x1p-23 +DBL_EPSILON = 0x1p-52 +LDBL_EPSILON = 0x1p-52 +pow(nan, nan) = nan +pow(nan, inf) = nan +pow(nan, -inf) = nan +pow(nan, 0) = 1 +pow(nan, -0) = 1 +pow(nan, 0.5) = nan +pow(nan, -0.5) = nan +pow(nan, 1) = nan +pow(nan, -1) = nan +pow(nan, 2) = nan +pow(nan, -2) = nan +pow(inf, nan) = nan +pow(inf, inf) = inf +pow(inf, -inf) = 0 +pow(inf, 0) = 1 +pow(inf, -0) = 1 +pow(inf, 0.5) = inf +pow(inf, -0.5) = 0 +pow(inf, 1) = inf +pow(inf, -1) = 0 +pow(inf, 2) = inf +pow(inf, -2) = 0 +pow(-inf, nan) = nan +pow(-inf, inf) = inf +pow(-inf, -inf) = 0 +pow(-inf, 0) = 1 +pow(-inf, -0) = 1 +pow(-inf, 0.5) = inf +pow(-inf, -0.5) = 0 +pow(-inf, 1) = -inf +pow(-inf, -1) = -0 +pow(-inf, 2) = inf +pow(-inf, -2) = 0 +pow(0, nan) = nan +pow(0, inf) = 0 +pow(0, -inf) = inf +pow(0, 0) = 1 +pow(0, -0) = 1 +pow(0, 0.5) = 0 +pow(0, -0.5) = inf +pow(0, 1) = 0 +pow(0, -1) = inf +pow(0, 2) = 0 +pow(0, -2) = inf +pow(-0, nan) = nan +pow(-0, inf) = 0 +pow(-0, -inf) = inf +pow(-0, 0) = 1 +pow(-0, -0) = 1 +pow(-0, 0.5) = 0 +pow(-0, -0.5) = inf +pow(-0, 1) = -0 +pow(-0, -1) = -inf +pow(-0, 2) = 0 +pow(-0, -2) = inf +pow(0.5, nan) = nan +pow(0.5, inf) = 0 +pow(0.5, -inf) = inf +pow(0.5, 0) = 1 +pow(0.5, -0) = 1 +pow(0.5, 0.5) = 0.707107 +pow(0.5, -0.5) = 1.41421 +pow(0.5, 1) = 0.5 +pow(0.5, -1) = 2 +pow(0.5, 2) = 0.25 +pow(0.5, -2) = 4 +pow(-0.5, nan) = nan +pow(-0.5, inf) = 0 +pow(-0.5, -inf) = inf +pow(-0.5, 0) = 1 +pow(-0.5, -0) = 1 +pow(-0.5, 0.5) = nan +pow(-0.5, -0.5) = nan +pow(-0.5, 1) = -0.5 +pow(-0.5, -1) = -2 +pow(-0.5, 2) = 0.25 +pow(-0.5, -2) = 4 +pow(1, nan) = nan +pow(1, inf) = nan +pow(1, -inf) = nan +pow(1, 0) = 1 +pow(1, -0) = 1 +pow(1, 0.5) = 1 +pow(1, -0.5) = 1 +pow(1, 1) = 1 +pow(1, -1) = 1 +pow(1, 2) = 1 +pow(1, -2) = 1 +pow(-1, nan) = nan +pow(-1, inf) = nan +pow(-1, -inf) = nan +pow(-1, 0) = 1 +pow(-1, -0) = 1 +pow(-1, 0.5) = nan +pow(-1, -0.5) = nan +pow(-1, 1) = -1 +pow(-1, -1) = -1 +pow(-1, 2) = 1 +pow(-1, -2) = 1 +pow(2, nan) = nan +pow(2, inf) = inf +pow(2, -inf) = 0 +pow(2, 0) = 1 +pow(2, -0) = 1 +pow(2, 0.5) = 1.41421 +pow(2, -0.5) = 0.707107 +pow(2, 1) = 2 +pow(2, -1) = 0.5 +pow(2, 2) = 4 +pow(2, -2) = 0.25 +pow(-2, nan) = nan +pow(-2, inf) = inf +pow(-2, -inf) = 0 +pow(-2, 0) = 1 +pow(-2, -0) = 1 +pow(-2, 0.5) = nan +pow(-2, -0.5) = nan +pow(-2, 1) = -2 +pow(-2, -1) = -0.5 +pow(-2, 2) = 4 +pow(-2, -2) = 0.25 + +Rounding toward 0 +Error + +Rounding to -oo +Error + +Rounding to +oo +Error +} + +set reference_output_x86_64 { +FLT_RADIX = 2 +FLT_MANT_DIG = 24 +DBL_MANT_DIG = 53 +LDBL_MANT_DIG = 64 + +FLT_MIN_EXP = -125 +DBL_MIN_EXP = -1021 +LDBL_MIN_EXP = -16381 + +FLT_MAX_EXP = 128 +DBL_MAX_EXP = 1024 +LDBL_MAX_EXP = 16384 + +FLT_EPSILON = 1.19209e-07 = 0x1p-23 +DBL_EPSILON = 2.22045e-16 = 0x1p-52 +LDBL_EPSILON = 1.0842e-19 = 0x1p-63 + +FLT_MIN = 1.17549e-38 = 0x1p-126 +DBL_MIN = 2.22507e-308 = 0x1p-1022 +LDBL_MIN = 3.3621e-4932 = 0x1p-16382 + +FLT_MAX = 3.40282e+38 = 0x1.fffffep+127 +DBL_MAX = 1.79769e+308 = 0x1.fffffffffffffp+1023 +LDBL_MAX = 1.18973e+4932 = 0x1.fffffffffffffffep+16383 + +sizeof(float) = 4 +sizeof(double) = 8 +sizeof(long double) = 16 + +x + y, with x = 9007199254740994.0 and y = 1.0 - 1/65536.0 (type double). +The IEEE-754 result is 9007199254740994 with double precision. +The IEEE-754 result is 9007199254740996 with extended precision. +The obtained result is 9007199254740994. + +NAN != NAN --> 1 (should be 1) +isnan(NAN) --> 1 (should be 1) +NAN >= 0.0 --> 0 (should be 0) +NAN <= 0.0 --> 0 (should be 0) + #3||#4 --> 0 (should be 0) +!(#3||#4) --> 1 (should be 1) + #3 + #4 --> 0 (should be 0) +!(#3 + #4) --> 1 (should be 1) +The FE_INVALID flag is not set for NAN >= 0. +The FE_INVALID flag is not set for NAN <= 0. +The FE_INVALID flag is not set for NAN > 0. +The FE_INVALID flag is not set for NAN < 0. + +x * y + z with FP_CONTRACT OFF is not fused. + +Rounding to nearest +(double) 0 = 0 +Signed zero tests (x is 0.0 and y is -0.0): + Test 1.0 / x != 1.0 / y returns 1 (should be 1). + Test 1.0 / x == 1.0 / +x returns 1 (should be 1). + Test 1.0 / x != 1.0 / +y returns 1 (should be 1). + Test 1.0 / x != 1.0 / -x returns 1 (should be 1). + Test 1.0 / x == 1.0 / -y returns 1 (should be 1). +0 + 0 = 0 +0 - 0 = 0 +0 + -0 = 0 +0 - -0 = 0 +-0 + 0 = 0 +-0 - 0 = -0 +-0 + -0 = -0 +-0 - -0 = 0 +1 + 1 = 2 +1 - 1 = 0 +1 + -1 = 0 +1 - -1 = 2 +0 * 0 = 0 +0 * -0 = -0 +-0 * 0 = -0 +-0 * -0 = 0 +Constant expression 1 + DBL_MIN = 1 +Variable expression 1 + DBL_MIN = 1 +Constant expression 1 - DBL_MIN = 1 +Variable expression 1 - DBL_MIN = 1 +1/3 in float : 0x1.555556p-2 +1/3 in double : 0x1.5555555555555p-2 +1/3 in long double : 0x1.5555555555555556p-2 +Dec 1.1 = 0x1.199999999999ap+0 +FLT_MAX = 0x1.fffffep+127 +DBL_MAX = 0x1.fffffffffffffp+1023 +LDBL_MAX = 0x1.fffffffffffffffep+16383 +FLT_EPSILON = 0x1p-23 +DBL_EPSILON = 0x1p-52 +LDBL_EPSILON = 0x1p-63 +pow(nan, nan) = nan +pow(nan, inf) = nan +pow(nan, -inf) = nan +pow(nan, 0) = 1 +pow(nan, -0) = 1 +pow(nan, 0.5) = nan +pow(nan, -0.5) = nan +pow(nan, 1) = nan +pow(nan, -1) = nan +pow(nan, 2) = nan +pow(nan, -2) = nan +pow(inf, nan) = nan +pow(inf, inf) = inf +pow(inf, -inf) = 0 +pow(inf, 0) = 1 +pow(inf, -0) = 1 +pow(inf, 0.5) = inf +pow(inf, -0.5) = 0 +pow(inf, 1) = inf +pow(inf, -1) = 0 +pow(inf, 2) = inf +pow(inf, -2) = 0 +pow(-inf, nan) = nan +pow(-inf, inf) = inf +pow(-inf, -inf) = 0 +pow(-inf, 0) = 1 +pow(-inf, -0) = 1 +pow(-inf, 0.5) = inf +pow(-inf, -0.5) = 0 +pow(-inf, 1) = -inf +pow(-inf, -1) = -0 +pow(-inf, 2) = inf +pow(-inf, -2) = 0 +pow(0, nan) = nan +pow(0, inf) = 0 +pow(0, -inf) = inf +pow(0, 0) = 1 +pow(0, -0) = 1 +pow(0, 0.5) = 0 +pow(0, -0.5) = inf +pow(0, 1) = 0 +pow(0, -1) = inf +pow(0, 2) = 0 +pow(0, -2) = inf +pow(-0, nan) = nan +pow(-0, inf) = 0 +pow(-0, -inf) = inf +pow(-0, 0) = 1 +pow(-0, -0) = 1 +pow(-0, 0.5) = 0 +pow(-0, -0.5) = inf +pow(-0, 1) = -0 +pow(-0, -1) = -inf +pow(-0, 2) = 0 +pow(-0, -2) = inf +pow(0.5, nan) = nan +pow(0.5, inf) = 0 +pow(0.5, -inf) = inf +pow(0.5, 0) = 1 +pow(0.5, -0) = 1 +pow(0.5, 0.5) = 0.707107 +pow(0.5, -0.5) = 1.41421 +pow(0.5, 1) = 0.5 +pow(0.5, -1) = 2 +pow(0.5, 2) = 0.25 +pow(0.5, -2) = 4 +pow(-0.5, nan) = nan +pow(-0.5, inf) = 0 +pow(-0.5, -inf) = inf +pow(-0.5, 0) = 1 +pow(-0.5, -0) = 1 +pow(-0.5, 0.5) = nan +pow(-0.5, -0.5) = nan +pow(-0.5, 1) = -0.5 +pow(-0.5, -1) = -2 +pow(-0.5, 2) = 0.25 +pow(-0.5, -2) = 4 +pow(1, nan) = nan +pow(1, inf) = nan +pow(1, -inf) = nan +pow(1, 0) = 1 +pow(1, -0) = 1 +pow(1, 0.5) = 1 +pow(1, -0.5) = 1 +pow(1, 1) = 1 +pow(1, -1) = 1 +pow(1, 2) = 1 +pow(1, -2) = 1 +pow(-1, nan) = nan +pow(-1, inf) = nan +pow(-1, -inf) = nan +pow(-1, 0) = 1 +pow(-1, -0) = 1 +pow(-1, 0.5) = nan +pow(-1, -0.5) = nan +pow(-1, 1) = -1 +pow(-1, -1) = -1 +pow(-1, 2) = 1 +pow(-1, -2) = 1 +pow(2, nan) = nan +pow(2, inf) = inf +pow(2, -inf) = 0 +pow(2, 0) = 1 +pow(2, -0) = 1 +pow(2, 0.5) = 1.41421 +pow(2, -0.5) = 0.707107 +pow(2, 1) = 2 +pow(2, -1) = 0.5 +pow(2, 2) = 4 +pow(2, -2) = 0.25 +pow(-2, nan) = nan +pow(-2, inf) = inf +pow(-2, -inf) = 0 +pow(-2, 0) = 1 +pow(-2, -0) = 1 +pow(-2, 0.5) = nan +pow(-2, -0.5) = nan +pow(-2, 1) = -2 +pow(-2, -1) = -0.5 +pow(-2, 2) = 4 +pow(-2, -2) = 0.25 + +Rounding toward 0 +(double) 0 = 0 +Signed zero tests (x is 0.0 and y is -0.0): + Test 1.0 / x != 1.0 / y returns 1 (should be 1). + Test 1.0 / x == 1.0 / +x returns 1 (should be 1). + Test 1.0 / x != 1.0 / +y returns 1 (should be 1). + Test 1.0 / x != 1.0 / -x returns 1 (should be 1). + Test 1.0 / x == 1.0 / -y returns 1 (should be 1). +0 + 0 = 0 +0 - 0 = 0 +0 + -0 = 0 +0 - -0 = 0 +-0 + 0 = 0 +-0 - 0 = -0 +-0 + -0 = -0 +-0 - -0 = 0 +1 + 1 = 2 +1 - 1 = 0 +1 + -1 = 0 +1 - -1 = 2 +0 * 0 = 0 +0 * -0 = -0 +-0 * 0 = -0 +-0 * -0 = 0 +Constant expression 1 + DBL_MIN = 1 +Variable expression 1 + DBL_MIN = 1 +Constant expression 1 - DBL_MIN = 1 +Variable expression 1 - DBL_MIN = 0.99999999999999988897 +1/3 in float : 0x1.555554p-2 +1/3 in double : 0x1.5555555555555p-2 +1/3 in long double : 0x1.5555555555555554p-2 +Dec 1.1 = 0x1.199999999999ap+0 +FLT_MAX = 0x1.fffffep+127 +DBL_MAX = 0x1.fffffffffffffp+1023 +LDBL_MAX = 0x1.fffffffffffffffep+16383 +FLT_EPSILON = 0x1p-23 +DBL_EPSILON = 0x1p-52 +LDBL_EPSILON = 0x1p-63 +pow(nan, nan) = nan +pow(nan, inf) = nan +pow(nan, -inf) = nan +pow(nan, 0) = 1 +pow(nan, -0) = 1 +pow(nan, 0.5) = nan +pow(nan, -0.5) = nan +pow(nan, 1) = nan +pow(nan, -1) = nan +pow(nan, 2) = nan +pow(nan, -2) = nan +pow(inf, nan) = nan +pow(inf, inf) = inf +pow(inf, -inf) = 0 +pow(inf, 0) = 1 +pow(inf, -0) = 1 +pow(inf, 0.5) = inf +pow(inf, -0.5) = 0 +pow(inf, 1) = inf +pow(inf, -1) = 0 +pow(inf, 2) = inf +pow(inf, -2) = 0 +pow(-inf, nan) = nan +pow(-inf, inf) = inf +pow(-inf, -inf) = 0 +pow(-inf, 0) = 1 +pow(-inf, -0) = 1 +pow(-inf, 0.5) = inf +pow(-inf, -0.5) = 0 +pow(-inf, 1) = -inf +pow(-inf, -1) = -0 +pow(-inf, 2) = inf +pow(-inf, -2) = 0 +pow(0, nan) = nan +pow(0, inf) = 0 +pow(0, -inf) = inf +pow(0, 0) = 1 +pow(0, -0) = 1 +pow(0, 0.5) = 0 +pow(0, -0.5) = inf +pow(0, 1) = 0 +pow(0, -1) = inf +pow(0, 2) = 0 +pow(0, -2) = inf +pow(-0, nan) = nan +pow(-0, inf) = 0 +pow(-0, -inf) = inf +pow(-0, 0) = 1 +pow(-0, -0) = 1 +pow(-0, 0.5) = 0 +pow(-0, -0.5) = inf +pow(-0, 1) = -0 +pow(-0, -1) = -inf +pow(-0, 2) = 0 +pow(-0, -2) = inf +pow(0.5, nan) = nan +pow(0.5, inf) = 0 +pow(0.5, -inf) = inf +pow(0.5, 0) = 1 +pow(0.5, -0) = 1 +pow(0.5, 0.5) = 0.707106 +pow(0.5, -0.5) = 1.41421 +pow(0.5, 1) = 0.5 +pow(0.5, -1) = 2 +pow(0.5, 2) = 0.25 +pow(0.5, -2) = 4 +pow(-0.5, nan) = nan +pow(-0.5, inf) = 0 +pow(-0.5, -inf) = inf +pow(-0.5, 0) = 1 +pow(-0.5, -0) = 1 +pow(-0.5, 0.5) = nan +pow(-0.5, -0.5) = nan +pow(-0.5, 1) = -0.5 +pow(-0.5, -1) = -2 +pow(-0.5, 2) = 0.25 +pow(-0.5, -2) = 4 +pow(1, nan) = nan +pow(1, inf) = nan +pow(1, -inf) = nan +pow(1, 0) = 1 +pow(1, -0) = 1 +pow(1, 0.5) = 1 +pow(1, -0.5) = 1 +pow(1, 1) = 1 +pow(1, -1) = 1 +pow(1, 2) = 1 +pow(1, -2) = 1 +pow(-1, nan) = nan +pow(-1, inf) = nan +pow(-1, -inf) = nan +pow(-1, 0) = 1 +pow(-1, -0) = 1 +pow(-1, 0.5) = nan +pow(-1, -0.5) = nan +pow(-1, 1) = -1 +pow(-1, -1) = -1 +pow(-1, 2) = 1 +pow(-1, -2) = 1 +pow(2, nan) = nan +pow(2, inf) = inf +pow(2, -inf) = 0 +pow(2, 0) = 1 +pow(2, -0) = 1 +pow(2, 0.5) = 1.41421 +pow(2, -0.5) = 0.707106 +pow(2, 1) = 2 +pow(2, -1) = 0.5 +pow(2, 2) = 4 +pow(2, -2) = 0.25 +pow(-2, nan) = nan +pow(-2, inf) = inf +pow(-2, -inf) = 0 +pow(-2, 0) = 1 +pow(-2, -0) = 1 +pow(-2, 0.5) = nan +pow(-2, -0.5) = nan +pow(-2, 1) = -2 +pow(-2, -1) = -0.5 +pow(-2, 2) = 4 +pow(-2, -2) = 0.25 + +Rounding to -oo +(double) 0 = 0 +Signed zero tests (x is 0.0 and y is -0.0): + Test 1.0 / x != 1.0 / y returns 1 (should be 1). + Test 1.0 / x == 1.0 / +x returns 1 (should be 1). + Test 1.0 / x != 1.0 / +y returns 1 (should be 1). + Test 1.0 / x != 1.0 / -x returns 1 (should be 1). + Test 1.0 / x == 1.0 / -y returns 1 (should be 1). +0 + 0 = 0 +0 - 0 = -0 +0 + -0 = -0 +0 - -0 = 0 +-0 + 0 = -0 +-0 - 0 = -0 +-0 + -0 = -0 +-0 - -0 = -0 +1 + 1 = 2 +1 - 1 = -0 +1 + -1 = -0 +1 - -1 = 2 +0 * 0 = 0 +0 * -0 = -0 +-0 * 0 = -0 +-0 * -0 = 0 +Constant expression 1 + DBL_MIN = 1 +Variable expression 1 + DBL_MIN = 1 +Constant expression 1 - DBL_MIN = 1 +Variable expression 1 - DBL_MIN = 0.99999999999999988897 +1/3 in float : 0x1.555554p-2 +1/3 in double : 0x1.5555555555555p-2 +1/3 in long double : 0x1.5555555555555554p-2 +Dec 1.1 = 0x1.199999999999ap+0 +FLT_MAX = 0x1.fffffep+127 +DBL_MAX = 0x1.fffffffffffffp+1023 +LDBL_MAX = 0x1.fffffffffffffffep+16383 +FLT_EPSILON = 0x1p-23 +DBL_EPSILON = 0x1p-52 +LDBL_EPSILON = 0x1p-63 +pow(nan, nan) = nan +pow(nan, inf) = nan +pow(nan, -inf) = nan +pow(nan, 0) = 1 +pow(nan, -0) = 1 +pow(nan, 0.5) = nan +pow(nan, -0.5) = nan +pow(nan, 1) = nan +pow(nan, -1) = nan +pow(nan, 2) = nan +pow(nan, -2) = nan +pow(inf, nan) = nan +pow(inf, inf) = inf +pow(inf, -inf) = 0 +pow(inf, 0) = 1 +pow(inf, -0) = 1 +pow(inf, 0.5) = inf +pow(inf, -0.5) = 0 +pow(inf, 1) = inf +pow(inf, -1) = 0 +pow(inf, 2) = inf +pow(inf, -2) = 0 +pow(-inf, nan) = nan +pow(-inf, inf) = inf +pow(-inf, -inf) = 0 +pow(-inf, 0) = 1 +pow(-inf, -0) = 1 +pow(-inf, 0.5) = inf +pow(-inf, -0.5) = 0 +pow(-inf, 1) = -inf +pow(-inf, -1) = -0 +pow(-inf, 2) = inf +pow(-inf, -2) = 0 +pow(0, nan) = nan +pow(0, inf) = 0 +pow(0, -inf) = inf +pow(0, 0) = 1 +pow(0, -0) = 1 +pow(0, 0.5) = 0 +pow(0, -0.5) = inf +pow(0, 1) = 0 +pow(0, -1) = inf +pow(0, 2) = 0 +pow(0, -2) = inf +pow(-0, nan) = nan +pow(-0, inf) = 0 +pow(-0, -inf) = inf +pow(-0, 0) = 1 +pow(-0, -0) = 1 +pow(-0, 0.5) = 0 +pow(-0, -0.5) = inf +pow(-0, 1) = -0 +pow(-0, -1) = -inf +pow(-0, 2) = 0 +pow(-0, -2) = inf +pow(0.5, nan) = nan +pow(0.5, inf) = 0 +pow(0.5, -inf) = inf +pow(0.5, 0) = 1 +pow(0.5, -0) = 1 +pow(0.5, 0.5) = 0.707106 +pow(0.5, -0.5) = 1.41421 +pow(0.5, 1) = 0.5 +pow(0.5, -1) = 2 +pow(0.5, 2) = 0.25 +pow(0.5, -2) = 4 +pow(-0.5, nan) = nan +pow(-0.5, inf) = 0 +pow(-0.5, -inf) = inf +pow(-0.5, 0) = 1 +pow(-0.5, -0) = 1 +pow(-0.5, 0.5) = nan +pow(-0.5, -0.5) = nan +pow(-0.5, 1) = -0.5 +pow(-0.5, -1) = -2 +pow(-0.5, 2) = 0.25 +pow(-0.5, -2) = 4 +pow(1, nan) = nan +pow(1, inf) = nan +pow(1, -inf) = nan +pow(1, 0) = 1 +pow(1, -0) = 1 +pow(1, 0.5) = 1 +pow(1, -0.5) = 1 +pow(1, 1) = 1 +pow(1, -1) = 1 +pow(1, 2) = 1 +pow(1, -2) = 1 +pow(-1, nan) = nan +pow(-1, inf) = nan +pow(-1, -inf) = nan +pow(-1, 0) = 1 +pow(-1, -0) = 1 +pow(-1, 0.5) = nan +pow(-1, -0.5) = nan +pow(-1, 1) = -1 +pow(-1, -1) = -1 +pow(-1, 2) = 1 +pow(-1, -2) = 1 +pow(2, nan) = nan +pow(2, inf) = inf +pow(2, -inf) = 0 +pow(2, 0) = 1 +pow(2, -0) = 1 +pow(2, 0.5) = 1.41421 +pow(2, -0.5) = 0.707106 +pow(2, 1) = 2 +pow(2, -1) = 0.5 +pow(2, 2) = 4 +pow(2, -2) = 0.25 +pow(-2, nan) = nan +pow(-2, inf) = inf +pow(-2, -inf) = 0 +pow(-2, 0) = 1 +pow(-2, -0) = 1 +pow(-2, 0.5) = nan +pow(-2, -0.5) = nan +pow(-2, 1) = -2 +pow(-2, -1) = -0.5 +pow(-2, 2) = 4 +pow(-2, -2) = 0.25 + +Rounding to +oo +(double) 0 = 0 +Signed zero tests (x is 0.0 and y is -0.0): + Test 1.0 / x != 1.0 / y returns 1 (should be 1). + Test 1.0 / x == 1.0 / +x returns 1 (should be 1). + Test 1.0 / x != 1.0 / +y returns 1 (should be 1). + Test 1.0 / x != 1.0 / -x returns 1 (should be 1). + Test 1.0 / x == 1.0 / -y returns 1 (should be 1). +0 + 0 = 0 +0 - 0 = 0 +0 + -0 = 0 +0 - -0 = 0 +-0 + 0 = 0 +-0 - 0 = -0 +-0 + -0 = -0 +-0 - -0 = 0 +1 + 1 = 2 +1 - 1 = 0 +1 + -1 = 0 +1 - -1 = 2 +0 * 0 = 0 +0 * -0 = -0 +-0 * 0 = -0 +-0 * -0 = 0 +Constant expression 1 + DBL_MIN = 1 +Variable expression 1 + DBL_MIN = 1.0000000000000002221 +Constant expression 1 - DBL_MIN = 1 +Variable expression 1 - DBL_MIN = 1 +1/3 in float : 0x1.555556p-2 +1/3 in double : 0x1.5555555555556p-2 +1/3 in long double : 0x1.5555555555555556p-2 +Dec 1.1 = 0x1.199999999999ap+0 +FLT_MAX = 0x1.fffffep+127 +DBL_MAX = 0x1.fffffffffffffp+1023 +LDBL_MAX = 0x1.fffffffffffffffep+16383 +FLT_EPSILON = 0x1p-23 +DBL_EPSILON = 0x1p-52 +LDBL_EPSILON = 0x1p-63 +pow(nan, nan) = nan +pow(nan, inf) = nan +pow(nan, -inf) = nan +pow(nan, 0) = 1 +pow(nan, -0) = 1 +pow(nan, 0.5) = nan +pow(nan, -0.5) = nan +pow(nan, 1) = nan +pow(nan, -1) = nan +pow(nan, 2) = nan +pow(nan, -2) = nan +pow(inf, nan) = nan +pow(inf, inf) = inf +pow(inf, -inf) = 0 +pow(inf, 0) = 1 +pow(inf, -0) = 1 +pow(inf, 0.5) = inf +pow(inf, -0.5) = 0 +pow(inf, 1) = inf +pow(inf, -1) = 0 +pow(inf, 2) = inf +pow(inf, -2) = 0 +pow(-inf, nan) = nan +pow(-inf, inf) = inf +pow(-inf, -inf) = 0 +pow(-inf, 0) = 1 +pow(-inf, -0) = 1 +pow(-inf, 0.5) = inf +pow(-inf, -0.5) = 0 +pow(-inf, 1) = -inf +pow(-inf, -1) = -0 +pow(-inf, 2) = inf +pow(-inf, -2) = 0 +pow(0, nan) = nan +pow(0, inf) = 0 +pow(0, -inf) = inf +pow(0, 0) = 1 +pow(0, -0) = 1 +pow(0, 0.5) = 0 +pow(0, -0.5) = inf +pow(0, 1) = 0 +pow(0, -1) = inf +pow(0, 2) = 0 +pow(0, -2) = inf +pow(-0, nan) = nan +pow(-0, inf) = 0 +pow(-0, -inf) = inf +pow(-0, 0) = 1 +pow(-0, -0) = 1 +pow(-0, 0.5) = 0 +pow(-0, -0.5) = inf +pow(-0, 1) = -0 +pow(-0, -1) = -inf +pow(-0, 2) = 0 +pow(-0, -2) = inf +pow(0.5, nan) = nan +pow(0.5, inf) = 0 +pow(0.5, -inf) = inf +pow(0.5, 0) = 1 +pow(0.5, -0) = 1 +pow(0.5, 0.5) = 0.707107 +pow(0.5, -0.5) = 1.41422 +pow(0.5, 1) = 0.5 +pow(0.5, -1) = 2 +pow(0.5, 2) = 0.25 +pow(0.5, -2) = 4 +pow(-0.5, nan) = nan +pow(-0.5, inf) = 0 +pow(-0.5, -inf) = inf +pow(-0.5, 0) = 1 +pow(-0.5, -0) = 1 +pow(-0.5, 0.5) = nan +pow(-0.5, -0.5) = nan +pow(-0.5, 1) = -0.5 +pow(-0.5, -1) = -2 +pow(-0.5, 2) = 0.25 +pow(-0.5, -2) = 4 +pow(1, nan) = nan +pow(1, inf) = nan +pow(1, -inf) = nan +pow(1, 0) = 1 +pow(1, -0) = 1 +pow(1, 0.5) = 1 +pow(1, -0.5) = 1 +pow(1, 1) = 1 +pow(1, -1) = 1 +pow(1, 2) = 1 +pow(1, -2) = 1 +pow(-1, nan) = nan +pow(-1, inf) = nan +pow(-1, -inf) = nan +pow(-1, 0) = 1 +pow(-1, -0) = 1 +pow(-1, 0.5) = nan +pow(-1, -0.5) = nan +pow(-1, 1) = -1 +pow(-1, -1) = -1 +pow(-1, 2) = 1 +pow(-1, -2) = 1 +pow(2, nan) = nan +pow(2, inf) = inf +pow(2, -inf) = 0 +pow(2, 0) = 1 +pow(2, -0) = 1 +pow(2, 0.5) = 1.41422 +pow(2, -0.5) = 0.707107 +pow(2, 1) = 2 +pow(2, -1) = 0.5 +pow(2, 2) = 4 +pow(2, -2) = 0.25 +pow(-2, nan) = nan +pow(-2, inf) = inf +pow(-2, -inf) = 0 +pow(-2, 0) = 1 +pow(-2, -0) = 1 +pow(-2, 0.5) = nan +pow(-2, -0.5) = nan +pow(-2, 1) = -2 +pow(-2, -1) = -0.5 +pow(-2, 2) = 4 +pow(-2, -2) = 0.25 +} + +set reference_output_x86_32 { +FLT_RADIX = 2 +FLT_MANT_DIG = 24 +DBL_MANT_DIG = 53 +LDBL_MANT_DIG = 64 + +FLT_MIN_EXP = -125 +DBL_MIN_EXP = -1021 +LDBL_MIN_EXP = -16381 + +FLT_MAX_EXP = 128 +DBL_MAX_EXP = 1024 +LDBL_MAX_EXP = 16384 + +FLT_EPSILON = 1.19209e-07 = 0x1p-23 + (dynamic epsilon = 1.0842e-19 = 0x1p-63) +DBL_EPSILON = 2.22045e-16 = 0x1p-52 + (dynamic epsilon = 1.0842e-19 = 0x1p-63) +LDBL_EPSILON = 1.0842e-19 = 0x1p-63 + +FLT_MIN = 1.17549e-38 = 0x1p-126 +DBL_MIN = 2.22507e-308 = 0x1p-1022 +LDBL_MIN = 3.3621e-4932 = 0x1p-16382 + +FLT_MAX = 3.40282e+38 = 0x1.fffffep+127 +DBL_MAX = 1.79769e+308 = 0x1.fffffffffffffp+1023 +LDBL_MAX = 1.18973e+4932 = 0x1.fffffffffffffffep+16383 + +sizeof(float) = 4 +sizeof(double) = 8 +sizeof(long double) = 12 + +x + y, with x = 9007199254740994.0 and y = 1.0 - 1/65536.0 (type double). +The IEEE-754 result is 9007199254740994 with double precision. +The IEEE-754 result is 9007199254740996 with extended precision. +The obtained result is 9007199254740996. + +BUG: +The implementation doesn't seem to convert values to the target type after +an assignment (see ISO/IEC 9899: 5.1.2.3#12, 6.3.1.5#2 and 6.3.1.8#2[52]). + +NAN != NAN --> 1 (should be 1) +isnan(NAN) --> 1 (should be 1) +NAN >= 0.0 --> 0 (should be 0) +NAN <= 0.0 --> 0 (should be 0) + #3||#4 --> 0 (should be 0) +!(#3||#4) --> 1 (should be 1) + #3 + #4 --> 0 (should be 0) +!(#3 + #4) --> 1 (should be 1) +The FE_INVALID flag is not set for NAN >= 0. +The FE_INVALID flag is not set for NAN <= 0. +The FE_INVALID flag is not set for NAN > 0. +The FE_INVALID flag is not set for NAN < 0. + +x * y + z with FP_CONTRACT OFF is not fused. + +Rounding to nearest +(double) 0 = 0 +Signed zero tests (x is 0.0 and y is -0.0): + Test 1.0 / x != 1.0 / y returns 1 (should be 1). + Test 1.0 / x == 1.0 / +x returns 1 (should be 1). + Test 1.0 / x != 1.0 / +y returns 1 (should be 1). + Test 1.0 / x != 1.0 / -x returns 1 (should be 1). + Test 1.0 / x == 1.0 / -y returns 1 (should be 1). +0 + 0 = 0 +0 - 0 = 0 +0 + -0 = 0 +0 - -0 = 0 +-0 + 0 = 0 +-0 - 0 = -0 +-0 + -0 = -0 +-0 - -0 = 0 +1 + 1 = 2 +1 - 1 = 0 +1 + -1 = 0 +1 - -1 = 2 +0 * 0 = 0 +0 * -0 = -0 +-0 * 0 = -0 +-0 * -0 = 0 +Constant expression 1 + DBL_MIN = 1 +Variable expression 1 + DBL_MIN = 1 +Constant expression 1 - DBL_MIN = 1 +Variable expression 1 - DBL_MIN = 1 +1/3 in float : 0x1.555556p-2 +1/3 in double : 0x1.5555555555555p-2 +1/3 in long double : 0x1.5555555555555556p-2 +Dec 1.1 = 0x1.199999999999ap+0 +FLT_MAX = 0x1.fffffep+127 +DBL_MAX = 0x1.fffffffffffffp+1023 +LDBL_MAX = 0x1.fffffffffffffffep+16383 +FLT_EPSILON = 0x1p-23 +DBL_EPSILON = 0x1p-52 +LDBL_EPSILON = 0x1p-63 +pow(nan, nan) = nan +pow(nan, inf) = nan +pow(nan, -inf) = nan +pow(nan, 0) = 1 +pow(nan, -0) = 1 +pow(nan, 0.5) = nan +pow(nan, -0.5) = nan +pow(nan, 1) = nan +pow(nan, -1) = nan +pow(nan, 2) = nan +pow(nan, -2) = nan +pow(inf, nan) = nan +pow(inf, inf) = inf +pow(inf, -inf) = 0 +pow(inf, 0) = 1 +pow(inf, -0) = 1 +pow(inf, 0.5) = inf +pow(inf, -0.5) = 0 +pow(inf, 1) = inf +pow(inf, -1) = 0 +pow(inf, 2) = inf +pow(inf, -2) = 0 +pow(-inf, nan) = nan +pow(-inf, inf) = inf +pow(-inf, -inf) = 0 +pow(-inf, 0) = 1 +pow(-inf, -0) = 1 +pow(-inf, 0.5) = inf +pow(-inf, -0.5) = 0 +pow(-inf, 1) = -inf +pow(-inf, -1) = -0 +pow(-inf, 2) = inf +pow(-inf, -2) = 0 +pow(0, nan) = nan +pow(0, inf) = 0 +pow(0, -inf) = inf +pow(0, 0) = 1 +pow(0, -0) = 1 +pow(0, 0.5) = 0 +pow(0, -0.5) = inf +pow(0, 1) = 0 +pow(0, -1) = inf +pow(0, 2) = 0 +pow(0, -2) = inf +pow(-0, nan) = nan +pow(-0, inf) = 0 +pow(-0, -inf) = inf +pow(-0, 0) = 1 +pow(-0, -0) = 1 +pow(-0, 0.5) = 0 +pow(-0, -0.5) = inf +pow(-0, 1) = -0 +pow(-0, -1) = -inf +pow(-0, 2) = 0 +pow(-0, -2) = inf +pow(0.5, nan) = nan +pow(0.5, inf) = 0 +pow(0.5, -inf) = inf +pow(0.5, 0) = 1 +pow(0.5, -0) = 1 +pow(0.5, 0.5) = 0.707107 +pow(0.5, -0.5) = 1.41421 +pow(0.5, 1) = 0.5 +pow(0.5, -1) = 2 +pow(0.5, 2) = 0.25 +pow(0.5, -2) = 4 +pow(-0.5, nan) = nan +pow(-0.5, inf) = 0 +pow(-0.5, -inf) = inf +pow(-0.5, 0) = 1 +pow(-0.5, -0) = 1 +pow(-0.5, 0.5) = nan +pow(-0.5, -0.5) = nan +pow(-0.5, 1) = -0.5 +pow(-0.5, -1) = -2 +pow(-0.5, 2) = 0.25 +pow(-0.5, -2) = 4 +pow(1, nan) = nan +pow(1, inf) = nan +pow(1, -inf) = nan +pow(1, 0) = 1 +pow(1, -0) = 1 +pow(1, 0.5) = 1 +pow(1, -0.5) = 1 +pow(1, 1) = 1 +pow(1, -1) = 1 +pow(1, 2) = 1 +pow(1, -2) = 1 +pow(-1, nan) = nan +pow(-1, inf) = nan +pow(-1, -inf) = nan +pow(-1, 0) = 1 +pow(-1, -0) = 1 +pow(-1, 0.5) = nan +pow(-1, -0.5) = nan +pow(-1, 1) = -1 +pow(-1, -1) = -1 +pow(-1, 2) = 1 +pow(-1, -2) = 1 +pow(2, nan) = nan +pow(2, inf) = inf +pow(2, -inf) = 0 +pow(2, 0) = 1 +pow(2, -0) = 1 +pow(2, 0.5) = 1.41421 +pow(2, -0.5) = 0.707107 +pow(2, 1) = 2 +pow(2, -1) = 0.5 +pow(2, 2) = 4 +pow(2, -2) = 0.25 +pow(-2, nan) = nan +pow(-2, inf) = inf +pow(-2, -inf) = 0 +pow(-2, 0) = 1 +pow(-2, -0) = 1 +pow(-2, 0.5) = nan +pow(-2, -0.5) = nan +pow(-2, 1) = -2 +pow(-2, -1) = -0.5 +pow(-2, 2) = 4 +pow(-2, -2) = 0.25 + +Rounding toward 0 +(double) 0 = 0 +Signed zero tests (x is 0.0 and y is -0.0): + Test 1.0 / x != 1.0 / y returns 1 (should be 1). + Test 1.0 / x == 1.0 / +x returns 1 (should be 1). + Test 1.0 / x != 1.0 / +y returns 1 (should be 1). + Test 1.0 / x != 1.0 / -x returns 1 (should be 1). + Test 1.0 / x == 1.0 / -y returns 1 (should be 1). +0 + 0 = 0 +0 - 0 = 0 +0 + -0 = 0 +0 - -0 = 0 +-0 + 0 = 0 +-0 - 0 = -0 +-0 + -0 = -0 +-0 - -0 = 0 +1 + 1 = 2 +1 - 1 = 0 +1 + -1 = 0 +1 - -1 = 2 +0 * 0 = 0 +0 * -0 = -0 +-0 * 0 = -0 +-0 * -0 = 0 +Constant expression 1 + DBL_MIN = 1 +Variable expression 1 + DBL_MIN = 1 +Constant expression 1 - DBL_MIN = 1 +Variable expression 1 - DBL_MIN = 0.99999999999999988897 +1/3 in float : 0x1.555554p-2 +1/3 in double : 0x1.5555555555555p-2 +1/3 in long double : 0x1.5555555555555554p-2 +Dec 1.1 = 0x1.199999999999ap+0 +FLT_MAX = 0x1.fffffep+127 +DBL_MAX = 0x1.fffffffffffffp+1023 +LDBL_MAX = 0x1.fffffffffffffffep+16383 +FLT_EPSILON = 0x1p-23 +DBL_EPSILON = 0x1p-52 +LDBL_EPSILON = 0x1p-63 +pow(nan, nan) = nan +pow(nan, inf) = nan +pow(nan, -inf) = nan +pow(nan, 0) = 1 +pow(nan, -0) = 1 +pow(nan, 0.5) = nan +pow(nan, -0.5) = nan +pow(nan, 1) = nan +pow(nan, -1) = nan +pow(nan, 2) = nan +pow(nan, -2) = nan +pow(inf, nan) = nan +pow(inf, inf) = inf +pow(inf, -inf) = 0 +pow(inf, 0) = 1 +pow(inf, -0) = 1 +pow(inf, 0.5) = inf +pow(inf, -0.5) = 0 +pow(inf, 1) = inf +pow(inf, -1) = 0 +pow(inf, 2) = inf +pow(inf, -2) = 0 +pow(-inf, nan) = nan +pow(-inf, inf) = inf +pow(-inf, -inf) = 0 +pow(-inf, 0) = 1 +pow(-inf, -0) = 1 +pow(-inf, 0.5) = inf +pow(-inf, -0.5) = 0 +pow(-inf, 1) = -inf +pow(-inf, -1) = -0 +pow(-inf, 2) = inf +pow(-inf, -2) = 0 +pow(0, nan) = nan +pow(0, inf) = 0 +pow(0, -inf) = inf +pow(0, 0) = 1 +pow(0, -0) = 1 +pow(0, 0.5) = 0 +pow(0, -0.5) = inf +pow(0, 1) = 0 +pow(0, -1) = inf +pow(0, 2) = 0 +pow(0, -2) = inf +pow(-0, nan) = nan +pow(-0, inf) = 0 +pow(-0, -inf) = inf +pow(-0, 0) = 1 +pow(-0, -0) = 1 +pow(-0, 0.5) = 0 +pow(-0, -0.5) = inf +pow(-0, 1) = -0 +pow(-0, -1) = -inf +pow(-0, 2) = 0 +pow(-0, -2) = inf +pow(0.5, nan) = nan +pow(0.5, inf) = 0 +pow(0.5, -inf) = inf +pow(0.5, 0) = 1 +pow(0.5, -0) = 1 +pow(0.5, 0.5) = 0.707106 +pow(0.5, -0.5) = 1.41421 +pow(0.5, 1) = 0.5 +pow(0.5, -1) = 2 +pow(0.5, 2) = 0.25 +pow(0.5, -2) = 4 +pow(-0.5, nan) = nan +pow(-0.5, inf) = 0 +pow(-0.5, -inf) = inf +pow(-0.5, 0) = 1 +pow(-0.5, -0) = 1 +pow(-0.5, 0.5) = nan +pow(-0.5, -0.5) = nan +pow(-0.5, 1) = -0.5 +pow(-0.5, -1) = -2 +pow(-0.5, 2) = 0.25 +pow(-0.5, -2) = 4 +pow(1, nan) = nan +pow(1, inf) = nan +pow(1, -inf) = nan +pow(1, 0) = 1 +pow(1, -0) = 1 +pow(1, 0.5) = 1 +pow(1, -0.5) = 1 +pow(1, 1) = 1 +pow(1, -1) = 1 +pow(1, 2) = 1 +pow(1, -2) = 1 +pow(-1, nan) = nan +pow(-1, inf) = nan +pow(-1, -inf) = nan +pow(-1, 0) = 1 +pow(-1, -0) = 1 +pow(-1, 0.5) = nan +pow(-1, -0.5) = nan +pow(-1, 1) = -1 +pow(-1, -1) = -1 +pow(-1, 2) = 1 +pow(-1, -2) = 1 +pow(2, nan) = nan +pow(2, inf) = inf +pow(2, -inf) = 0 +pow(2, 0) = 1 +pow(2, -0) = 1 +pow(2, 0.5) = 1.41421 +pow(2, -0.5) = 0.707106 +pow(2, 1) = 2 +pow(2, -1) = 0.5 +pow(2, 2) = 4 +pow(2, -2) = 0.25 +pow(-2, nan) = nan +pow(-2, inf) = inf +pow(-2, -inf) = 0 +pow(-2, 0) = 1 +pow(-2, -0) = 1 +pow(-2, 0.5) = nan +pow(-2, -0.5) = nan +pow(-2, 1) = -2 +pow(-2, -1) = -0.5 +pow(-2, 2) = 4 +pow(-2, -2) = 0.25 + +Rounding to -oo +(double) 0 = 0 +Signed zero tests (x is 0.0 and y is -0.0): + Test 1.0 / x != 1.0 / y returns 1 (should be 1). + Test 1.0 / x == 1.0 / +x returns 1 (should be 1). + Test 1.0 / x != 1.0 / +y returns 1 (should be 1). + Test 1.0 / x != 1.0 / -x returns 1 (should be 1). + Test 1.0 / x == 1.0 / -y returns 1 (should be 1). +0 + 0 = 0 +0 - 0 = -0 +0 + -0 = -0 +0 - -0 = 0 +-0 + 0 = -0 +-0 - 0 = -0 +-0 + -0 = -0 +-0 - -0 = -0 +1 + 1 = 2 +1 - 1 = -0 +1 + -1 = -0 +1 - -1 = 2 +0 * 0 = 0 +0 * -0 = -0 +-0 * 0 = -0 +-0 * -0 = 0 +Constant expression 1 + DBL_MIN = 1 +Variable expression 1 + DBL_MIN = 1 +Constant expression 1 - DBL_MIN = 1 +Variable expression 1 - DBL_MIN = 0.99999999999999988897 +1/3 in float : 0x1.555554p-2 +1/3 in double : 0x1.5555555555555p-2 +1/3 in long double : 0x1.5555555555555554p-2 +Dec 1.1 = 0x1.199999999999ap+0 +FLT_MAX = 0x1.fffffep+127 +DBL_MAX = 0x1.fffffffffffffp+1023 +LDBL_MAX = 0x1.fffffffffffffffep+16383 +FLT_EPSILON = 0x1p-23 +DBL_EPSILON = 0x1p-52 +LDBL_EPSILON = 0x1p-63 +pow(nan, nan) = nan +pow(nan, inf) = nan +pow(nan, -inf) = nan +pow(nan, 0) = 1 +pow(nan, -0) = 1 +pow(nan, 0.5) = nan +pow(nan, -0.5) = nan +pow(nan, 1) = nan +pow(nan, -1) = nan +pow(nan, 2) = nan +pow(nan, -2) = nan +pow(inf, nan) = nan +pow(inf, inf) = inf +pow(inf, -inf) = 0 +pow(inf, 0) = 1 +pow(inf, -0) = 1 +pow(inf, 0.5) = inf +pow(inf, -0.5) = 0 +pow(inf, 1) = inf +pow(inf, -1) = 0 +pow(inf, 2) = inf +pow(inf, -2) = 0 +pow(-inf, nan) = nan +pow(-inf, inf) = inf +pow(-inf, -inf) = 0 +pow(-inf, 0) = 1 +pow(-inf, -0) = 1 +pow(-inf, 0.5) = inf +pow(-inf, -0.5) = 0 +pow(-inf, 1) = -inf +pow(-inf, -1) = -0 +pow(-inf, 2) = inf +pow(-inf, -2) = 0 +pow(0, nan) = nan +pow(0, inf) = 0 +pow(0, -inf) = inf +pow(0, 0) = 1 +pow(0, -0) = 1 +pow(0, 0.5) = 0 +pow(0, -0.5) = inf +pow(0, 1) = 0 +pow(0, -1) = inf +pow(0, 2) = 0 +pow(0, -2) = inf +pow(-0, nan) = nan +pow(-0, inf) = 0 +pow(-0, -inf) = inf +pow(-0, 0) = 1 +pow(-0, -0) = 1 +pow(-0, 0.5) = 0 +pow(-0, -0.5) = inf +pow(-0, 1) = -0 +pow(-0, -1) = -inf +pow(-0, 2) = 0 +pow(-0, -2) = inf +pow(0.5, nan) = nan +pow(0.5, inf) = 0 +pow(0.5, -inf) = inf +pow(0.5, 0) = 1 +pow(0.5, -0) = 1 +pow(0.5, 0.5) = 0.707106 +pow(0.5, -0.5) = 1.41421 +pow(0.5, 1) = 0.5 +pow(0.5, -1) = 2 +pow(0.5, 2) = 0.25 +pow(0.5, -2) = 4 +pow(-0.5, nan) = nan +pow(-0.5, inf) = 0 +pow(-0.5, -inf) = inf +pow(-0.5, 0) = 1 +pow(-0.5, -0) = 1 +pow(-0.5, 0.5) = nan +pow(-0.5, -0.5) = nan +pow(-0.5, 1) = -0.5 +pow(-0.5, -1) = -2 +pow(-0.5, 2) = 0.25 +pow(-0.5, -2) = 4 +pow(1, nan) = nan +pow(1, inf) = nan +pow(1, -inf) = nan +pow(1, 0) = 1 +pow(1, -0) = 1 +pow(1, 0.5) = 1 +pow(1, -0.5) = 1 +pow(1, 1) = 1 +pow(1, -1) = 1 +pow(1, 2) = 1 +pow(1, -2) = 1 +pow(-1, nan) = nan +pow(-1, inf) = nan +pow(-1, -inf) = nan +pow(-1, 0) = 1 +pow(-1, -0) = 1 +pow(-1, 0.5) = nan +pow(-1, -0.5) = nan +pow(-1, 1) = -1 +pow(-1, -1) = -1 +pow(-1, 2) = 1 +pow(-1, -2) = 1 +pow(2, nan) = nan +pow(2, inf) = inf +pow(2, -inf) = 0 +pow(2, 0) = 1 +pow(2, -0) = 1 +pow(2, 0.5) = 1.41421 +pow(2, -0.5) = 0.707106 +pow(2, 1) = 2 +pow(2, -1) = 0.5 +pow(2, 2) = 4 +pow(2, -2) = 0.25 +pow(-2, nan) = nan +pow(-2, inf) = inf +pow(-2, -inf) = 0 +pow(-2, 0) = 1 +pow(-2, -0) = 1 +pow(-2, 0.5) = nan +pow(-2, -0.5) = nan +pow(-2, 1) = -2 +pow(-2, -1) = -0.5 +pow(-2, 2) = 4 +pow(-2, -2) = 0.25 + +Rounding to +oo +(double) 0 = 0 +Signed zero tests (x is 0.0 and y is -0.0): + Test 1.0 / x != 1.0 / y returns 1 (should be 1). + Test 1.0 / x == 1.0 / +x returns 1 (should be 1). + Test 1.0 / x != 1.0 / +y returns 1 (should be 1). + Test 1.0 / x != 1.0 / -x returns 1 (should be 1). + Test 1.0 / x == 1.0 / -y returns 1 (should be 1). +0 + 0 = 0 +0 - 0 = 0 +0 + -0 = 0 +0 - -0 = 0 +-0 + 0 = 0 +-0 - 0 = -0 +-0 + -0 = -0 +-0 - -0 = 0 +1 + 1 = 2 +1 - 1 = 0 +1 + -1 = 0 +1 - -1 = 2 +0 * 0 = 0 +0 * -0 = -0 +-0 * 0 = -0 +-0 * -0 = 0 +Constant expression 1 + DBL_MIN = 1 +Variable expression 1 + DBL_MIN = 1.0000000000000002221 +Constant expression 1 - DBL_MIN = 1 +Variable expression 1 - DBL_MIN = 1 +1/3 in float : 0x1.555556p-2 +1/3 in double : 0x1.5555555555556p-2 +1/3 in long double : 0x1.5555555555555556p-2 +Dec 1.1 = 0x1.199999999999ap+0 +FLT_MAX = 0x1.fffffep+127 +DBL_MAX = 0x1.fffffffffffffp+1023 +LDBL_MAX = 0x1.fffffffffffffffep+16383 +FLT_EPSILON = 0x1p-23 +DBL_EPSILON = 0x1p-52 +LDBL_EPSILON = 0x1p-63 +pow(nan, nan) = nan +pow(nan, inf) = nan +pow(nan, -inf) = nan +pow(nan, 0) = 1 +pow(nan, -0) = 1 +pow(nan, 0.5) = nan +pow(nan, -0.5) = nan +pow(nan, 1) = nan +pow(nan, -1) = nan +pow(nan, 2) = nan +pow(nan, -2) = nan +pow(inf, nan) = nan +pow(inf, inf) = inf +pow(inf, -inf) = 0 +pow(inf, 0) = 1 +pow(inf, -0) = 1 +pow(inf, 0.5) = inf +pow(inf, -0.5) = 0 +pow(inf, 1) = inf +pow(inf, -1) = 0 +pow(inf, 2) = inf +pow(inf, -2) = 0 +pow(-inf, nan) = nan +pow(-inf, inf) = inf +pow(-inf, -inf) = 0 +pow(-inf, 0) = 1 +pow(-inf, -0) = 1 +pow(-inf, 0.5) = inf +pow(-inf, -0.5) = 0 +pow(-inf, 1) = -inf +pow(-inf, -1) = -0 +pow(-inf, 2) = inf +pow(-inf, -2) = 0 +pow(0, nan) = nan +pow(0, inf) = 0 +pow(0, -inf) = inf +pow(0, 0) = 1 +pow(0, -0) = 1 +pow(0, 0.5) = 0 +pow(0, -0.5) = inf +pow(0, 1) = 0 +pow(0, -1) = inf +pow(0, 2) = 0 +pow(0, -2) = inf +pow(-0, nan) = nan +pow(-0, inf) = 0 +pow(-0, -inf) = inf +pow(-0, 0) = 1 +pow(-0, -0) = 1 +pow(-0, 0.5) = 0 +pow(-0, -0.5) = inf +pow(-0, 1) = -0 +pow(-0, -1) = -inf +pow(-0, 2) = 0 +pow(-0, -2) = inf +pow(0.5, nan) = nan +pow(0.5, inf) = 0 +pow(0.5, -inf) = inf +pow(0.5, 0) = 1 +pow(0.5, -0) = 1 +pow(0.5, 0.5) = 0.707107 +pow(0.5, -0.5) = 1.41422 +pow(0.5, 1) = 0.5 +pow(0.5, -1) = 2 +pow(0.5, 2) = 0.25 +pow(0.5, -2) = 4 +pow(-0.5, nan) = nan +pow(-0.5, inf) = 0 +pow(-0.5, -inf) = inf +pow(-0.5, 0) = 1 +pow(-0.5, -0) = 1 +pow(-0.5, 0.5) = nan +pow(-0.5, -0.5) = nan +pow(-0.5, 1) = -0.5 +pow(-0.5, -1) = -2 +pow(-0.5, 2) = 0.25 +pow(-0.5, -2) = 4 +pow(1, nan) = nan +pow(1, inf) = nan +pow(1, -inf) = nan +pow(1, 0) = 1 +pow(1, -0) = 1 +pow(1, 0.5) = 1 +pow(1, -0.5) = 1 +pow(1, 1) = 1 +pow(1, -1) = 1 +pow(1, 2) = 1 +pow(1, -2) = 1 +pow(-1, nan) = nan +pow(-1, inf) = nan +pow(-1, -inf) = nan +pow(-1, 0) = 1 +pow(-1, -0) = 1 +pow(-1, 0.5) = nan +pow(-1, -0.5) = nan +pow(-1, 1) = -1 +pow(-1, -1) = -1 +pow(-1, 2) = 1 +pow(-1, -2) = 1 +pow(2, nan) = nan +pow(2, inf) = inf +pow(2, -inf) = 0 +pow(2, 0) = 1 +pow(2, -0) = 1 +pow(2, 0.5) = 1.41422 +pow(2, -0.5) = 0.707107 +pow(2, 1) = 2 +pow(2, -1) = 0.5 +pow(2, 2) = 4 +pow(2, -2) = 0.25 +pow(-2, nan) = nan +pow(-2, inf) = inf +pow(-2, -inf) = 0 +pow(-2, 0) = 1 +pow(-2, -0) = 1 +pow(-2, 0.5) = nan +pow(-2, -0.5) = nan +pow(-2, 1) = -2 +pow(-2, -1) = -0.5 +pow(-2, 2) = 4 +pow(-2, -2) = 0.25 +} + +if {[have_spec arm]} { + set reference_output $reference_output_arm +} +if {[have_spec x86_64]} { + set reference_output $reference_output_x86_64 +} +if {[have_spec x86_32]} { + set reference_output $reference_output_x86_32 +} + +proc filter_and_compare_output {pattern expected} { + global output + set old_output $output + grep_output "init -> $pattern" + unify_output {\[init -> test.\] } {} + compare_output_to $expected + set output $old_output +} + +filter_and_compare_output "test1" $reference_output +filter_and_compare_output "test2" $reference_output +filter_and_compare_output "test3" $reference_output +filter_and_compare_output "test4" $reference_output diff --git a/repos/libports/src/test/ieee754/component.cc b/repos/libports/src/test/ieee754/component.cc new file mode 100644 index 000000000..26d0e08fd --- /dev/null +++ b/repos/libports/src/test/ieee754/component.cc @@ -0,0 +1,15 @@ +#include +#include + +extern int main (int argc, char* argv[]); + +void Libc::Component::construct(Libc::Env &env) +{ + env.exec_static_constructors(); + + Genode::Heap heap(env.ram(), env.rm()); + + int r = 0; + Libc::with_libc([&r] () { r = main(0, 0); }); + env.parent().exit(r); +} diff --git a/repos/libports/src/test/ieee754/target.mk b/repos/libports/src/test/ieee754/target.mk new file mode 100644 index 000000000..beee84413 --- /dev/null +++ b/repos/libports/src/test/ieee754/target.mk @@ -0,0 +1,4 @@ +TARGET = test-ieee754 +LIBS = libc libm +SRC_C = tst-ieee754.c +SRC_CC = component.cc diff --git a/repos/libports/src/test/ieee754/tst-ieee754.c b/repos/libports/src/test/ieee754/tst-ieee754.c new file mode 100755 index 000000000..0588ab2f9 --- /dev/null +++ b/repos/libports/src/test/ieee754/tst-ieee754.c @@ -0,0 +1,489 @@ +/* Some IEEE-754 / ISO C99+ conformance tests. + * + * Compile this program with: + * gcc -Wall -O2 -std=c99 tst-ieee754.c -o tst-ieee754 -lm + * for instance. + * + * Add -DFP_CONTRACT to allow contraction of FP expressions (e.g. with icc). + * + * Copyright 2003-2017 Vincent Lefevre . + * + * You may use this software under the terms of the MIT License: + * http://opensource.org/licenses/MIT + * + * More information: https://en.wikipedia.org/wiki/MIT_License + */ + +#define SVNID "$Id: tst-ieee754.c 98609 2017-05-19 18:35:55Z vinc17/zira $" + +#include +#include +#include +#include +#include + +#define STRINGIFY(S) #S +#define MAKE_STR(S) STRINGIFY(S) + +#ifdef FP_CONTRACT +#undef FP_CONTRACT +#define FP_CONTRACT "ON" +#pragma STDC FP_CONTRACT ON +#else +#define FP_CONTRACT "OFF" +#pragma STDC FP_CONTRACT OFF +#endif + +#ifndef NO_FENV_H +#include +#pragma STDC FENV_ACCESS ON +#endif + +#ifndef NAN +#define NAN (0.0/0.0) +#endif + +#ifndef INFINITY +#define INFINITY (1.0/0.0) +#endif + +#define DBL_NAN (NAN) +#define DBL_POS_INF (INFINITY) +#define DBL_NEG_INF (- DBL_POS_INF) + +/* Note: The dynamic epsilon now gives information about + - the possible extended precision used to evaluate expression; + - the possible reduced precision due to the use of options like + GCC's -mpc32 or -mpc64 to reduce the dynamic rounding precision + with "387" arithmetic on x86 processors. */ +#define PREC_EPSILON(T,V,F) \ + do \ + { \ + volatile T eps = 1.0; \ + printf (#V " = %" F "g = %" F "a\n", (T) (V), (T) (V)); \ + while (eps != 0) \ + { \ + volatile T x = 1.0, e = eps / FLT_RADIX; \ + x = (x + e) - 1.0; \ + if (x != e) \ + break; \ + eps = e; \ + } \ + if (eps == 0) \ + printf (" (cannot compute the dynamic epsilon)\n"); \ + else if (eps != (V)) \ + printf (" (dynamic epsilon = %" F "g = %" F "a)\n", eps, eps); \ + } \ + while (0) + +#define ERRSTR(X) ((X) ? " [ERROR]" : "") + +static float flt_max = FLT_MAX; +static double dbl_max = DBL_MAX; +static long double ldbl_max = LDBL_MAX; + +static float flt_epsilon = FLT_EPSILON; +static double dbl_epsilon = DBL_EPSILON; +static long double ldbl_epsilon = LDBL_EPSILON; + +/* constants */ +static void float_h (void) +{ + printf ("FLT_RADIX = %d\n", (int) FLT_RADIX); + printf ("FLT_MANT_DIG = %d\n", (int) FLT_MANT_DIG); + printf ("DBL_MANT_DIG = %d\n", (int) DBL_MANT_DIG); + printf ("LDBL_MANT_DIG = %d\n\n", (int) LDBL_MANT_DIG); + + printf ("FLT_MIN_EXP = %d\n", (int) FLT_MIN_EXP); + printf ("DBL_MIN_EXP = %d\n", (int) DBL_MIN_EXP); + printf ("LDBL_MIN_EXP = %d\n\n", (int) LDBL_MIN_EXP); + + printf ("FLT_MAX_EXP = %d\n", (int) FLT_MAX_EXP); + printf ("DBL_MAX_EXP = %d\n", (int) DBL_MAX_EXP); + printf ("LDBL_MAX_EXP = %d\n\n", (int) LDBL_MAX_EXP); + + PREC_EPSILON (float, FLT_EPSILON, ""); + PREC_EPSILON (double, DBL_EPSILON, ""); + PREC_EPSILON (long double, LDBL_EPSILON, "L"); + putchar ('\n'); + + printf ("FLT_MIN = %g = %a\n", (double) FLT_MIN, (double) FLT_MIN); + printf ("DBL_MIN = %g = %a\n", (double) DBL_MIN, (double) DBL_MIN); + printf ("LDBL_MIN = %Lg = %La\n\n", + (long double) LDBL_MIN, (long double) LDBL_MIN); + + printf ("FLT_MAX = %g = %a\n", (double) FLT_MAX, (double) FLT_MAX); + printf ("DBL_MAX = %g = %a\n", (double) DBL_MAX, (double) DBL_MAX); + printf ("LDBL_MAX = %Lg = %La\n\n", + (long double) LDBL_MAX, (long double) LDBL_MAX); +} + +#define TSIZEOF(T) printf ("sizeof(" #T ") = %d\n", (int) sizeof(T)) + +static void float_sizeof (void) +{ + TSIZEOF (float); + TSIZEOF (double); + TSIZEOF (long double); + putchar ('\n'); +} + +static void tstcast (void) +{ + double x; + x = (double) 0; + printf ("(double) 0 = %g\n", x); +} + +/* This mostly tests signed zero support. This test is written in + such a way that "gcc -O -ffast-math" gives a wrong result. */ +static void signed_zero_inf (void) +{ + double x = 0.0, y = -0.0, px, py, nx, ny; + + printf ("Signed zero tests (x is 0.0 and y is -0.0):\n"); + + if (x == y) + printf (" Test 1.0 / x != 1.0 / y returns %d (should be 1).\n", + 1.0 / x != 1.0 / y); + else + printf ("x != y; this is wrong!\n"); + + px = +x; + if (x == px) + printf (" Test 1.0 / x == 1.0 / +x returns %d (should be 1).\n", + 1.0 / x == 1.0 / px); + else + printf ("x != +x; this is wrong!\n"); + + py = +y; + if (x == py) + printf (" Test 1.0 / x != 1.0 / +y returns %d (should be 1).\n", + 1.0 / x != 1.0 / py); + else + printf ("x != +y; this is wrong!\n"); + + nx = -x; + if (x == nx) + printf (" Test 1.0 / x != 1.0 / -x returns %d (should be 1).\n", + 1.0 / x != 1.0 / nx); + else + printf ("x != -x; this is wrong!\n"); + + ny = -y; + if (x == ny) + printf (" Test 1.0 / x == 1.0 / -y returns %d (should be 1).\n", + 1.0 / x == 1.0 / ny); + else + printf ("x != -y; this is wrong!\n"); +} + +static void tstadd (double x, double y) +{ + double a, s; + + a = x + y; + s = x - y; + printf ("%g + %g = %g\n", x, y, a); + printf ("%g - %g = %g\n", x, y, s); +} + +static void tstmul (double x, double y) +{ + double m; + + m = x * y; + printf ("%g * %g = %g\n", x, y, m); +} + +#define TSTCONST(S,OP) \ + printf ("Constant expression 1 " S " DBL_MIN = %.20g\n" \ + "Variable expression 1 " S " DBL_MIN = %.20g\n", \ + 1.0 OP DBL_MIN, 1.0 OP x); + +static void tstconst (void) +{ + volatile double x = DBL_MIN; + + TSTCONST ("+", +); + TSTCONST ("-", -); +} + +#define TSTDIV(T,S) \ + do \ + { \ + volatile T x = 1.0, y = 3.0; \ + x /= y; \ + printf ("1/3 in %-12s: %" S "a\n", #T, x); \ + } \ + while (0) + +static void tstpow (void) +{ + double val[] = { 0.0, 0.0, 0.0, +0.0, -0.0, + +0.5, -0.5, +1.0, -1.0, +2.0, -2.0 }; + int i, j; + + /* Not used above to avoid an error with IRIX64 cc. */ + val[0] = DBL_NAN; + val[1] = DBL_POS_INF; + val[2] = DBL_NEG_INF; + + for (i = 0; i < sizeof (val) / sizeof (val[0]); i++) + for (j = 0; j < sizeof (val) / sizeof (val[0]); j++) + { + double p; + p = pow (val[i], val[j]); + printf ("pow(%g, %g) = %g\n", val[i], val[j], p); + } +} + +static void tstall (void) +{ + float fm = FLT_MAX, fe = FLT_EPSILON; + double dm = DBL_MAX, de = DBL_EPSILON; + long double lm = LDBL_MAX, le = LDBL_EPSILON; + + tstcast (); + signed_zero_inf (); + + tstadd (+0.0, +0.0); + tstadd (+0.0, -0.0); + tstadd (-0.0, +0.0); + tstadd (-0.0, -0.0); + tstadd (+1.0, +1.0); + tstadd (+1.0, -1.0); + + tstmul (+0.0, +0.0); + tstmul (+0.0, -0.0); + tstmul (-0.0, +0.0); + tstmul (-0.0, -0.0); + + tstconst (); + TSTDIV (float, ""); + TSTDIV (double, ""); + TSTDIV (long double, "L"); + + printf ("Dec 1.1 = %a\n", (double) 1.1); + printf ("FLT_MAX = %a%s\n", (double) fm, ERRSTR (fm != flt_max)); + printf ("DBL_MAX = %a%s\n", dm, ERRSTR (dm != dbl_max)); + printf ("LDBL_MAX = %La%s\n", lm, ERRSTR (lm != ldbl_max)); + printf ("FLT_EPSILON = %a%s\n", (double) fe, ERRSTR (fe != flt_epsilon)); + printf ("DBL_EPSILON = %a%s\n", de, ERRSTR (de != dbl_epsilon)); + printf ("LDBL_EPSILON = %La%s\n", le, ERRSTR (le != ldbl_epsilon)); + + tstpow (); +} + +static void tsteval_method (void) +{ + volatile double x, y, z; + +#if __STDC__ == 1 && __STDC_VERSION__ >= 199901 && defined(__STDC_IEC_559__) + printf ("__STDC_IEC_559__ defined:\n" + "The implementation shall conform to the IEEE-754 standard.\n"); +# ifdef FLT_EVAL_METHOD + printf ("FLT_EVAL_METHOD is %d (see ISO/IEC 9899, 5.2.4.2.2#8).\n\n", + (int) FLT_EVAL_METHOD); +# else + printf ("But FLT_EVAL_METHOD is not defined!\n\n"); +# endif +#endif + + x = 9007199254740994.0; /* 2^53 + 2 */ + y = 1.0 - 1/65536.0; + z = x + y; + printf ("x + y, with x = 9007199254740994.0 and y = 1.0 - 1/65536.0" + " (type double).\n" + "The IEEE-754 result is 9007199254740994 with double precision.\n" + "The IEEE-754 result is 9007199254740996 with extended precision.\n" + "The obtained result is %.17g.\n", z); + + if (z == 9007199254740996.0) /* computations in extended precision */ + { + volatile double a, b; + double c; + + a = 9007199254740992.0; /* 2^53 */ + b = a + 0.25; + c = a + 0.25; + if (b != c) + printf ("\nBUG:\nThe implementation doesn't seem to convert values " + "to the target type after\nan assignment (see ISO/IEC 9899: " + "5.1.2.3#12, 6.3.1.5#2 and 6.3.1.8#2[52]).\n"); + } +} + +/* This test is useful only on implementations where the "double" type + * corresponds to the IEEE-754 double precision and the "long double" + * type corresponds to the traditional x86 extended precision, but let's + * do it in any case. It shows a bug in gcc 3.4 to 4.3.3 on x86_64 and + * ia64 platforms. See: + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36578 + */ +static void ldcast_test (void) +{ + volatile double a = 4294967219.0; + volatile double b = 4294967429.0; + double c, d; + long double al, bl; + + al = a; + bl = b; + c = (long double) a * (long double) b; + d = al * bl; + if (c != d) + printf ("\nBUG: Casts to long double do not seem to be taken into " + "account when\nthe result to stored to a variable of type " + "double. If your compiler\nis gcc (version < 4.3.4), this " + "may be the following bug:\n " + "https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36578\n"); +} + +static void tstnan (void) +{ + double d; + + /* Various tests to detect a NaN without using the math library (-lm). + * MIPSpro 7.3.1.3m (IRIX64) does too many optimisations, so that + * both NAN != NAN and !(NAN >= 0.0 || NAN <= 0.0) give 0 instead + * of 1. As a consequence, in MPFR, one needs to use + * #define DOUBLE_ISNAN(x) (!(((x) >= 0.0) + ((x) <= 0.0))) + * in this case. */ + + d = NAN; + printf ("\n"); + printf ("NAN != NAN --> %d (should be 1)\n", d != d); + printf ("isnan(NAN) --> %d (should be 1)\n", isnan (d)); + printf ("NAN >= 0.0 --> %d (should be 0)\n", d >= 0.0); + printf ("NAN <= 0.0 --> %d (should be 0)\n", d <= 0.0); + printf (" #3||#4 --> %d (should be 0)\n", d >= 0.0 || d <= 0.0); + printf ("!(#3||#4) --> %d (should be 1)\n", !(d >= 0.0 || d <= 0.0)); + printf (" #3 + #4 --> %d (should be 0)\n", (d >= 0.0) + (d <= 0.0)); + printf ("!(#3 + #4) --> %d (should be 1)\n", !((d >= 0.0) + (d <= 0.0))); +} + +#define TSTINVALID(F,C) \ + do \ + { \ + feclearexcept (FE_INVALID); \ + (void) (d C 0.0); \ + if ((F) ^ ! fetestexcept (FE_INVALID)) \ + printf ("The FE_INVALID flag is%s set for NAN " #C " 0.\n", \ + (F) ? "" : " not"); \ + } \ + while (0) + +static void tstinvalid (void) +{ +#ifdef NO_FENV_H + printf ("The FE_INVALID flag could not be tested (no )\n"); +#else + double d = NAN; + TSTINVALID(1,==); + TSTINVALID(1,!=); + TSTINVALID(0,>=); + TSTINVALID(0,<=); + TSTINVALID(0,>); + TSTINVALID(0,<); +#endif +} + +/* Note: we do not use the FP_CONTRACT pragma locally (in a block) as + icc 10.1 seems to disable contraction when it sees FP_CONTRACT OFF + somewhere in the source. */ +static void fused_madd_test (void) +{ +#define TWO40 (1099511627776.0) /* 2^40 */ +#define C1U40 (1.0 + 1.0/TWO40) /* 1 + 2^(-40) */ + volatile double x = C1U40, y = C1U40, z = -1.0, d; + + d = x * y + z; + printf ("\nx * y + z with FP_CONTRACT " FP_CONTRACT " is %sfused.\n", + d == 2.0 * (1 + 0.5 / TWO40) / TWO40 ? "" : "not "); +} + +/* FE_INVALID exception with Clang: + * https://bugs.llvm.org//show_bug.cgi?id=17686 + */ +static void double_to_unsigned (void) +{ + volatile double d; + uint64_t i = (uint64_t) 1 << 63; + int t1, t2; + + d = i; + feclearexcept (FE_INVALID); + t1 = (uint64_t) d != i; + t2 = fetestexcept (FE_INVALID); + if (t1 || t2) + printf ("\nError in cast of double to unsigned: %s value%s\n", + t1 ? "incorrect" : "correct", t2 ? ", FE_INVALID" : ""); +} + +static void ibm_ldconv (void) +{ +#define CAT1(X) 1 ## X +#define CAT2(X) CAT1(X) +#define LD0 .000000000000000000000000000000000001L +#define LD1 CAT2(LD0) + long double x = 1.0L + LD0, y = LD1; + + if (x > 1.0L && y == 1.0L) + { + printf ("\nBad conversion of " MAKE_STR(LD1) "\n"); + printf ("Got 1 instead of about 1 + %La\n", x - 1.0L); + } +} + +int main (void) +{ + /* printf ("%s\n\n", SVNID); */ + + float_h (); + float_sizeof (); + tsteval_method (); + ldcast_test (); + tstnan (); + tstinvalid (); + fused_madd_test (); + double_to_unsigned (); + + if (LDBL_MIN_EXP == -968 && LDBL_MAX_EXP == 1024 && + LDBL_MANT_DIG == 106) /* IBM long double format, i.e. double-double */ + ibm_ldconv (); + + printf ("\nRounding to nearest\n"); +#ifdef FE_TONEAREST + if (fesetround (FE_TONEAREST)) + printf ("Error, but let's do the test since it " + "should be the default rounding mode.\n"); +#endif + tstall (); + +#ifdef FE_TOWARDZERO + printf ("\nRounding toward 0\n"); + if (fesetround (FE_TOWARDZERO)) + printf ("Error\n"); + else + tstall (); +#endif + +#ifdef FE_DOWNWARD + printf ("\nRounding to -oo\n"); + if (fesetround (FE_DOWNWARD)) + printf ("Error\n"); + else + tstall (); +#endif + +#ifdef FE_UPWARD + printf ("\nRounding to +oo\n"); + if (fesetround (FE_UPWARD)) + printf ("Error\n"); + else + tstall (); +#endif + + return 0; +} diff --git a/tool/autopilot.list b/tool/autopilot.list index 95b5acb8d..4c7ecdbc5 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -12,6 +12,7 @@ fetchurl_lxip fetchurl_lwip fs_query gdb_monitor +ieee754 init_smp input_filter libc_fatfs