1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
! bcc 386 floating point routines (version 2) -- Fmul, Fmuld, Fmulf
! author: Bruce Evans
#include "fplib.h"
#define FRAME_SIZE (3 * GENREG_SIZE + PC_SIZE)
.extern Fpushf
.extern fpoverflow
.extern fpunderflow
.extern normalize2
.globl Fmul
.align ALIGNMENT
Fmul:
push ebp
push edi
push esi
mov eax,FRAME_SIZE+D_LOW[esp]
mov edx,FRAME_SIZE+D_HIGH[esp]
mov ebx,FRAME_SIZE+D_SIZE+D_LOW[esp]
mov ecx,FRAME_SIZE+D_SIZE+D_HIGH[esp]
call multiplication
mov FRAME_SIZE+D_SIZE+D_LOW[esp],eax
mov FRAME_SIZE+D_SIZE+D_HIGH[esp],edx
pop esi
pop edi
pop ebp
ret #D_SIZE
.globl Fmuld
.align ALIGNMENT
Fmuld:
push ebp
push edi
push esi
mov eax,FRAME_SIZE+D_LOW[esp]
mov edx,FRAME_SIZE+D_HIGH[esp]
mov ecx,D_HIGH[ebx]
mov ebx,D_LOW[ebx]
call multiplication
mov FRAME_SIZE+D_LOW[esp],eax
mov FRAME_SIZE+D_HIGH[esp],edx
pop esi
pop edi
pop ebp
ret
.globl Fmulf
.align ALIGNMENT
Fmulf:
push ebp
push edi
push esi
call Fpushf
pop ebx ! yl
pop ecx ! xu
mov eax,FRAME_SIZE+D_LOW[esp] ! xl
mov edx,FRAME_SIZE+D_HIGH[esp] ! xu
call multiplication
mov FRAME_SIZE+D_LOW[esp],eax
mov FRAME_SIZE+D_HIGH[esp],edx
pop esi
pop edi
pop ebp
ret
.align ALIGNMENT
exp_x_0:
mov edx,#1 << D_EXP_SHIFT ! change exponent from 0 to 1
jmp x_unpacked ! XXX - check for denormal?
.align ALIGNMENT
exp_y_0:
mov ecx,#1 << D_EXP_SHIFT
jmp y_unpacked
.align ALIGNMENT
multiplication:
mov ebp,edx ! xu
xor ebp,ecx ! xu ^ yu
and ebp,#D_SIGN_MASK ! sign of result is difference of signs
mov esi,edx ! free edx for multiplications
and esi,#D_FRAC_MASK ! discard sign and exponent
and edx,#D_EXP_MASK ! exponent(x)
jz exp_x_0
or esi,#D_NORM_MASK ! normalize
x_unpacked:
mov edi,ecx ! this mainly for consistent naming
and edi,#D_FRAC_MASK
and ecx,#D_EXP_MASK ! exponent(y)
jz exp_y_0
or edi,#D_NORM_MASK
y_unpacked:
add ecx,edx ! add exponents
! exponent is in ecx, sign in ebp, operands in esi:eax and edi:ebx, edx is free
! product to go in esi:eax:ebp:ebx
! terminology: x * y = (xu,xl) * (yu,yl)
! = (xu * yu,0,0) + (0,xu * yl + xl * yu,0) + (0,0,xl * yl)
push ecx
push ebp
mov ecx,eax
mul ebx ! xl * yl
mov ebp,edx ! (xl * yl).u in ebp
xchg ebx,eax ! (xl * yl).l in ebx (final), yl in eax
mul esi ! xu * yl
push eax ! (xu * yl).l on stack
push edx ! (xu * yl).u on stack
mov eax,esi ! xu
mul edi ! xu * yu
mov esi,edx ! (xu * yu).u in esi (final except carries)
xchg ecx,eax ! (xu * yu).l in ecx, xl in eax
mul edi ! xl * yu
add ebp,eax ! (xl * yl).u + (xl * yu).l
pop eax ! (xu * yl).u
adc eax,edx ! (xu * yl).u + (xl * yu).u
adc esi,#0
pop edx ! (xu * yl).l
add ebp,edx ! ((xl * yl).u + (xl * yu).l) + (xu * yl).l
adc eax,ecx ! ((xu * yl).u + (xl * yu).u) + (xu * yu).l
adc esi,#0
pop edx ! sign
pop edi ! exponent
sub edi,#(D_EXP_BIAS+1-(D_EXP_BIT+2)) << D_EXP_SHIFT ! adjust
! cmp edi,#(D_EXP_INFINITE-1+(D_EXP_BIT+2)) << D_EXP_SHIFT
! jae outofbounds ! 0 will be caught as underflow by normalize2
cmp edi,#(2*D_EXP_INFINITE-(D_EXP_BIAS+1)+(D_EXP_BIT+2)) << D_EXP_SHIFT
ja underflow
br normalize2
.align ALIGNMENT
overflow:
mov edx,ebp ! put sign in usual reg
call fpoverflow
mov eax,ecx ! XXX - wrong reg
ret
.align ALIGNMENT
underflow:
mov edx,ebp ! put sign in usual reg
neg edi
shr edi,#D_EXP_SHIFT
inc edi
br fpunderflow
|