1/* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Run-Time Library 5 * FILE: lib/sdk/crt/math/i386/alldiv_asm.s 6 * PROGRAMER: Alex Ionescu (alex@relsoft.net) 7 * 8 * Copyright (C) 2002 Michael Ringgaard. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the project nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES// LOSS OF USE, DATA, OR PROFITS// OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#include <asm.inc> 38 39PUBLIC __alldiv 40 41/* FUNCTIONS ***************************************************************/ 42.code 43 44// 45// lldiv - signed long divide 46// 47// Purpose: 48// Does a signed long divide of the arguments. Arguments are 49// not changed. 50// 51// Entry: 52// Arguments are passed on the stack: 53// 1st pushed: divisor (QWORD) 54// 2nd pushed: dividend (QWORD) 55// 56// Exit: 57// EDX:EAX contains the quotient (dividend/divisor) 58// NOTE: this routine removes the parameters from the stack. 59// 60// Uses: 61// ECX 62// 63 64__alldiv: 65 66 push edi 67 push esi 68 push ebx 69 70// Set up the local stack and save the index registers. When this is done 71// the stack frame will look as follows (assuming that the expression a/b will 72// generate a call to lldiv(a, b)): 73// 74// ----------------- 75// | | 76// |---------------| 77// | | 78// |--divisor (b)--| 79// | | 80// |---------------| 81// | | 82// |--dividend (a)-| 83// | | 84// |---------------| 85// | return addr** | 86// |---------------| 87// | EDI | 88// |---------------| 89// | ESI | 90// |---------------| 91// ESP---->| EBX | 92// ----------------- 93// 94 95#define DVNDLO [esp + 16] // stack address of dividend (a) 96#define DVNDHI [esp + 20] // stack address of dividend (a) 97#define DVSRLO [esp + 24] // stack address of divisor (b) 98#define DVSRHI [esp + 28] // stack address of divisor (b) 99 100// Determine sign of the result (edi = 0 if result is positive, non-zero 101// otherwise) and make operands positive. 102 103 xor edi,edi // result sign assumed positive 104 105 mov eax,DVNDHI // hi word of a 106 or eax,eax // test to see if signed 107 jge short L1 // skip rest if a is already positive 108 inc edi // complement result sign flag 109 mov edx,DVNDLO // lo word of a 110 neg eax // make a positive 111 neg edx 112 sbb eax,0 113 mov DVNDHI,eax // save positive value 114 mov DVNDLO,edx 115L1: 116 mov eax,DVSRHI // hi word of b 117 or eax,eax // test to see if signed 118 jge short L2 // skip rest if b is already positive 119 inc edi // complement the result sign flag 120 mov edx,DVSRLO // lo word of a 121 neg eax // make b positive 122 neg edx 123 sbb eax,0 124 mov DVSRHI,eax // save positive value 125 mov DVSRLO,edx 126L2: 127 128// 129// Now do the divide. First look to see if the divisor is less than 4194304K. 130// If so, then we can use a simple algorithm with word divides, otherwise 131// things get a little more complex. 132// 133// NOTE - eax currently contains the high order word of DVSR 134// 135 136 or eax,eax // check to see if divisor < 4194304K 137 jnz short L3 // nope, gotta do this the hard way 138 mov ecx,DVSRLO // load divisor 139 mov eax,DVNDHI // load high word of dividend 140 xor edx,edx 141 div ecx // eax <- high order bits of quotient 142 mov ebx,eax // save high bits of quotient 143 mov eax,DVNDLO // edx:eax <- remainder:lo word of dividend 144 div ecx // eax <- low order bits of quotient 145 mov edx,ebx // edx:eax <- quotient 146 jmp short L4 // set sign, restore stack and return 147 148// 149// Here we do it the hard way. Remember, eax contains the high word of DVSR 150// 151 152L3: 153 mov ebx,eax // ebx:ecx <- divisor 154 mov ecx,DVSRLO 155 mov edx,DVNDHI // edx:eax <- dividend 156 mov eax,DVNDLO 157L5: 158 shr ebx,1 // shift divisor right one bit 159 rcr ecx,1 160 shr edx,1 // shift dividend right one bit 161 rcr eax,1 162 or ebx,ebx 163 jnz short L5 // loop until divisor < 4194304K 164 div ecx // now divide, ignore remainder 165 mov esi,eax // save quotient 166 167// 168// We may be off by one, so to check, we will multiply the quotient 169// by the divisor and check the result against the orignal dividend 170// Note that we must also check for overflow, which can occur if the 171// dividend is close to 2**64 and the quotient is off by 1. 172// 173 174 mul dword ptr DVSRHI // QUOT * DVSRHI 175 mov ecx,eax 176 mov eax,DVSRLO 177 mul esi // QUOT * DVSRLO 178 add edx,ecx // EDX:EAX = QUOT * DVSR 179 jc short L6 // carry means Quotient is off by 1 180 181// 182// do long compare here between original dividend and the result of the 183// multiply in edx:eax. If original is larger or equal, we are ok, otherwise 184// subtract one (1) from the quotient. 185// 186 187 cmp edx,DVNDHI // compare hi words of result and original 188 ja short L6 // if result > original, do subtract 189 jb short L7 // if result < original, we are ok 190 cmp eax,DVNDLO // hi words are equal, compare lo words 191 jbe short L7 // if less or equal we are ok, else subtract 192L6: 193 dec esi // subtract 1 from quotient 194L7: 195 xor edx,edx // edx:eax <- quotient 196 mov eax,esi 197 198// 199// Just the cleanup left to do. edx:eax contains the quotient. Set the sign 200// according to the save value, cleanup the stack, and return. 201// 202 203L4: 204 dec edi // check to see if result is negative 205 jnz short L8 // if EDI == 0, result should be negative 206 neg edx // otherwise, negate the result 207 neg eax 208 sbb edx,0 209 210// 211// Restore the saved registers and return. 212// 213 214L8: 215 pop ebx 216 pop esi 217 pop edi 218 219 ret 16 220 221END 222