this repo has no description
1/*
2 * Written by Stephen Canon
3 *
4 * Copyright © 2007, Apple Inc. All Rights Reserved.
5 */
6
7#include <machine/asm.h>
8
9#if defined( __LP64__ )
10#define PTR_SIZE 8
11#define MOVP movq
12#define ADDP addq
13#define SUBP subq
14#define RESULT_DEST %rdi
15#define STACKP %rsp
16#else
17#define PTR_SIZE 4
18#define MOVP movl
19#define ADDP addl
20#define SUBP subl
21#define RESULT_DEST %edx
22#define STACKP %esp
23#endif
24
25
26// void cosisinl(long double x, long double complex *z)
27
28ENTRY(cosisinl)
29 fldt PTR_SIZE(STACKP) // load argument
30
31#if defined( __LP64__ ) // in lp64 case, result address is already in %rdi
32#else
33 MOVP 16+PTR_SIZE(STACKP), RESULT_DEST // load result address
34#endif
35
36 fsincos // try sincos
37 fnstsw %ax // load status word
38 andw $0x400,%ax // check status word to see if x was in range for fsincos
39 jnz 1f
40
41 fstpt (RESULT_DEST) // if the argument was in range, store the result
42 fstpt 16(RESULT_DEST)
43 ret // and return
44
45 1: fldpi // if the argument was out of range, put 2π on the fp stack
46 fadd %st(0)
47 fxch %st(1)
48
49 2: fprem1 // while x is out of range, reduce by 2π
50 fnstsw %ax
51 andw $0x400,%ax
52 jnz 2b
53 fstp %st(1) // clear 2π off the fp stack
54
55 fsincos // compute fsincos (argument is surely in range here)
56
57 fstpt (RESULT_DEST) // store the result
58 fstpt 16(RESULT_DEST)
59 ret // and return
60
61
62// void cosisin(double x, double complex *z)
63
64ENTRY(cosisin)
65#if defined( __LP64__ ) // in LP64, load x from %xmm0 (result dest will stay in %rdi)
66 SUBP $8, STACKP
67 movsd %xmm0, (STACKP)
68 fldl (STACKP)
69#else
70 fldl PTR_SIZE(STACKP) // otherwise, load x and the result dest off the stack
71 MOVP 8+PTR_SIZE(STACKP), RESULT_DEST
72#endif
73
74 fsincos // try sincos
75 fnstsw %ax // load status word
76 andw $0x400,%ax // check status word to see if x was in range for fsincos
77 jnz 3f
78
79 fstpl (RESULT_DEST) // store the result
80 fstpl 8(RESULT_DEST)
81#if defined( __LP64__ )
82 ADDP $8, STACKP // restore the stack, since we touched it in 64-bit mode
83#endif
84 ret
85
86 3: fldpi // if the argument was out of range, put 2π on the fp stack
87 fadd %st(0)
88 fxch %st(1)
89
90 4: fprem1 // while x is out of range, reduce by 2π
91 fnstsw %ax
92 andw $0x400,%ax
93 jnz 4b
94 fstp %st(1) // clear 2π off the fp stack
95
96 fsincos // compute fsincos (argument is surely in range here)
97
98 fstpl (RESULT_DEST) // store the result
99 fstpl 8(RESULT_DEST)
100#if defined( __LP64__ )
101 ADDP $8, STACKP // restore the stack, since we touched it in 64-bit mode
102#endif
103 ret
104
105
106// void cosisinf(float x, float complex *z)
107
108ENTRY(cosisinf)
109#if defined( __LP64__ ) // in LP64, load x from %xmm0 (result dest will stay in %rdi)
110 SUBP $4, STACKP
111 movss %xmm0, (STACKP)
112 flds (STACKP)
113#else
114 flds PTR_SIZE(STACKP) // otherwise, load x and the result dest off the stack
115 MOVP 4+PTR_SIZE(STACKP), RESULT_DEST
116#endif
117
118 fsincos // try sincos
119 fnstsw %ax // load status word
120 andw $0x400,%ax // check status word to see if x was in range for fsincos
121 jnz 5f
122
123 fstps (RESULT_DEST) // store the result
124 fstps 4(RESULT_DEST)
125#if defined( __LP64__ )
126 ADDP $4, STACKP // restore the stack, since we touched it in 64-bit mode
127#endif
128 ret
129
130 5: fldpi // if the argument was out of range, put 2π on the stack
131 fadd %st(0)
132 fxch %st(1)
133
134 6: fprem1 // while x is out of range, reduce by 2π
135 fnstsw %ax
136 andw $0x400,%ax
137 jnz 6b
138 fstp %st(1) // clear 2π off the stack
139
140 fsincos // compute fsincos (argument is surely in range here)
141
142 fstps (RESULT_DEST) // store the result
143 fstps 4(RESULT_DEST)
144#if defined( __LP64__ )
145 ADDP $4, STACKP // restore the stack, since we touched it in 64-bit mode
146#endif
147 ret