summaryrefslogtreecommitdiff
path: root/libc/i386fp/fptoi.x
blob: 30de7298b0e0b97d64558193b67a6f8b3ed52b70 (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
! bcc 386 floating point routines (version 2)
! -- dtoi, dtol, dtoui, dtoul, ftoi, ftol (todo: ftoui, ftoul)
! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans

#include "fplib.h"

	.extern	fpoverflow
	.extern	Fpushf

! Convert double x at [ebx] to int and return in eax

	.globl dtoi
	.globl dtol
	.align	ALIGNMENT
dtoi:
dtol:
	mov	eax,D_HIGH[ebx]
	mov	ecx,eax
	and	ecx,#D_EXP_MASK	! extract exponent
	jz	retz		! if 0 return 0
	test	eax,#D_SIGN_MASK
	jnz	negative
	call	into_dtoui
	cmp	eax,#INT_MAX
	ja	overflow_int_max
	ret

	.align	ALIGNMENT
negative:
	and	eax,#~D_SIGN_MASK
	call	into_dtoui
	cmp	eax,#INT_MIN
	ja	overflow_int_min
	neg	eax
	ret

	.align	ALIGNMENT
overflow_int_max:
	call	fpoverflow
	mov	eax,#INT_MAX
	ret

	.align	ALIGNMENT
overflow_int_min:
	js	return		! actually INT_MIN is OK
	call	fpoverflow
	mov	eax,#INT_MIN
return:
	ret

	.align	ALIGNMENT
retz:
	sub	eax,eax		! clear return value
	ret

! Convert double x at [ebx] to unsigned and return in eax

	.globl dtoui
	.globl dtoul
	.align	ALIGNMENT
dtoui:
dtoul:
	mov	eax,D_HIGH[ebx]
	mov	ecx,eax
	and	ecx,#D_EXP_MASK	! extract exponent
	jz	retz		! if 0 return 0
	test	eax,#D_SIGN_MASK
	jnz	overflow_0
into_dtoui:
	mov	edx,D_LOW[ebx]

	and	eax,#D_FRAC_MASK	! extract fraction
	or	eax,#D_NORM_MASK	! restore normalization bit

	shr	ecx,#D_EXP_SHIFT	! convert exponent to number
	sub	ecx,#D_EXP_BIAS+D_NORM_BIT	! adjust radix point
	jl	dtoui_rightshift	! should we shift left or right?
	cmp	ecx,#D_BIT-D_FRAC_BIT	! can shift left by at most this
	ja	overflow_uint_max	! if more, overflow
	shld	eax,edx,cl
	ret

	.align	ALIGNMENT
dtoui_rightshift:
	neg	ecx		! make shift count > 0
	cmp	ecx,#REG_BIT	! big shifts would be taken mod REG_BIT ...
	jae	retz		! ... no good
	shr	eax,cl		! otherwise it is faster to do the shift ...
	ret			! ... then to jump for the slightly smaller
				! ... shift counts that shift out all bits

	.align	ALIGNMENT
overflow_0:
	call	fpoverflow
	sub	eax,eax
	ret

	.align	ALIGNMENT
overflow_uint_max:
	call	fpoverflow
	mov	eax,#UINT_MAX
	ret

! ftoi is like dtoi except ebx points to a float instead of a double.
! This is a quickly-written slowish version that does not take advantage
! of the float being smaller.

	.globl ftoi
	.globl ftol
	.align	ALIGNMENT
ftoi:
ftol:
	call	Fpushf
	mov	ebx,esp
	call	dtoi
	add	esp,#D_SIZE
	ret