File r37/lisp/csl/cslbase/imulvc.c artifact 10bdd45aab part of check-in 3af273af29


/* imulvc.c                   Copyright (C) 1993-2002 Codemist Ltd */

/*
 * This code may be used and modified, and redistributed in binary
 * or source form, subject to the "CCL Public License", which should
 * accompany it. This license is a variant on the BSD license, and thus
 * permits use of code derived from this in either open and commercial
 * projects: but it does require that updates to this code be made
 * available back to the originators of the package.
 * Before merging other code in with this or linking this code
 * with other packages or libraries please check that the license terms
 * of the other material are compatible with those of this.
 */


/* Signature: 77597f94 08-Apr-2002 */

/*
 * This code implements Imultiply and Idivide in 80386 (and up) assembly
 * code.  I use the __stdcall calling convention.
 */


#include "machine.h"

#include "tags.h"
#include "externs.h"
#include "cslerror.h"
#include "sys.h"

/*
 * Get rid of unwanted warnings about lack of return values...
 */

#pragma warning (disable : 4035)


unsigned32 __stdcall Imultiply(unsigned32 *rlow,
                             unsigned32 a, unsigned32 b, unsigned32 c)
{
/*
 *     uns64 r = (uns64)a*(uns64)b + (uns64)c;
 *     *rlow = (unsigned32)(r & 0x7fffffff);
 *     return (unsigned32)(r >> 31);
 */
    __asm
    {
        mov        eax, b
        mul        a
        mov        ecx, rlow
        add        eax, c
        adc        edx, 0                ; carry into top half
        add        eax, eax
        adc        edx, edx
        shr        eax, 1
        mov        DWORD PTR [ecx], eax
        mov        eax, edx
    }
}



unsigned32 __stdcall Idiv10_9(unsigned32 *qp, unsigned32 high31, unsigned32 low31)
{
/*
 *      uns64 p = ((uns64)high31 << 31) | (uns64)low31;
 *     *qp = (unsigned32)(p / (uns64)1000000000U);
 *     return (unsigned32)(p % (uns64)1000000000U);
 */
    __asm {
        mov        edx, high31
        mov        eax, low31
        shl        eax, 1
        shr        edx, 1
        rcr        eax, 1            ; That glued together 31+31 bits
        mov        ecx, 1000000000
        div        ecx
        mov        ecx, qp
        mov        DWORD PTR [ecx], eax
        mov        eax, edx
    }
}


unsigned32 __stdcall Idivide(unsigned32 *qp, unsigned32 a,
                           unsigned32 b, unsigned32 c)
{
/*
 *     uns64 p = ((uns64)a << 31) | (uns64)b;
 *     *qp = (unsigned32)(p / (uns64)c);
 *     return (unsigned32)(p % (uns64)c);
 */
    __asm {
        mov        edx, a
        mov        eax, b
        shl        eax, 1
        shr        edx, 1
        rcr        eax, 1          ; That glued together 31+31 bits
        mov        ecx, c
        div        ecx
        mov        ecx, qp
        mov        DWORD PTR [ecx], eax
        mov        eax, edx
    }
}


/* end of imulvc.c */


REDUCE Historical
REDUCE Sourceforge Project | Historical SVN Repository | GitHub Mirror | SourceHut Mirror | NotABug Mirror | Chisel Mirror | Chisel RSS ]