0001
0002 .file "reg_u_div.S"
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "exception.h"
0027 #include "fpu_emu.h"
0028 #include "control_w.h"
0029
0030
0031
0032
0033
0034
0035 #ifndef NON_REENTRANT_FPU
0036
0037
0038
0039
0040
0041 #define FPU_accum_3 -4(%ebp)
0042 #define FPU_accum_2 -8(%ebp)
0043 #define FPU_accum_1 -12(%ebp)
0044 #define FPU_accum_0 -16(%ebp)
0045 #define FPU_result_1 -20(%ebp)
0046 #define FPU_result_2 -24(%ebp)
0047 #define FPU_ovfl_flag -28(%ebp)
0048
0049 #else
0050 .data
0051
0052
0053
0054
0055
0056 .align 4,0
0057 FPU_accum_3:
0058 .long 0
0059 FPU_accum_2:
0060 .long 0
0061 FPU_accum_1:
0062 .long 0
0063 FPU_accum_0:
0064 .long 0
0065 FPU_result_1:
0066 .long 0
0067 FPU_result_2:
0068 .long 0
0069 FPU_ovfl_flag:
0070 .byte 0
0071 #endif
0072
0073 #define REGA PARAM1
0074 #define REGB PARAM2
0075 #define DEST PARAM3
0076
0077 .text
0078 SYM_FUNC_START(FPU_u_div)
0079 pushl %ebp
0080 movl %esp,%ebp
0081 #ifndef NON_REENTRANT_FPU
0082 subl $28,%esp
0083 #endif
0084
0085 pushl %esi
0086 pushl %edi
0087 pushl %ebx
0088
0089 movl REGA,%esi
0090 movl REGB,%ebx
0091 movl DEST,%edi
0092
0093 movswl EXP(%esi),%edx
0094 movswl EXP(%ebx),%eax
0095 subl %eax,%edx
0096 addl EXP_BIAS,%edx
0097
0098
0099 cmpl EXP_WAY_UNDER,%edx
0100 jg xExp_not_underflow
0101
0102
0103 movl EXP_WAY_UNDER,%edx
0104
0105 xExp_not_underflow:
0106
0107 movw %dx,EXP(%edi)
0108
0109 #ifdef PARANOID
0110
0111
0112 testl $0x80000000, SIGH(%ebx)
0113 je L_bugged
0114 #endif
0115
0116
0117 cmpl $0,SIGL(%ebx)
0118 jnz L_Full_Division
0119
0120
0121 movl SIGH(%ebx),%ecx
0122 movl SIGH(%esi),%edx
0123 movl SIGL(%esi),%eax
0124
0125 cmpl %ecx,%edx
0126 setaeb FPU_ovfl_flag
0127 jb L_no_adjust
0128
0129 subl %ecx,%edx
0130
0131 L_no_adjust:
0132
0133 divl %ecx
0134 movl %eax,FPU_result_2
0135
0136
0137 xorl %eax,%eax
0138 divl %ecx
0139 movl %eax,FPU_result_1
0140
0141
0142 xorl %eax,%eax
0143 divl %ecx
0144
0145 testb $255,FPU_ovfl_flag
0146 je L_no_overflow
0147
0148
0149
0150 incw EXP(%edi)
0151
0152
0153 stc
0154 rcrl FPU_result_2
0155 rcrl FPU_result_1
0156 rcrl %eax
0157
0158 L_no_overflow:
0159 jmp LRound_precision
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180 L_Full_Division:
0181
0182 movl SIGL(%esi),%eax
0183 movl %eax,FPU_accum_2
0184 movl SIGH(%esi),%eax
0185 movl %eax,FPU_accum_3
0186 xorl %eax,%eax
0187 movl %eax,FPU_accum_1
0188 movl %eax,FPU_accum_0
0189
0190 movl SIGL(%esi),%eax
0191 movl SIGH(%esi),%edx
0192
0193
0194
0195
0196
0197 movb $0,FPU_ovfl_flag
0198 cmpl SIGH(%ebx),%edx
0199 jb LLess_than_1
0200 ja LGreater_than_1
0201
0202 cmpl SIGL(%ebx),%eax
0203 jb LLess_than_1
0204
0205 LGreater_than_1:
0206
0207 setaeb FPU_ovfl_flag
0208
0209 subl SIGL(%ebx),%eax
0210 sbbl SIGH(%ebx),%edx
0211 movl %eax,FPU_accum_2
0212 movl %edx,FPU_accum_3
0213
0214 LLess_than_1:
0215
0216
0217
0218
0219 movl SIGH(%ebx),%ecx
0220 addl $1,%ecx
0221 jnc LFirst_div_not_1
0222
0223
0224
0225 mov %edx,%eax
0226 jmp LFirst_div_done
0227
0228 LFirst_div_not_1:
0229 divl %ecx
0230
0231
0232 LFirst_div_done:
0233 movl %eax,FPU_result_2
0234
0235 mull SIGH(%ebx)
0236
0237 subl %eax,FPU_accum_2
0238 sbbl %edx,FPU_accum_3
0239
0240 movl FPU_result_2,%eax
0241 mull SIGL(%ebx)
0242
0243 subl %eax,FPU_accum_1
0244 sbbl %edx,FPU_accum_2
0245 sbbl $0,FPU_accum_3
0246 je LDo_2nd_32_bits
0247
0248 #ifdef PARANOID
0249 jb L_bugged_1
0250 #endif
0251
0252
0253 incl FPU_result_2
0254
0255 movl SIGL(%ebx),%eax
0256 movl SIGH(%ebx),%edx
0257 subl %eax,FPU_accum_1
0258 sbbl %edx,FPU_accum_2
0259
0260 #ifdef PARANOID
0261 sbbl $0,FPU_accum_3
0262 jne L_bugged_1
0263 #endif
0264
0265
0266
0267
0268
0269 LDo_2nd_32_bits:
0270 movl FPU_accum_2,%edx
0271 movl FPU_accum_1,%eax
0272
0273
0274 cmpl SIGH(%ebx),%edx
0275 jb LDo_2nd_div
0276 ja LPrevent_2nd_overflow
0277
0278 cmpl SIGL(%ebx),%eax
0279 jb LDo_2nd_div
0280
0281 LPrevent_2nd_overflow:
0282
0283
0284 subl SIGL(%ebx),%eax
0285 sbbl SIGH(%ebx),%edx
0286 movl %edx,FPU_accum_2
0287 movl %eax,FPU_accum_1
0288
0289 incl FPU_result_2
0290
0291 #ifdef PARANOID
0292 je L_bugged_2
0293 #endif
0294
0295 LDo_2nd_div:
0296 cmpl $0,%ecx
0297 jnz LSecond_div_not_1
0298
0299
0300 mov %edx,%eax
0301 jmp LSecond_div_done
0302
0303 LSecond_div_not_1:
0304 divl %ecx
0305
0306 LSecond_div_done:
0307 movl %eax,FPU_result_1
0308
0309 mull SIGH(%ebx)
0310
0311 subl %eax,FPU_accum_1
0312 sbbl %edx,FPU_accum_2
0313
0314 #ifdef PARANOID
0315 jc L_bugged_2
0316 #endif
0317
0318 movl FPU_result_1,%eax
0319 mull SIGL(%ebx)
0320
0321 subl %eax,FPU_accum_0
0322 sbbl %edx,FPU_accum_1
0323 sbbl $0,FPU_accum_2
0324
0325 #ifdef PARANOID
0326 jc L_bugged_2
0327 #endif
0328
0329 jz LDo_3rd_32_bits
0330
0331 #ifdef PARANOID
0332 cmpl $1,FPU_accum_2
0333 jne L_bugged_2
0334 #endif
0335
0336
0337 movl SIGL(%ebx),%eax
0338 movl SIGH(%ebx),%edx
0339 subl %eax,FPU_accum_0
0340 sbbl %edx,FPU_accum_1
0341 sbbl $0,FPU_accum_2
0342
0343 #ifdef PARANOID
0344 jc L_bugged_2
0345 jne L_bugged_2
0346 #endif
0347
0348 addl $1,FPU_result_1
0349 adcl $0,FPU_result_2
0350
0351 #ifdef PARANOID
0352 jc L_bugged_2
0353 #endif
0354
0355
0356
0357
0358
0359 LDo_3rd_32_bits:
0360 movl FPU_accum_1,%edx
0361 movl FPU_accum_0,%eax
0362
0363
0364 cmpl SIGH(%ebx),%edx
0365 jb LRound_prep
0366 ja LPrevent_3rd_overflow
0367
0368 cmpl SIGL(%ebx),%eax
0369 jb LRound_prep
0370
0371 LPrevent_3rd_overflow:
0372
0373 subl SIGL(%ebx),%eax
0374 sbbl SIGH(%ebx),%edx
0375 movl %edx,FPU_accum_1
0376 movl %eax,FPU_accum_0
0377
0378 addl $1,FPU_result_1
0379 adcl $0,FPU_result_2
0380 jne LRound_prep
0381 jnc LRound_prep
0382
0383
0384 movb $255,FPU_ovfl_flag
0385
0386 LRound_prep:
0387
0388
0389
0390
0391
0392 movl FPU_accum_0,%ecx
0393 movl FPU_accum_1,%edx
0394 movl %ecx,%eax
0395 orl %edx,%eax
0396 jz LRound_ovfl
0397
0398
0399 clc
0400 rcll $1,%ecx
0401 rcll $1,%edx
0402 jc LRound_large
0403
0404 subl SIGL(%ebx),%ecx
0405 sbbl SIGH(%ebx),%edx
0406 jnc LRound_not_small
0407
0408 movl $0x70000000,%eax
0409 jmp LRound_ovfl
0410
0411 LRound_not_small:
0412 jnz LRound_large
0413
0414 movl $0x80000000,%eax
0415 jmp LRound_ovfl
0416
0417 LRound_large:
0418 movl $0xff000000,%eax
0419
0420 LRound_ovfl:
0421
0422
0423 testb $255,FPU_ovfl_flag
0424 je LRound_precision
0425
0426 incw EXP(%edi)
0427
0428
0429 stc
0430 rcrl FPU_result_2
0431 rcrl FPU_result_1
0432 rcrl %eax
0433
0434
0435 LRound_precision:
0436 decw EXP(%edi)
0437
0438 movl %eax,%edx
0439 movl FPU_result_1,%ebx
0440 movl FPU_result_2,%eax
0441 jmp fpu_reg_round
0442
0443
0444 #ifdef PARANOID
0445
0446 L_bugged:
0447 pushl EX_INTERNAL|0x202
0448 call EXCEPTION
0449 pop %ebx
0450 jmp L_exit
0451
0452 L_bugged_1:
0453 pushl EX_INTERNAL|0x203
0454 call EXCEPTION
0455 pop %ebx
0456 jmp L_exit
0457
0458 L_bugged_2:
0459 pushl EX_INTERNAL|0x204
0460 call EXCEPTION
0461 pop %ebx
0462 jmp L_exit
0463
0464 L_exit:
0465 movl $-1,%eax
0466 popl %ebx
0467 popl %edi
0468 popl %esi
0469
0470 leave
0471 RET
0472 #endif
0473
0474 SYM_FUNC_END(FPU_u_div)