0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include "exception.h"
0021 #include "reg_constant.h"
0022 #include "fpu_emu.h"
0023 #include "fpu_system.h"
0024
0025
0026
0027
0028 int FPU_div(int flags, int rm, int control_w)
0029 {
0030 FPU_REG x, y;
0031 FPU_REG const *a, *b, *st0_ptr, *st_ptr;
0032 FPU_REG *dest;
0033 u_char taga, tagb, signa, signb, sign, saved_sign;
0034 int tag, deststnr;
0035
0036 if (flags & DEST_RM)
0037 deststnr = rm;
0038 else
0039 deststnr = 0;
0040
0041 if (flags & REV) {
0042 b = &st(0);
0043 st0_ptr = b;
0044 tagb = FPU_gettag0();
0045 if (flags & LOADED) {
0046 a = (FPU_REG *) rm;
0047 taga = flags & 0x0f;
0048 } else {
0049 a = &st(rm);
0050 st_ptr = a;
0051 taga = FPU_gettagi(rm);
0052 }
0053 } else {
0054 a = &st(0);
0055 st0_ptr = a;
0056 taga = FPU_gettag0();
0057 if (flags & LOADED) {
0058 b = (FPU_REG *) rm;
0059 tagb = flags & 0x0f;
0060 } else {
0061 b = &st(rm);
0062 st_ptr = b;
0063 tagb = FPU_gettagi(rm);
0064 }
0065 }
0066
0067 signa = getsign(a);
0068 signb = getsign(b);
0069
0070 sign = signa ^ signb;
0071
0072 dest = &st(deststnr);
0073 saved_sign = getsign(dest);
0074
0075 if (!(taga | tagb)) {
0076
0077 reg_copy(a, &x);
0078 reg_copy(b, &y);
0079 setpositive(&x);
0080 setpositive(&y);
0081 tag = FPU_u_div(&x, &y, dest, control_w, sign);
0082
0083 if (tag < 0)
0084 return tag;
0085
0086 FPU_settagi(deststnr, tag);
0087 return tag;
0088 }
0089
0090 if (taga == TAG_Special)
0091 taga = FPU_Special(a);
0092 if (tagb == TAG_Special)
0093 tagb = FPU_Special(b);
0094
0095 if (((taga == TAG_Valid) && (tagb == TW_Denormal))
0096 || ((taga == TW_Denormal) && (tagb == TAG_Valid))
0097 || ((taga == TW_Denormal) && (tagb == TW_Denormal))) {
0098 if (denormal_operand() < 0)
0099 return FPU_Exception;
0100
0101 FPU_to_exp16(a, &x);
0102 FPU_to_exp16(b, &y);
0103 tag = FPU_u_div(&x, &y, dest, control_w, sign);
0104 if (tag < 0)
0105 return tag;
0106
0107 FPU_settagi(deststnr, tag);
0108 return tag;
0109 } else if ((taga <= TW_Denormal) && (tagb <= TW_Denormal)) {
0110 if (tagb != TAG_Zero) {
0111
0112 if (tagb == TW_Denormal) {
0113 if (denormal_operand() < 0)
0114 return FPU_Exception;
0115 }
0116
0117
0118 FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
0119 setsign(dest, sign);
0120 return TAG_Zero;
0121 }
0122
0123 if (taga == TAG_Zero) {
0124
0125 return arith_invalid(deststnr);
0126 }
0127
0128 return FPU_divide_by_zero(deststnr, sign);
0129 }
0130
0131 else if ((taga == TW_NaN) || (tagb == TW_NaN)) {
0132 if (flags & LOADED)
0133 return real_2op_NaN((FPU_REG *) rm, flags & 0x0f, 0,
0134 st0_ptr);
0135
0136 if (flags & DEST_RM) {
0137 int tag;
0138 tag = FPU_gettag0();
0139 if (tag == TAG_Special)
0140 tag = FPU_Special(st0_ptr);
0141 return real_2op_NaN(st0_ptr, tag, rm,
0142 (flags & REV) ? st0_ptr : &st(rm));
0143 } else {
0144 int tag;
0145 tag = FPU_gettagi(rm);
0146 if (tag == TAG_Special)
0147 tag = FPU_Special(&st(rm));
0148 return real_2op_NaN(&st(rm), tag, 0,
0149 (flags & REV) ? st0_ptr : &st(rm));
0150 }
0151 } else if (taga == TW_Infinity) {
0152 if (tagb == TW_Infinity) {
0153
0154 return arith_invalid(deststnr);
0155 } else {
0156
0157 if ((tagb == TW_Denormal) && (denormal_operand() < 0))
0158 return FPU_Exception;
0159
0160
0161
0162 FPU_copy_to_regi(a, TAG_Special, deststnr);
0163 setsign(dest, sign);
0164 return taga;
0165 }
0166 } else if (tagb == TW_Infinity) {
0167 if ((taga == TW_Denormal) && (denormal_operand() < 0))
0168 return FPU_Exception;
0169
0170
0171 FPU_copy_to_regi(&CONST_Z, TAG_Zero, deststnr);
0172 setsign(dest, sign);
0173 return TAG_Zero;
0174 }
0175 #ifdef PARANOID
0176 else {
0177 EXCEPTION(EX_INTERNAL | 0x102);
0178 return FPU_Exception;
0179 }
0180 #endif
0181
0182 return 0;
0183 }