crt: Convert the arm sincos.c to assembly

This avoids optimizing the sincos function to a recursive call to
itself, if built with -ffast-math (unless built with -fno-builtin-sin).

While building with -ffast-math can break certain math routines and
thus can be considered a self-inflicted issue, it's safest to avoid
constructs that potentially can be optimized into an infinite self
recursion.

Signed-off-by: Martin Storsjö <martin@martin.st>
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index 3feaa44..49cd701 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -525,14 +525,15 @@
   math/softmath/sinf.c      math/softmath/sinl.c      math/softmath/tanf.c      math/softmath/tanl.c
 else
 src_libmingwexarm32+=\
-  math/arm-common/ldexpl.c  math/arm-common/sincos.c
+  math/arm-common/ldexpl.c  math/arm/sincos.S         math/arm/sincosf.S
 endif
 
 # these only go into the ARM64 version:
 src_libmingwexarm64=\
   math/arm64/_chgsignl.S \
   math/arm64/rint.c         math/arm64/rintf.c \
-  math/arm-common/ldexpl.c  math/arm-common/sincos.c
+  math/arm64/sincos.S       math/arm64/sincosf.S \
+  math/arm-common/ldexpl.c
 
 
 # These intrinsics are target independent:
diff --git a/mingw-w64-crt/math/arm-common/sincos.c b/mingw-w64-crt/math/arm-common/sincos.c
deleted file mode 100644
index 099351f..0000000
--- a/mingw-w64-crt/math/arm-common/sincos.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is part of the mingw-w64 runtime package.
- * No warranty is given; refer to the file DISCLAIMER.PD within this package.
- */
-
-#include <math.h>
-
-void sincos (double __x, double *p_sin, double *p_cos)
-{
-  *p_sin = sin(__x);
-  *p_cos = cos(__x);
-}
-
-void sincosf (float __x, float *p_sin, float *p_cos)
-{
-  *p_sin = sinf(__x);
-  *p_cos = cosf(__x);
-}
-
-void sincosl (long double __x, long double *p_sin, long double *p_cos)
-{
-#if defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_)
-  *p_sin = sin(__x);
-  *p_cos = cos(__x);
-#else
-#error Not supported on your platform yet
-#endif
-}
diff --git a/mingw-w64-crt/math/arm/sincos.S b/mingw-w64-crt/math/arm/sincos.S
new file mode 100644
index 0000000..2d3caa8
--- /dev/null
+++ b/mingw-w64-crt/math/arm/sincos.S
@@ -0,0 +1,32 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <_mingw_mac.h>
+
+	.file	"sincos.S"
+	.text
+	.align 2
+	.globl __MINGW_USYMBOL(sincos)
+	.globl __MINGW_USYMBOL(sincosl)
+	.def	__MINGW_USYMBOL(sincos);	.scl	2;	.type	32;	.endef
+	.def	__MINGW_USYMBOL(sincosl);	.scl	2;	.type	32;	.endef
+__MINGW_USYMBOL(sincos):
+__MINGW_USYMBOL(sincosl):
+	push {r4, r5, r11, lr}
+	add r11, sp, #8
+	vpush {d8}
+
+	mov r4, r0
+	mov r5, r1
+	vmov.f64 d8, d0
+	bl sin
+	vstr d0, [r4]
+
+	vmov.f64 d0, d8
+	bl cos
+	vstr d0, [r5]
+
+	vpop {d8}
+	pop {r4, r5, r11, pc}
diff --git a/mingw-w64-crt/math/arm/sincosf.S b/mingw-w64-crt/math/arm/sincosf.S
new file mode 100644
index 0000000..ce88b18
--- /dev/null
+++ b/mingw-w64-crt/math/arm/sincosf.S
@@ -0,0 +1,29 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <_mingw_mac.h>
+
+	.file	"sincosf.S"
+	.text
+	.align 2
+	.globl __MINGW_USYMBOL(sincosf)
+	.def	__MINGW_USYMBOL(sincosf);	.scl	2;	.type	32;	.endef
+__MINGW_USYMBOL(sincosf):
+	push {r4, r5, r11, lr}
+	add r11, sp, #8
+	vpush {d8}
+
+	mov r4, r0
+	mov r5, r1
+	vmov.f32 s16, s0
+	bl sinf
+	vstr s0, [r4]
+
+	vmov.f32 s0, s16
+	bl cosf
+	vstr s0, [r5]
+
+	vpop {d8}
+	pop {r4, r5, r11, pc}
diff --git a/mingw-w64-crt/math/arm64/sincos.S b/mingw-w64-crt/math/arm64/sincos.S
new file mode 100644
index 0000000..f7ae446
--- /dev/null
+++ b/mingw-w64-crt/math/arm64/sincos.S
@@ -0,0 +1,34 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <_mingw_mac.h>
+
+	.file	"sincos.S"
+	.text
+	.align 2
+	.globl __MINGW_USYMBOL(sincos)
+	.globl __MINGW_USYMBOL(sincosl)
+	.def	__MINGW_USYMBOL(sincos);	.scl	2;	.type	32;	.endef
+	.def	__MINGW_USYMBOL(sincosl);	.scl	2;	.type	32;	.endef
+__MINGW_USYMBOL(sincos):
+__MINGW_USYMBOL(sincosl):
+	str d8, [sp, #-32]!
+	str x30, [sp, #8]
+	stp x19, x20, [sp, #16]
+
+	mov x19, x0
+	mov x20, x1
+	fmov d8, d0
+	bl sin
+	str d0, [x19]
+
+	fmov d0, d8
+	bl cos
+	str d0, [x20]
+
+	ldp x19, x20, [sp, #16]
+	ldr x30, [sp, #8]
+	ldr d8, [sp], #32
+	ret
diff --git a/mingw-w64-crt/math/arm64/sincosf.S b/mingw-w64-crt/math/arm64/sincosf.S
new file mode 100644
index 0000000..6939eeb
--- /dev/null
+++ b/mingw-w64-crt/math/arm64/sincosf.S
@@ -0,0 +1,31 @@
+/**
+ * This file has no copyright assigned and is placed in the Public Domain.
+ * This file is part of the mingw-w64 runtime package.
+ * No warranty is given; refer to the file DISCLAIMER.PD within this package.
+ */
+#include <_mingw_mac.h>
+
+	.file	"sincosf.S"
+	.text
+	.align 2
+	.globl __MINGW_USYMBOL(sincosf)
+	.def	__MINGW_USYMBOL(sincosf);	.scl	2;	.type	32;	.endef
+__MINGW_USYMBOL(sincosf):
+	str d8, [sp, #-32]!
+	str x30, [sp, #8]
+	stp x19, x20, [sp, #16]
+
+	mov x19, x0
+	mov x20, x1
+	fmov s8, s0
+	bl sinf
+	str s0, [x19]
+
+	fmov s0, s8
+	bl cosf
+	str s0, [x20]
+
+	ldp x19, x20, [sp, #16]
+	ldr x30, [sp, #8]
+	ldr d8, [sp], #32
+	ret