1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "exception.h"
21#include "reg_constant.h"
22#include "fpu_emu.h"
23#include "fpu_system.h"
24
25
26
27
28int FPU_div(int flags, int rm, int control_w)
29{
30 FPU_REG x, y;
31 FPU_REG const *a, *b, *st0_ptr, *st_ptr;
32 FPU_REG *dest;
33 u_char taga, tagb, signa, signb, sign, saved_sign;
34 int tag, deststnr;
35
36 if (flags & DEST_RM)
37 deststnr = rm;
38 else
39 deststnr = 0;
40
41 if (flags & REV) {
42 b = &st(0);
43 st0_ptr = b;
44 tagb = FPU_gettag0();
45 if (flags & LOADED) {
46 a = (FPU_REG *) rm;
47 taga = flags & 0x0f;
48 } else {
49 a = &st(rm);
50 st_ptr = a;
51 taga = FPU_gettagi(rm);
52 }
53 } else {
54 a = &st(0);
55 st0_ptr = a;
56 taga = FPU_gettag0();
57 if (flags & LOADED) {
58 b = (FPU_REG *) rm;
59 tagb = flags & 0x0f;
60 } else {
61 b = &st(rm);
62 st_ptr = b;
63 tagb = FPU_gettagi(rm);
64 }
65 }
66
67 signa = getsign(a);
68 signb = getsign(b);
69
70 sign = signa ^ signb;
71
72 dest = &st(deststnr);
73 saved_sign = getsign(dest);
74
75 if (!(taga | tagb)) {
76
77 reg_copy(a, &x);
78 reg_copy(b, &y);
79 setpositive(&x);
80 setpositive(&y);
81 tag = FPU_u_div(&x, &y, dest, control_w, sign);
82
83 if (tag < 0)
84 return tag;
85
86 FPU_settagi(deststnr, tag);
87 return tag;
88 }
89
90 if (taga == TAG_Special)
91 taga = FPU_Special(a);
92 if (tagb == TAG_Special)
93 tagb = FPU_Special(b);
94
95 if (((taga == TAG_Valid) && (tagb == TW_Denormal))
96 || ((taga == TW_Denormal) && (tagb == TAG_Valid))
97 || ((taga == TW_Denormal) && (tagb == TW_Denormal))) {
98 if (denormal_operand() < 0)
99 return FPU_Exception;
100
101 FPU_to_exp16(a, &x);
102 FPU_to_exp16(b, &y);
103 tag = FPU_u_div(&x, &y, dest, control_w, sign);
104 if (tag < 0)
105 return tag;
106
107 FPU_settagi(deststnr, tag);
108 return tag;
109 } else if ((taga <= TW_Denormal) && (tagb <= TW_Denormal)) {
110 if (tagb != TAG_Zero) {
111
112 if (tagb == TW_Denormal) {
113 if (denormal_operand() < 0)
114 return FPU_Exception;
115 }
116
117
118 FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
119 setsign(dest, sign);
120 return TAG_Zero;
121 }
122
123 if (taga == TAG_Zero) {
124
125 return arith_invalid(deststnr);
126 }
127
128 return FPU_divide_by_zero(deststnr, sign);
129 }
130
131 else if ((taga == TW_NaN) || (tagb == TW_NaN)) {
132 if (flags & LOADED)
133 return real_2op_NaN((FPU_REG *) rm, flags & 0x0f, 0,
134 st0_ptr);
135
136 if (flags & DEST_RM) {
137 int tag;
138 tag = FPU_gettag0();
139 if (tag == TAG_Special)
140 tag = FPU_Special(st0_ptr);
141 return real_2op_NaN(st0_ptr, tag, rm,
142 (flags & REV) ? st0_ptr : &st(rm));
143 } else {
144 int tag;
145 tag = FPU_gettagi(rm);
146 if (tag == TAG_Special)
147 tag = FPU_Special(&st(rm));
148 return real_2op_NaN(&st(rm), tag, 0,
149 (flags & REV) ? st0_ptr : &st(rm));
150 }
151 } else if (taga == TW_Infinity) {
152 if (tagb == TW_Infinity) {
153
154 return arith_invalid(deststnr);
155 } else {
156
157 if ((tagb == TW_Denormal) && (denormal_operand() < 0))
158 return FPU_Exception;
159
160
161
162 FPU_copy_to_regi(a, TAG_Special, deststnr);
163 setsign(dest, sign);
164 return taga;
165 }
166 } else if (tagb == TW_Infinity) {
167 if ((taga == TW_Denormal) && (denormal_operand() < 0))
168 return FPU_Exception;
169
170
171 FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
172 setsign(dest, sign);
173 return TAG_Zero;
174 }
175#ifdef PARANOID
176 else {
177 EXCEPTION(EX_INTERNAL | 0x102);
178 return FPU_Exception;
179 }
180#endif
181
182 return 0;
183}
184