xref: /linux/arch/x86/math-emu/reg_norm.S (revision ca55b2fef3a9373fcfc30f82fd26bc7fccbda732)
1/*---------------------------------------------------------------------------+
2 |  reg_norm.S                                                               |
3 |                                                                           |
4 | Copyright (C) 1992,1993,1994,1995,1997                                    |
5 |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
6 |                       Australia.  E-mail billm@suburbia.net               |
7 |                                                                           |
8 | Normalize the value in a FPU_REG.                                         |
9 |                                                                           |
10 | Call from C as:                                                           |
11 |    int FPU_normalize(FPU_REG *n)                                          |
12 |                                                                           |
13 |    int FPU_normalize_nuo(FPU_REG *n)                                      |
14 |                                                                           |
15 |    Return value is the tag of the answer, or-ed with FPU_Exception if     |
16 |    one was raised, or -1 on internal error.                               |
17 |                                                                           |
18 +---------------------------------------------------------------------------*/
19
20#include "fpu_emu.h"
21
22
23.text
24ENTRY(FPU_normalize)
25	pushl	%ebp
26	movl	%esp,%ebp
27	pushl	%ebx
28
29	movl	PARAM1,%ebx
30
31	movl	SIGH(%ebx),%edx
32	movl	SIGL(%ebx),%eax
33
34	orl	%edx,%edx	/* ms bits */
35	js	L_done		/* Already normalized */
36	jnz	L_shift_1	/* Shift left 1 - 31 bits */
37
38	orl	%eax,%eax
39	jz	L_zero		/* The contents are zero */
40
41	movl	%eax,%edx
42	xorl	%eax,%eax
43	subw	$32,EXP(%ebx)	/* This can cause an underflow */
44
45/* We need to shift left by 1 - 31 bits */
46L_shift_1:
47	bsrl	%edx,%ecx	/* get the required shift in %ecx */
48	subl	$31,%ecx
49	negl	%ecx
50	shld	%cl,%eax,%edx
51	shl	%cl,%eax
52	subw	%cx,EXP(%ebx)	/* This can cause an underflow */
53
54	movl	%edx,SIGH(%ebx)
55	movl	%eax,SIGL(%ebx)
56
57L_done:
58	cmpw	EXP_OVER,EXP(%ebx)
59	jge	L_overflow
60
61	cmpw	EXP_UNDER,EXP(%ebx)
62	jle	L_underflow
63
64L_exit_valid:
65	movl	TAG_Valid,%eax
66
67	/* Convert the exponent to 80x87 form. */
68	addw	EXTENDED_Ebias,EXP(%ebx)
69	andw	$0x7fff,EXP(%ebx)
70
71L_exit:
72	popl	%ebx
73	leave
74	ret
75
76
77L_zero:
78	movw	$0,EXP(%ebx)
79	movl	TAG_Zero,%eax
80	jmp	L_exit
81
82L_underflow:
83	/* Convert the exponent to 80x87 form. */
84	addw	EXTENDED_Ebias,EXP(%ebx)
85	push	%ebx
86	call	arith_underflow
87	pop	%ebx
88	jmp	L_exit
89
90L_overflow:
91	/* Convert the exponent to 80x87 form. */
92	addw	EXTENDED_Ebias,EXP(%ebx)
93	push	%ebx
94	call	arith_overflow
95	pop	%ebx
96	jmp	L_exit
97
98
99
100/* Normalise without reporting underflow or overflow */
101ENTRY(FPU_normalize_nuo)
102	pushl	%ebp
103	movl	%esp,%ebp
104	pushl	%ebx
105
106	movl	PARAM1,%ebx
107
108	movl	SIGH(%ebx),%edx
109	movl	SIGL(%ebx),%eax
110
111	orl	%edx,%edx	/* ms bits */
112	js	L_exit_nuo_valid	/* Already normalized */
113	jnz	L_nuo_shift_1	/* Shift left 1 - 31 bits */
114
115	orl	%eax,%eax
116	jz	L_exit_nuo_zero		/* The contents are zero */
117
118	movl	%eax,%edx
119	xorl	%eax,%eax
120	subw	$32,EXP(%ebx)	/* This can cause an underflow */
121
122/* We need to shift left by 1 - 31 bits */
123L_nuo_shift_1:
124	bsrl	%edx,%ecx	/* get the required shift in %ecx */
125	subl	$31,%ecx
126	negl	%ecx
127	shld	%cl,%eax,%edx
128	shl	%cl,%eax
129	subw	%cx,EXP(%ebx)	/* This can cause an underflow */
130
131	movl	%edx,SIGH(%ebx)
132	movl	%eax,SIGL(%ebx)
133
134L_exit_nuo_valid:
135	movl	TAG_Valid,%eax
136
137	popl	%ebx
138	leave
139	ret
140
141L_exit_nuo_zero:
142	movl	TAG_Zero,%eax
143	movw	EXP_UNDER,EXP(%ebx)
144
145	popl	%ebx
146	leave
147	ret
148