OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [i386/] [math-emu/] [reg_div.S] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
        .file   "reg_div.S"
2
/*---------------------------------------------------------------------------+
3
 |  reg_div.S                                                                |
4
 |                                                                           |
5
 | Divide one FPU_REG by another and put the result in a destination FPU_REG.|
6
 |                                                                           |
7
 | Copyright (C) 1992,1993,1994,1995                                         |
8
 |                       W. Metzenthen, 22 Parker St, Ormond, Vic 3163,      |
9
 |                       Australia.  E-mail billm@jacobi.maths.monash.edu.au |
10
 |                                                                           |
11
 | Call from C as:                                                           |
12
 |   void reg_div(FPU_REG *a, FPU_REG *b, FPU_REG *dest,                     |
13
 |                                    unsigned int control_word)             |
14
 |                                                                           |
15
 +---------------------------------------------------------------------------*/
16
 
17
#include "exception.h"
18
#include "fpu_emu.h"
19
 
20
 
21
.text
22
ENTRY(reg_div)
23
        pushl   %ebp
24
        movl    %esp,%ebp
25
#ifndef NON_REENTRANT_FPU
26
        subl    $28,%esp        /* Needed by divide_kernel */
27
#endif NON_REENTRANT_FPU
28
 
29
        pushl   %esi
30
        pushl   %edi
31
        pushl   %ebx
32
 
33
        movl    PARAM1,%esi
34
        movl    PARAM2,%ebx
35
        movl    PARAM3,%edi
36
 
37
        movb    TAG(%esi),%al
38
        orb     TAG(%ebx),%al
39
 
40
        jne     L_div_special           /* Not (both numbers TW_Valid) */
41
 
42
#ifdef DENORM_OPERAND
43
/* Check for denormals */
44
        cmpl    EXP_UNDER,EXP(%esi)
45
        jg      xL_arg1_not_denormal
46
 
47
        call    SYMBOL_NAME(denormal_operand)
48
        orl     %eax,%eax
49
        jnz     fpu_Arith_exit
50
 
51
xL_arg1_not_denormal:
52
        cmpl    EXP_UNDER,EXP(%ebx)
53
        jg      xL_arg2_not_denormal
54
 
55
        call    SYMBOL_NAME(denormal_operand)
56
        orl     %eax,%eax
57
        jnz     fpu_Arith_exit
58
 
59
xL_arg2_not_denormal:
60
#endif DENORM_OPERAND
61
 
62
/* Both arguments are TW_Valid */
63
        movb    TW_Valid,TAG(%edi)
64
 
65
        movb    SIGN(%esi),%cl
66
        cmpb    %cl,SIGN(%ebx)
67
        setne   (%edi)        /* Set the sign, requires SIGN_NEG=1, SIGN_POS=0 */
68
 
69
        movl    EXP(%esi),%edx
70
        movl    EXP(%ebx),%eax
71
        subl    %eax,%edx
72
        addl    EXP_BIAS,%edx
73
        movl    %edx,EXP(%edi)
74
 
75
        jmp     SYMBOL_NAME(divide_kernel)
76
 
77
 
78
/*-----------------------------------------------------------------------*/
79
L_div_special:
80
        cmpb    TW_NaN,TAG(%esi)        /* A NaN with anything to give NaN */
81
        je      L_arg1_NaN
82
 
83
        cmpb    TW_NaN,TAG(%ebx)        /* A NaN with anything to give NaN */
84
        jne     L_no_NaN_arg
85
 
86
/* Operations on NaNs */
87
L_arg1_NaN:
88
L_arg2_NaN:
89
        pushl   %edi                    /* Destination */
90
        pushl   %esi
91
        pushl   %ebx                    /* Ordering is important here */
92
        call    SYMBOL_NAME(real_2op_NaN)
93
        jmp     LDiv_exit
94
 
95
/* Invalid operations */
96
L_zero_zero:
97
L_inf_inf:
98
        pushl   %edi                    /* Destination */
99
        call    SYMBOL_NAME(arith_invalid) /* 0/0 or Infinity/Infinity */
100
        jmp     LDiv_exit
101
 
102
L_no_NaN_arg:
103
        cmpb    TW_Infinity,TAG(%esi)
104
        jne     L_arg1_not_inf
105
 
106
        cmpb    TW_Infinity,TAG(%ebx)
107
        je      L_inf_inf               /* invalid operation */
108
 
109
        cmpb    TW_Valid,TAG(%ebx)
110
        je      L_inf_valid
111
 
112
#ifdef PARANOID
113
        /* arg2 must be zero or valid */
114
        cmpb    TW_Zero,TAG(%ebx)
115
        ja      L_unknown_tags
116
#endif PARANOID
117
 
118
        /* Note that p16-9 says that infinity/0 returns infinity */
119
        jmp     L_copy_arg1             /* Answer is Inf */
120
 
121
L_inf_valid:
122
#ifdef DENORM_OPERAND
123
        cmpl    EXP_UNDER,EXP(%ebx)
