2 // Copyright (C) 1993-2003 by Digital Mars, www.digitalmars.com
4 // Written by Walter Bright
8 // Compiler runtime support for 64 bit longs
13 /***************************************
14 * Unsigned long divide.
18 * [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
19 * [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
33 // left justify [ECX,EBX] and leave count of shifts + 1 in EBP
35 mov EBP,1 ; // at least 1 shift
36 test ECX,ECX ; // left justified?
43 xor BL,BL ; // [ECX,EBX] <<= 8
47 L2: inc EBP ; // another shift
49 rcl ECX,1 ; // [ECX,EBX] <<= 1
50 jno L2 ; // not left justified yet
53 mov EDI,EBX ; // [ESI,EDI] = divisor
56 mov EBX,EAX ; // [ECX,EBX] = [EDX,EAX]
58 cdq ; // [EDX,EAX] = 0
60 L4: cmp ESI,ECX ; // is [ECX,EBX] > [ESI,EDI]?
62 jb L5 ; // definitely less than
63 cmp EDI,EBX ; // check low order word
66 sbb ECX,ESI ; // [ECX,EBX] -= [ESI,EDI]
67 stc ; // rotate in a 1
69 rcl EDX,1 ; // [EDX,EAX] = ([EDX,EAX] << 1) + C
71 rcr EDI,1 ; // [ESI,EDI] >>= 1
72 dec EBP ; // control count
78 cwd ; // quotient is -1
80 // mov EBX,ECX ; // remainder is 0 (ECX and EBX already 0)
86 // Both high words are 0, we can use the DIV instruction
89 mov EDX,ECX ; // EDX = ECX = 0
93 D3: // Divide [EDX,EAX] by EBX
110 /***************************************
111 * Signed long divide.
113 * [EDX,EAX],[ECX,EBX]
115 * [EDX,EAX] = [EDX,EAX] / [ECX,EBX]
116 * [ECX,EBX] = [EDX,EAX] % [ECX,EBX]
125 test EDX,EDX ; // [EDX,EAX] negative?
127 //neg64 EDX,EAX ; // [EDX,EAX] = -[EDX,EAX]
131 test ECX,ECX ; // [ECX,EBX] negative?
138 //neg64 ECX,EBX ; // remainder same sign as dividend
144 L11: call __ULDIV__ ;
145 //neg64 ECX,EBX ; // remainder same sign as dividend
149 //neg64 EDX,EAX ; // quotient is negative
155 L10: test ECX,ECX ; // [ECX,EBX] negative?
156 jns L12 ; // no (all is positive)
162 //neg64 EDX,EAX ; // quotient is negative
173 /***************************************
174 * Compare [EDX,EAX] with [ECX,EBX]
176 * Returns result in flags
204 // Convert ulong to real
206 private real adjust = cast(real)0x800_0000_0000_0000 * 0x10;
214 and dword ptr 4[ESP], 0x7FFFFFFF ;
215 fild qword ptr [ESP] ;
218 fld real ptr adjust ;
226 // Same as __U64_LDBL, but return result as double in [EDX,EAX]
233 fstp double ptr [ESP] ;
240 // Convert double to ulong
242 private short roundTo0 = 0xFBF;
246 // BUG: should handle NAN's and overflows
251 fld double ptr [ESP] ;
253 fld real ptr adjust ;
260 fld real ptr adjust ;
262 fistp qword ptr [ESP] ;
267 add EDX,0x8000_0000 ;
270 fistp qword ptr [ESP] ;
279 // Convert double in ST0 to uint
283 // BUG: should handle NAN's and overflows
289 fistp qword ptr [ESP] ;