summaryrefslogtreecommitdiff
path: root/libc/i386fp/ldexp.x
blob: bc9dd03f44432cede28b6bb8bc05ad992b9d026c (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
! bcc 386 floating point routines (version 2) -- _ldexp
! authors: Timothy Murphy (tim@maths.tcd.ie), Bruce Evans

#include "fplib.h"

	.extern	fpoverflow
	.extern	fpunderflow

! void ldexp(double value, int exponent);
! returns value * (2 ** exponent)

	.globl	_ldexp
	.align	ALIGNMENT
_ldexp:
push ebx
#undef PC_SIZE
#define PC_SIZE 8
	mov	ebx,PC_SIZE+D_HIGH[esp]	! upper dword of x
	mov	ecx,PC_SIZE+D_SIZE[esp]	! exponent arg
	mov	eax,ebx		! extract exponent (of x) here
	and	eax,#D_EXP_MASK
!	jz	exp_y_0		! may need check for preposterous exponent arg too

	shr	eax,#D_EXP_SHIFT	! shift to low bits just for testing
	jz	underflow	! denormal?
	add	eax,ecx		! test-add the exponents
	jz	underflow	! XXX probably need to fiddle norm bit
	cmp	eax,#D_EXP_INFINITE	! check if still within range
	jae	outofbounds	! the unsigned compare catches all overflow cases
				! because the exponent of x is non-negative

	shl	ecx,#D_EXP_SHIFT	! shift exponent arg bits into final position ...
	add	ebx,ecx		! ... safe to add it to exponent of x now
	mov	eax,PC_SIZE+D_LOW[esp]	! lower dword of x
mov edx,ebx
pop ebx
	ret


	.align	ALIGNMENT
outofbounds:
	test	ecx,ecx		! overflow or underflow?
	jns	overflow
underflow:
	mov	edx,ebx		! put sign in usual reg
	push	edi
	push	esi
	mov	edi,eax		! put exponent in usual reg
	mov	eax,2*GENREG_SIZE+PC_SIZE+D_LOW[esp]
				! put lower dword of x in usual reg
	mov	esi,ebx		! put upper dword of x in usual reg
	and	esi,#D_EXP_MASK | D_FRAC_MASK
	test	esi,#D_EXP_MASK
	jz	foo
	and	esi,#D_FRAC_MASK
	or	esi,#D_NORM_MASK
foo:
	neg	edi
!	inc	edi		! XXX ?
	call	fpunderflow
	pop	esi
	pop	edi
	mov	ebx,edx		! XXX = wrong reg
pop ebx
	ret

	.align	ALIGNMENT
overflow:
	mov	edx,ebx		! put sign in usual reg
	call	fpoverflow
	mov	eax,ecx		! XXX = wrong reg
	mov	ebx,edx		! XXX = wrong reg
pop ebx
	ret