124
        jg      L_copy_arg1             /* Answer is Inf */
125
 
126
        call    SYMBOL_NAME(denormal_operand)
127
        orl     %eax,%eax
128
        jnz     fpu_Arith_exit
129
#endif DENORM_OPERAND
130
 
131
        jmp     L_copy_arg1             /* Answer is Inf */
132
 
133
L_arg1_not_inf:
134
        cmpb    TW_Zero,TAG(%ebx)       /* Priority to div-by-zero error */
135
        jne     L_arg2_not_zero
136
 
137
        cmpb    TW_Zero,TAG(%esi)
138
        je      L_zero_zero             /* invalid operation */
139
 
140
#ifdef PARANOID
141
        /* arg1 must be valid */
142
        cmpb    TW_Valid,TAG(%esi)
143
        ja      L_unknown_tags
144
#endif PARANOID
145
 
146
/* Division by zero error */
147
        pushl   %edi                    /* destination */
148
        movb    SIGN(%esi),%al
149
        xorb    SIGN(%ebx),%al
150
        pushl   %eax                    /* lower 8 bits have the sign */
151
        call    SYMBOL_NAME(divide_by_zero)
152
        jmp     LDiv_exit
153
 
154
L_arg2_not_zero:
155
        cmpb    TW_Infinity,TAG(%ebx)
156
        jne     L_arg2_not_inf
157
 
158
#ifdef DENORM_OPERAND
159
        cmpb    TW_Valid,TAG(%esi)
160
        jne     L_return_zero
161
 
162
        cmpl    EXP_UNDER,EXP(%esi)
163
        jg      L_return_zero           /* Answer is zero */
164
 
165
        call    SYMBOL_NAME(denormal_operand)
166
        orl     %eax,%eax
167
        jnz     fpu_Arith_exit
168
#endif DENORM_OPERAND
169
 
170
        jmp     L_return_zero           /* Answer is zero */
171
 
172
L_arg2_not_inf:
173
 
174
#ifdef PARANOID
175
        cmpb    TW_Zero,TAG(%esi)
176
        jne     L_unknown_tags
177
#endif PARANOID
178
 
179
        /* arg1 is zero, arg2 is not Infinity or a NaN */
180
 
181
#ifdef DENORM_OPERAND
182
        cmpl    EXP_UNDER,EXP(%ebx)
183
        jg      L_copy_arg1             /* Answer is zero */
184
 
185
        call    SYMBOL_NAME(denormal_operand)
186
        orl     %eax,%eax
187
        jnz     fpu_Arith_exit
188
#endif DENORM_OPERAND
189
 
190
L_copy_arg1:
191
        movb    TAG(%esi),%ax
192
        movb    %ax,TAG(%edi)
193
        movl    EXP(%esi),%eax
194
        movl    %eax,EXP(%edi)
195
        movl    SIGL(%esi),%eax
196
        movl    %eax,SIGL(%edi)
197
        movl    SIGH(%esi),%eax
198
        movl    %eax,SIGH(%edi)
199
 
200
LDiv_set_result_sign:
201
        movb    SIGN(%esi),%cl
202
        cmpb    %cl,SIGN(%ebx)
203
        jne     LDiv_negative_result
204
 
205
        movb    SIGN_POS,SIGN(%edi)
206
        xorl    %eax,%eax               /* Valid result */
207
        jmp     LDiv_exit
208
 
209
LDiv_negative_result:
210
        movb    SIGN_NEG,SIGN(%edi)
211
        xorl    %eax,%eax               /* Valid result */
212
 
213
LDiv_exit:
214
#ifndef NON_REENTRANT_FPU
215
        leal    -40(%ebp),%esp
216
#else
217
        leal    -12(%ebp),%esp
218
#endif NON_REENTRANT_FPU
219
 
220
        popl    %ebx
221
        popl    %edi
222
        popl    %esi
223
        leave
224
        ret
225
 
226
 
227
L_return_zero:
228
        xorl    %eax,%eax
229
        movl    %eax,SIGH(%edi)
230
        movl    %eax,SIGL(%edi)
231
        movl    EXP_UNDER,EXP(%edi)
232
        movb    TW_Zero,TAG(%edi)
233
        jmp     LDiv_set_result_sign
234
 
235
#ifdef PARANOID
236
L_unknown_tags:
237
        pushl   EX_INTERNAL | 0x208
238
        call    EXCEPTION
239
 
240
        /* Generate a NaN for unknown tags */
241
        movl    SYMBOL_NAME(CONST_QNaN),%eax
242
        movl    %eax,(%edi)
243
        movl    SYMBOL_NAME(CONST_QNaN)+4,%eax
244
        movl    %eax,SIGL(%edi)
245
        movl    SYMBOL_NAME(CONST_QNaN)+8,%eax
246
        movl    %eax,SIGH(%edi)
247
        jmp     LDiv_exit               /* %eax is nz */
248
#endif PARANOID

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.