summaryrefslogtreecommitdiff
path: root/libc/i386fp/fperror.x
blob: 04f3f74be8367a5cd3c199292292f00059eeb1e9 (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
! bcc 386 floating point routines (version 2)
! --- fpdenormal, fperror, fpinfinity, fpNaN, fpoverflow, fpunderflow,fpdivzero
! author: Bruce Evans

#include "fperr.h"
#include "fplib.h"

	.extern	_fperr

! Cause a denormal-operand exception
! Preserves all general registers if signal handler returns

	.globl	fpdenormal
	.align	ALIGNMENT
fpdenormal:
#if 0
	push	eax
	mov	eax,#EFDENORMAL
	call	fperror
	pop	eax
#endif
	ret

! Cause an exception with error code eax, preserving all genregs except eax

	.globl	fperror
	.align	ALIGNMENT
fperror:
	push	ebp		! set up usual frame ...
	mov	ebp,esp		! ... for debugging
	push	edx		! save default
	push	ecx
	push	eax		! error code is arg to C routine
	call	_fperr
	add	esp,#GENREG_SIZE
	pop	ecx		! restore default
	pop	edx
	pop	ebp
	ret

	.align	ALIGNMENT
fphuge:
	mov	ecx,#D_HUGE_LOW	! prepare number +-HUGEVAL
	or	edx,#D_HUGE_HIGH	! ... in case signal handler returns
	jmp	fperror

! Cause an infinite-operand exception
! Return +-HUGEVAL in edx:ecx with sign from edx

	.globl	fpinfinity
	.align	ALIGNMENT
fpinfinity:
	mov	eax,#EFINFINITY
	jmp	fphuge		! almost right

! Cause an NaN-operand exception
! Return +-HUGEVAL in edx:ecx with sign from edx

	.globl	fpNaN
	.align	ALIGNMENT
fpNaN:
	mov	eax,#EFNAN	! there are different types of NaNs but...
	jmp	fphuge		! WRONG

! Cause an overflow exception
! Return +-HUGEVAL in edx:ecx with sign from edx

	.globl	fpoverflow
	.align	ALIGNMENT
fpoverflow:
	mov	eax,#EFOVERFLOW
	jmp	fphuge		! almost right

! Cause an underflow exception (actually assume it is masked for now)
! Return denormal or 0.0 in edx:ecx
! XXX - this should cause a denormal exception or none for the denormal case
! Args: sign in edx, fraction in esi:eax, right shift in edi
! Returns: denormalized number in edx:eax

	.globl	fpunderflow
	.align	ALIGNMENT
fpunderflow:
#if 0
	mov	eax,#EFUNDERFLOW
	jmp	fperror
#endif
	cmp	edi,#REG_BIT
	jb	denormalize1
	mov	eax,esi
	sub	esi,esi
	sub	edi,#REG_BIT
	cmp	edi,#REG_BIT
	jb	denormalize1
denormalize_underflow:
#if 0
	mov	eax,#EFUNDERFLOW
	jmp	fperror
#endif
	sub	eax,eax
	mov	edx,eax
	ret

	.align	ALIGNMENT
denormalize1:
	mov	ecx,edi
	shrd	eax,esi,cl
	shr	esi,cl
	mov	ecx,esi
	or	ecx,eax
	jz	denormalize_underflow
	and	edx,#D_SIGN_MASK
	or	edx,esi
	ret

! Cause an fp division by zero exception
! Return +-HUGEVAL in edx:ecx with sign from edx

	.globl	fpdivzero
	.align	ALIGNMENT
fpdivzero:
	mov	eax,#EFDIVZERO
	test	edx,#D_EXP_MASK
	jnz	fphuge		! almost right
	sub	ecx,ecx
	mov	edx,ecx
	jmp	fperror