summaryrefslogtreecommitdiff
path: root/components/external/espruino/libs/math/setprec.87
blob: e9e2b081a1faaf4863ab9720be5d1b0fc240797a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
;
; Microsoft MASM subroutines for setting coprocessor precision
;
.286
.287
_TEXT	SEGMENT  BYTE PUBLIC 'CODE'
_TEXT	ENDS
CONST	SEGMENT  WORD PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT  WORD PUBLIC 'BSS'
_BSS	ENDS
_DATA	SEGMENT  WORD PUBLIC 'DATA'
_DATA	ENDS
DGROUP	GROUP	CONST,	_BSS,	_DATA
	ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP
EXTRN	__fac:QWORD

_BSS      SEGMENT
EXTRN	__fltused:NEAR
_BSS      ENDS


; exception masks (1 = masked)
;   1  invalid operation
;   2  denormalized operand
;   4  zero divide
;   8  overflow
;  10  underflow
;  20  precision

_DATA SEGMENT

; double precision setting
;;ctlwrd dw 01230h ; note this traps on denormal operands!
;;ctld dw 0133fh   ; this doesn't trap
ctld dw 01230h

; single precision
ctls dw 01030h

; long double precision
ctlld dw 01320h

_DATA ENDS

	ASSUME  CS: _TEXT

_TEXT SEGMENT
; Set coprocessor to single precision float
	PUBLIC	_sprec
_sprec	PROC NEAR
	fclex
	fwait
	finit
	fwait
	fldcw word ptr ctls
	fwait
	ret
_sprec ENDP

; set coprocessor to long double precision
	PUBLIC	_ldprec
_ldprec PROC NEAR
	fclex
	fwait
	finit
	fwait
	fldcw word ptr ctlld
	fwait
	ret
_ldprec ENDP

; set coprocessor to double precision
	PUBLIC	_dprec
_dprec PROC NEAR
	fclex
	fwait
	finit
	fwait
	fldcw word ptr ctld
	fwait
	ret
_dprec ENDP


; get a double promoted to long double size
; getld( &doub, &ldoub );
	PUBLIC	_getld
_getld	PROC NEAR
	push bp
	mov bp,sp
	push bx
	mov bx, word ptr [bp+4]
;	fld st(0)
	fld qword ptr [bx]
	mov bx, word ptr [bp+6]
	fstp tbyte ptr [bx]
	mov bx, word ptr [bp+4]
	fld qword ptr [bx]
	mov bx, word ptr [bp+8]
	fstp qword ptr [bx]
	pop bx
	pop bp
	ret
_getld	ENDP

	PUBLIC	_getprec
_getprec	PROC NEAR
	push bp
	mov bp,sp
	sub sp,4
	fstcw [bp-4]
	fwait
	mov ax,[bp-4]
	add sp,4
	pop bp
	ret
_getprec	ENDP


	PUBLIC	_fpclear
_fpclear	PROC NEAR
	push bp
	mov bp,sp
	fnclex
	fwait
	pop bp
	ret
_fpclear	ENDP


	PUBLIC	_noexcept
_noexcept	PROC NEAR
	push bp
	mov bp,sp
	push ax
	sub sp,4
	fnclex
	fwait
	fstcw [bp-4]
	fwait
	mov ax,[bp-4]
	and ax,0FFC0h
	or ax,003fh
	mov [bp-4],ax
	fldcw [bp-4]
	add sp,4
	pop ax
	pop bp
	ret
_noexcept	ENDP

;; single precision square root
;; assumes coprocessor precision already set up
;; return value in static __fac
;	PUBLIC	_sqrtf
;_sqrtf	PROC NEAR
;	push bp
;	mov bp,sp
;	fld	DWORD PTR [bp+4]
;	fsqrt
;	fwait	
;	fstp	DWORD PTR __fac
;	mov	ax,OFFSET __fac
;	mov	sp,bp
;	pop bp
;	ret
;_sqrtf	ENDP
;
;
;; double precision square root
;; assumes coprocessor precision already set up
;; return value in static __fac
;	PUBLIC	_sqrt
;_sqrt	PROC NEAR
;	push bp
;	mov bp,sp
;	fld	QWORD PTR [bp+4]
;	fsqrt
;	fwait	
;	fstp	QWORD PTR __fac
;	mov	ax,OFFSET __fac
;	mov	sp,bp
;	pop bp
;	ret
;_sqrt	ENDP
;
;
;; long double precision square root
;; assumes coprocessor precision already set up
;; return value in fp register
;	PUBLIC	_sqrtl
;_sqrtl	PROC NEAR
;	push bp
;	mov bp,sp
;	fld tbyte ptr [bp+4]
;	fsqrt
;	fwait	
;	mov	sp,bp
;	pop bp
;	ret
;_sqrtl	ENDP
;

_TEXT ENDS
END