//      TITLE("Fast Integer Division and Remainder")
//++
//
// Copyright (c) 1993  Digital Equipment Corporation
//
// Module Name:
//
//    divide2.s
//
// Abstract:
//
//    This module implements high-performance versions of the integer divide
//    and remainder routines that are called by assembler pseudo-ops.
//
// Author:
//
//    Thomas Van Baak (tvb) 12-Jan-1993
//    Ken Lesniak (lesniak) 04-Nov-1992
//
// Environment:
//
//    Any mode.
//
// Revision History:
//
//--

#include "ksalpha.h"

//
// Implementation Notes:
//
//    There are no Alpha machine instructions for performing integer division
//    (divl, divlu, divq, divqu) or remainder (reml, remlu, remq, remqu). The
//    machine instructions generated for these assembler pseudo instructions
//    are dependent on the type of operands.
//
//    Division and remainder by constant values are replaced with a sequence
//    of instructions that depend on the data type and the value of the
//    constant. Shifting or reciprocal multiplication are used in most cases
//    to generate the result. No run-time code is necessary in these cases.
//
//    Division and remainder by non-constant values are replaced with a
//    procedure call to a library routine to perform the operation. This file
//    contains those routines.
//
//    This code is adapted from the Alpha/OSF version by Ken Lesniak.
//
//    There are two sets of these eight functions. The __div set were used
//    by an earlier version of the acc compiler. This is the new __2div set.
//    The new functions are about an order of magnitude faster.
//
//    The new function names differ from the original set of functions so
//    that the old and new compilers can co-exist for a time.
//
//    Both the division algorithm code and the large division tables used by
//    the code are contained in the fastdiv.s file which is included several
//    times from this file.
//

//
// Define common stack frame for functions in this file.
//

        .struct 0
DvRa:   .space  8                       // save register ra
DvJr:   .space  8                       // save register t9

DvNu:   .space  8                       // save register t10
DvDi:   .space  8                       // save register t11

DvT0:   .space  8                       // save register t0
DvT1:   .space  8                       // save register t1

DvT2:   .space  8                       // save register t2
DvT3:   .space  8                       // save register t3

DvT4:   .space  8                       // save register a0
        .space  8                       // ensure 16-byte stack alignment
DvFrameLength:                          // length of stack frame

//
// Define non-standard calling convention required by the compiler.
//
//    The compiler uses t9, t10, t11, t12 as indicated below. All other
//    registers (except AT) must be preserved by this calling convention.
//
//    For the fastdiv code, since register a0 must be preserved anyway (it
//    is used by gentrap), define temp register T4 to be a0. Similarly,
//    register J4 must be preserved, so define temp register T5 to be Jr.
//    And the fastdiv code allows Qu to also be temp register T6.
//

#define Jr      t9                      // ($23) return address
#define Nu      t10                     // ($24) dividend (numerator)
#define Di      t11                     // ($25) divisor (denominator)
#define Qu      t12                     // ($27) result (quotient)
#define Re      Qu                      // ($27) result (remainder)

#define T0      t0                      // standard temp
#define T1      t1                      // standard temp
#define T2      t2                      // standard temp
#define T3      t3                      // standard temp
#define T4      a0                      // may use a0 as temp
#define T5      Jr                      // may use Jr as temp
#define T6      Qu                      // may overload Qu as temp T6 only

#ifdef DIV2_DEBUG

//
// In order to debug locally, re-define some of the registers so that
// these functions can be called using a standard calling convention.
//

#undef Jr
#define Jr      ra                      // standard return address register
#undef Nu
#define Nu      a0                      // dividend argument in a0
#undef Di
#define Di      a1                      // divisor argument in a1
#undef Qu
#define Qu      v0                      // quotient result in v0
#undef Re
#define Re      v0                      // remainder result in v0
#undef T4
#define T4      t4                      // normal temp

#endif

        SBTTL("Signed Long Integer Division")
//++
//
// LONG
// __2divl (
//    IN LONG Dividend,
//    IN LONG Divisor
//    )
//
// Routine Description:
//
//    This function divides a signed 32-bit integer by a signed 32-bit integer
//    and returns the signed 32-bit integer result.
//
// Arguments:
//
//    Dividend (t10) - Supplies the dividend (numerator) value.
//
//    Divisor (t11) - Supplies the divisor (denominator) value.
//
// Return Value:
//
//    The 32-bit integer result (quotient) is returned in register t12.
//
// Note:
//
//    This function uses a non-standard calling procedure. The return address
//    is stored in the t9 register and the return value is in the t10 register.
//    No other registers are modified.
//
//--

        NESTED_ENTRY(__2divl, DvFrameLength, Jr)

//
// This prologue is magic. When executed during a call, it will save the
// value of register ra (twice) and register t9 in the stack frame, even
// though these registers are not modified by this function. The stores
// appear to unnecessary.
//
// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
// is reverse executed by virtual unwind to reset the stack pointer and to
// obtain the return address. The return address is the value of RA the
// first time it is restored, which will be the saved value of t9.
//

        .set    noreorder
        .set    noat
        lda     sp, -DvFrameLength(sp)  // allocate stack frame

        stq     ra, DvRa(sp)            // save ra register
        stq     ra, DvJr(sp)            // backtrace return address
        stq     Jr, DvJr(sp)            // save actual return address

        stq     Nu, DvNu(sp)            // save original dividend
        stq     Di, DvDi(sp)            // save original divisor
        stq     t0, DvT0(sp)            // save temp registers
        stq     t1, DvT1(sp)            //
        stq     t2, DvT2(sp)            //
        stq     t3, DvT3(sp)            //
        stq     T4, DvT4(sp)            //
        .set    at
        .set    reorder

        PROLOGUE_END

        addl    Nu, 0, Nu               // convert LONG dividend to quadword
        addl    Di, 0, Di               // convert LONG divisor to quadword

//
// Check for division of the most negative integer (0x800...00) by the least
// negative (-1). The result would be an integer which is one greater than the
// maximum positive integer. Since this cannot be represented, an overflow must
// be generated.
//

        addl    Di, 1, t0               // 0 if Di == -1; != 0 otherwise
        mov     Nu, t1                  // copy dividend
        cmovne  t0, 0, t1               // replace w/ 0 if divisor != -1
        sublv   zero, t1, t1            // trap if dividend == 0x800..00

//
// Convert negative arguments to positive for the division algorithm.
//

        subq    zero, Nu, t0            // negate dividend
        cmovlt  Nu, t0, Nu              // get absolute value of dividend
        subq    zero, Di, t0            // negate divisor
        cmovlt  Di, t0, Di              // get absolute value of divisor

//
// Set up defines and include the main body of the division code.
//

#define FASTDIV_OPTIONS (THIRTY_TWO_BIT | SIGNED | DIVISION)

#include "fastdiv.s"

//
// Restore some registers and set the correct sign of the quotient.
//

        ldq     Jr, DvJr(sp)            // restore return address
        ldq     Nu, DvNu(sp)            // restore original dividend
        ldq     Di, DvDi(sp)            // restore original divisor

        addl    Qu, 0, Qu               // ensure quotient is in canonical form
        subl    zero, Qu, t1            // negate LONG quotient
        xor     Nu, Di, t0              // compute sign of quotient
        addl    t0, 0, t0               // ensure quotient is in canonical form
        cmovlt  t0, t1, Qu              // use negated quotient if necessary

//
// Restore other saved registers and return with quotient in register Qu.
//

        ldq     t0, DvT0(sp)            // restore temp registers
        ldq     t1, DvT1(sp)            //
        ldq     t2, DvT2(sp)            //
        ldq     t3, DvT3(sp)            //
        ldq     T4, DvT4(sp)            //

        lda     sp, DvFrameLength(sp)   // deallocate stack frame
        ret     zero, (Jr)              // return

        .end    __2divl

        SBTTL("Unsigned Long Integer Division")
//++
//
// ULONG
// __2divlu (
//    IN ULONG Dividend,
//    IN ULONG Divisor
//    )
//
// Routine Description:
//
//    This function divides an unsigned 32-bit integer by an unsigned 32-bit
//    integer and returns the unsigned 32-bit integer result.
//
// Arguments:
//
//    Dividend (t10) - Supplies the dividend (numerator) value.
//
//    Divisor (t11) - Supplies the divisor (denominator) value.
//
// Return Value:
//
//    The 32-bit integer result (quotient) is returned in register t12.
//
// Note:
//
//    This function uses a non-standard calling procedure. The return address
//    is stored in the t9 register and the return value is in the t10 register.
//    No other registers are modified.
//
//--

        NESTED_ENTRY(__2divlu, DvFrameLength, Jr)

//
// This prologue is magic. When executed during a call, it will save the
// value of register ra (twice) and register t9 in the stack frame, even
// though these registers are not modified by this function. The stores
// appear to unnecessary.
//
// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
// is reverse executed by virtual unwind to reset the stack pointer and to
// obtain the return address. The return address is the value of RA the
// first time it is restored, which will be the saved value of t9.
//

        .set    noreorder
        .set    noat
        lda     sp, -DvFrameLength(sp)  // allocate stack frame

        stq     ra, DvRa(sp)            // save ra register
        stq     ra, DvJr(sp)            // backtrace return address
        stq     Jr, DvJr(sp)            // save actual return address

        stq     Nu, DvNu(sp)            // save original dividend
        stq     Di, DvDi(sp)            // save original divisor
        stq     t0, DvT0(sp)            // save temp registers
        stq     t1, DvT1(sp)            //
        stq     t2, DvT2(sp)            //
        stq     t3, DvT3(sp)            //
        stq     T4, DvT4(sp)            //
        .set    at
        .set    reorder

        PROLOGUE_END

        zap     Nu, 0xf0, Nu            // convert ULONG dividend to quadword
        zap     Di, 0xf0, Di            // convert ULONG divisor to quadword

//
// Set up defines and include the main body of the division code.
//

#define FASTDIV_OPTIONS (THIRTY_TWO_BIT | UNSIGNED | DIVISION)

#include "fastdiv.s"

//
// Restore all saved registers and return with quotient in register Qu.
//

        ldq     Jr, DvJr(sp)            // restore return address
        ldq     Nu, DvNu(sp)            // restore original dividend
        ldq     Di, DvDi(sp)            // restore original divisor

        ldq     t0, DvT0(sp)            // restore temp registers
        ldq     t1, DvT1(sp)            //
        ldq     t2, DvT2(sp)            //
        ldq     t3, DvT3(sp)            //
        ldq     T4, DvT4(sp)            //

        lda     sp, DvFrameLength(sp)   // deallocate stack frame
        ret     zero, (Jr)              // return

        .end    __2divlu

        SBTTL("Signed Quad Integer Division")
//++
//
// LONGLONG
// __2divq (
//    IN LONGLONG Dividend,
//    IN LONGLONG Divisor
//    )
//
// Routine Description:
//
//    This function divides a signed 64-bit integer by a signed 64-bit integer
//    and returns the signed 64-bit integer result.
//
// Arguments:
//
//    Dividend (t10) - Supplies the dividend (numerator) value.
//
//    Divisor (t11) - Supplies the divisor (denominator) value.
//
// Return Value:
//
//    The 64-bit integer result (quotient) is returned in register t12.
//
// Note:
//
//    This function uses a non-standard calling procedure. The return address
//    is stored in the t9 register and the return value is in the t10 register.
//    No other registers are modified.
//
//--

        NESTED_ENTRY(__2divq, DvFrameLength, Jr)

//
// This prologue is magic. When executed during a call, it will save the
// value of register ra (twice) and register t9 in the stack frame, even
// though these registers are not modified by this function. The stores
// appear to unnecessary.
//
// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
// is reverse executed by virtual unwind to reset the stack pointer and to
// obtain the return address. The return address is the value of RA the
// first time it is restored, which will be the saved value of t9.
//

        .set    noreorder
        .set    noat
        lda     sp, -DvFrameLength(sp)  // allocate stack frame

        stq     ra, DvRa(sp)            // save ra register
        stq     ra, DvJr(sp)            // backtrace return address
        stq     Jr, DvJr(sp)            // save actual return address

        stq     Nu, DvNu(sp)            // save original dividend
        stq     Di, DvDi(sp)            // save original divisor
        stq     t0, DvT0(sp)            // save temp registers
        stq     t1, DvT1(sp)            //
        stq     t2, DvT2(sp)            //
        stq     t3, DvT3(sp)            //
        stq     T4, DvT4(sp)            //
        .set    at
        .set    reorder

        PROLOGUE_END

//
// Check for division of the most negative integer (0x800..00) by the least
// negative (-1). The result would be an integer which is one greater than the
// maximum positive integer. Since this cannot be represented, an overflow must
// be generated.
//

        addq    Di, 1, t0               // 0 if Di == -1; != 0 otherwise
        mov     Nu, t1                  // copy dividend
        cmovne  t0, 0, t1               // replace w/ 0 if divisor != -1
        subqv   zero, t1, t1            // trap if dividend == 0x800..00

//
// Convert negative arguments to positive for the division algorithm.
//

        subq    zero, Nu, t0            // negate dividend
        cmovlt  Nu, t0, Nu              // get absolute value of dividend
        subq    zero, Di, t0            // negate divisor
        cmovlt  Di, t0, Di              // get absolute value of divisor

//
// Set up defines and include the main body of the division code.
//

#define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | SIGNED | DIVISION)

#include "fastdiv.s"

//
// Restore some registers and set the correct sign of the quotient.
//

        ldq     Jr, DvJr(sp)            // restore return address
        ldq     Nu, DvNu(sp)            // restore original dividend
        ldq     Di, DvDi(sp)            // restore original divisor

        subq    zero, Qu, t1            // negate quadword quotient
        xor     Nu, Di, t0              // compute sign of quotient
        cmovlt  t0, t1, Qu              // use negated quotient if necessary

//
// Restore other saved registers and return with quotient in register Qu.
//

        ldq     t0, DvT0(sp)            // restore temp registers
        ldq     t1, DvT1(sp)            //
        ldq     t2, DvT2(sp)            //
        ldq     t3, DvT3(sp)            //
        ldq     T4, DvT4(sp)            //

        lda     sp, DvFrameLength(sp)   // deallocate stack frame
        ret     zero, (Jr)              // return

        .end    __2divq

        SBTTL("Unsigned Quad Integer Division")
//++
//
// ULONGLONG
// __2divqu (
//    IN ULONGLONG Dividend,
//    IN ULONGLONG Divisor
//    )
//
// Routine Description:
//
//    This function divides an unsigned 64-bit integer by an unsigned 64-bit
//    integer and returns the unsigned 64-bit integer result.
//
// Arguments:
//
//    Dividend (t10) - Supplies the dividend (numerator) value.
//
//    Divisor (t11) - Supplies the divisor (denominator) value.
//
// Return Value:
//
//    The 64-bit integer result (quotient) is returned in register t12.
//
// Note:
//
//    This function uses a non-standard calling procedure. The return address
//    is stored in the t9 register and the return value is in the t10 register.
//    No other registers are modified.
//
//--

        NESTED_ENTRY(__2divqu, DvFrameLength, Jr)

//
// This prologue is magic. When executed during a call, it will save the
// value of register ra (twice) and register t9 in the stack frame, even
// though these registers are not modified by this function. The stores
// appear to unnecessary.
//
// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
// is reverse executed by virtual unwind to reset the stack pointer and to
// obtain the return address. The return address is the value of RA the
// first time it is restored, which will be the saved value of t9.
//

        .set    noreorder
        .set    noat
        lda     sp, -DvFrameLength(sp)  // allocate stack frame

        stq     ra, DvRa(sp)            // save ra register
        stq     ra, DvJr(sp)            // backtrace return address
        stq     Jr, DvJr(sp)            // save actual return address

        stq     t0, DvT0(sp)            // save temp registers
        stq     t1, DvT1(sp)            //
        stq     t2, DvT2(sp)            //
        stq     t3, DvT3(sp)            //
        stq     T4, DvT4(sp)            //
        .set    at
        .set    reorder

        PROLOGUE_END

//
// Set up defines and include the main body of the division code.
//

#define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | UNSIGNED | DIVISION)

#include "fastdiv.s"

//
// Restore all saved registers and return with quotient in register Qu.
//

        ldq     Jr, DvJr(sp)            // restore return address

        ldq     t0, DvT0(sp)            // restore temp registers
        ldq     t1, DvT1(sp)            //
        ldq     t2, DvT2(sp)            //
        ldq     t3, DvT3(sp)            //
        ldq     T4, DvT4(sp)            //

        lda     sp, DvFrameLength(sp)   // deallocate stack frame
        ret     zero, (Jr)              // return

        .end    __2divqu

        SBTTL("Signed Long Integer Remainder")
//++
//
// LONG
// __2reml (
//    IN LONG Dividend,
//    IN LONG Divisor
//    )
//
// Routine Description:
//
//    This function divides a signed 32-bit integer by a signed 32-bit integer
//    and returns the signed 32-bit integer remainder result.
//
// Arguments:
//
//    Dividend (t10) - Supplies the dividend (numerator) value.
//
//    Divisor (t11) - Supplies the divisor (denominator) value.
//
// Return Value:
//
//    The 32-bit integer result (remainder) is returned in register t12.
//
// Note:
//
//    This function uses a non-standard calling procedure. The return address
//    is stored in the t9 register and the return value is in the t10 register.
//    No other registers are modified.
//
//--

        NESTED_ENTRY(__2reml, DvFrameLength, Jr)

//
// This prologue is magic. When executed during a call, it will save the
// value of register ra (twice) and register t9 in the stack frame, even
// though these registers are not modified by this function. The stores
// appear to unnecessary.
//
// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
// is reverse executed by virtual unwind to reset the stack pointer and to
// obtain the return address. The return address is the value of RA the
// first time it is restored, which will be the saved value of t9.
//

        .set    noreorder
        .set    noat
        lda     sp, -DvFrameLength(sp)  // allocate stack frame

        stq     ra, DvRa(sp)            // save ra register
        stq     ra, DvJr(sp)            // backtrace return address
        stq     Jr, DvJr(sp)            // save actual return address

        stq     Nu, DvNu(sp)            // save original dividend
        stq     Di, DvDi(sp)            // save original divisor
        stq     t0, DvT0(sp)            // save temp registers
        stq     t1, DvT1(sp)            //
        stq     t2, DvT2(sp)            //
        stq     t3, DvT3(sp)            //
        stq     T4, DvT4(sp)            //
        .set    at
        .set    reorder

        PROLOGUE_END

        addl    Nu, 0, Nu               // convert LONG dividend to quadword
        addl    Di, 0, Di               // convert LONG divisor to quadword

//
// Check for division of the most negative integer (0x800..00) by the least
// negative (-1). The result would be an integer which is one greater than the
// maximum positive integer. Since this cannot be represented, an overflow must
// be generated.
//

        addl    Di, 1, t0               // 0 if Di == -1; != 0 otherwise
        mov     Nu, t1                  // copy dividend
        cmovne  t0, 0, t1               // replace w/ 0 if divisor != -1
        sublv   zero, t1, t1            // trap if dividend == 0x800..00

//
// Convert negative arguments to positive for the division algorithm.
//

        subq    zero, Nu, t0            // negate dividend
        cmovlt  Nu, t0, Nu              // get absolute value of dividend
        subq    zero, Di, t0            // negate divisor
        cmovlt  Di, t0, Di              // get absolute value of divisor

//
// Set up defines and include the main body of the division code.
//

#define FASTDIV_OPTIONS (THIRTY_TWO_BIT | SIGNED | REMAINDER)

#include "fastdiv.s"

//
// Restore some registers and set the correct sign of the remainder.
//

        ldq     Jr, DvJr(sp)            // restore return address
        ldq     Nu, DvNu(sp)            // restore original dividend
        ldq     Di, DvDi(sp)            // restore original divisor

        addl    Qu, 0, Qu               // ensure remainder is in canonical form
        subl    zero, Qu, t1            // negate LONG remainder
        addl    Nu, 0, t0               // get dividend in canonical form
        cmovlt  t0, t1, Qu              // use negated remainder if necessary

//
// Restore other saved registers and return with remainder in register Qu.
//

        ldq     t0, DvT0(sp)            // restore temp registers
        ldq     t1, DvT1(sp)            //
        ldq     t2, DvT2(sp)            //
        ldq     t3, DvT3(sp)            //
        ldq     T4, DvT4(sp)            //

        lda     sp, DvFrameLength(sp)   // deallocate stack frame
        ret     zero, (Jr)              // return

        .end    __2reml

        SBTTL("Unsigned Long Integer Remainder")
//++
//
// ULONG
// __2remlu (
//    IN ULONG Dividend,
//    IN ULONG Divisor
//    )
//
// Routine Description:
//
//    This function divides an unsigned 32-bit integer by an unsigned 32-bit
//    integer and returns the unsigned 32-bit integer remainder result.
//
// Arguments:
//
//    Dividend (t10) - Supplies the dividend (numerator) value.
//
//    Divisor (t11) - Supplies the divisor (denominator) value.
//
// Return Value:
//
//    The 32-bit integer result (remainder) is returned in register t12.
//
// Note:
//
//    This function uses a non-standard calling procedure. The return address
//    is stored in the t9 register and the return value is in the t10 register.
//    No other registers are modified.
//
//--

        NESTED_ENTRY(__2remlu, DvFrameLength, Jr)

//
// This prologue is magic. When executed during a call, it will save the
// value of register ra (twice) and register t9 in the stack frame, even
// though these registers are not modified by this function. The stores
// appear to unnecessary.
//
// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
// is reverse executed by virtual unwind to reset the stack pointer and to
// obtain the return address. The return address is the value of RA the
// first time it is restored, which will be the saved value of t9.
//

        .set    noreorder
        .set    noat
        lda     sp, -DvFrameLength(sp)  // allocate stack frame

        stq     ra, DvRa(sp)            // save ra register
        stq     ra, DvJr(sp)            // backtrace return address
        stq     Jr, DvJr(sp)            // save actual return address

        stq     Nu, DvNu(sp)            // save original dividend
        stq     Di, DvDi(sp)            // save original divisor
        stq     t0, DvT0(sp)            // save temp registers
        stq     t1, DvT1(sp)            //
        stq     t2, DvT2(sp)            //
        stq     t3, DvT3(sp)            //
        stq     T4, DvT4(sp)            //
        .set    at
        .set    reorder

        PROLOGUE_END

        zap     Nu, 0xf0, Nu            // convert ULONG dividend to quadword
        zap     Di, 0xf0, Di            // convert ULONG divisor to quadword

//
// Set up defines and include the main body of the division code.
//

#define FASTDIV_OPTIONS (THIRTY_TWO_BIT | UNSIGNED | REMAINDER)

#include "fastdiv.s"

//
// Restore all saved registers and return with remainder in register Qu.
//

        ldq     Jr, DvJr(sp)            // restore return address
        ldq     Nu, DvNu(sp)            // restore original dividend
        ldq     Di, DvDi(sp)            // restore original divisor

        ldq     t0, DvT0(sp)            // restore temp registers
        ldq     t1, DvT1(sp)            //
        ldq     t2, DvT2(sp)            //
        ldq     t3, DvT3(sp)            //
        ldq     T4, DvT4(sp)            //

        lda     sp, DvFrameLength(sp)   // deallocate stack frame
        ret     zero, (Jr)              // return

        .end    __2remlu

        SBTTL("Signed Quad Integer Remainder")
//++
//
// LONGLONG
// __2remq (
//    IN LONGLONG Dividend,
//    IN LONGLONG Divisor
//    )
//
// Routine Description:
//
//    This function divides a signed 64-bit integer by a signed 64-bit integer
//    and returns the signed 64-bit integer remainder result.
//
// Arguments:
//
//    Dividend (t10) - Supplies the dividend (numerator) value.
//
//    Divisor (t11) - Supplies the divisor (denominator) value.
//
// Return Value:
//
//    The 64-bit integer result (remainder) is returned in register t12.
//
// Note:
//
//    This function uses a non-standard calling procedure. The return address
//    is stored in the t9 register and the return value is in the t10 register.
//    No other registers are modified.
//
//--

        NESTED_ENTRY(__2remq, DvFrameLength, Jr)

//
// This prologue is magic. When executed during a call, it will save the
// value of register ra (twice) and register t9 in the stack frame, even
// though these registers are not modified by this function. The stores
// appear to unnecessary.
//
// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
// is reverse executed by virtual unwind to reset the stack pointer and to
// obtain the return address. The return address is the value of RA the
// first time it is restored, which will be the saved value of t9.
//

        .set    noreorder
        .set    noat
        lda     sp, -DvFrameLength(sp)  // allocate stack frame

        stq     ra, DvRa(sp)            // save ra register
        stq     ra, DvJr(sp)            // backtrace return address
        stq     Jr, DvJr(sp)            // save actual return address

        stq     Nu, DvNu(sp)            // save original dividend
        stq     Di, DvDi(sp)            // save original divisor
        stq     t0, DvT0(sp)            // save temp registers
        stq     t1, DvT1(sp)            //
        stq     t2, DvT2(sp)            //
        stq     t3, DvT3(sp)            //
        stq     T4, DvT4(sp)            //
        .set    at
        .set    reorder

        PROLOGUE_END

//
// Check for division of the most negative integer (0x800..00) by the least
// negative (-1). The result would be an integer which is one greater than the
// maximum positive integer. Since this cannot be represented, an overflow must
// be generated.
//

        addq    Di, 1, t0               // 0 if Di == -1; != 0 otherwise
        mov     Nu, t1                  // copy dividend
        cmovne  t0, 0, t1               // replace w/ 0 if divisor != -1
        subqv   zero, t1, t1            // trap if dividend == 0x800..00

//
// Convert negative arguments to positive for the division algorithm.
//

        subq    zero, Nu, t0            // negate dividend
        cmovlt  Nu, t0, Nu              // get absolute value of dividend
        subq    zero, Di, t0            // negate divisor
        cmovlt  Di, t0, Di              // get absolute value of divisor

//
// Set up defines and include the main body of the division code.
//

#define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | SIGNED | REMAINDER)

#include "fastdiv.s"

//
// Restore some registers and set the correct sign of the remainder.
//

        ldq     Jr, DvJr(sp)            // restore return address
        ldq     Nu, DvNu(sp)            // restore original dividend
        ldq     Di, DvDi(sp)            // restore original divisor

        subq    zero, Qu, t1            // negate quadword remainder
        cmovlt  Nu, t1, Qu              // use negated remainder if necessary

//
// Restore other saved registers and return with remainder in register Qu.
//

        ldq     t0, DvT0(sp)            // restore temp registers
        ldq     t1, DvT1(sp)            //
        ldq     t2, DvT2(sp)            //
        ldq     t3, DvT3(sp)            //
        ldq     T4, DvT4(sp)            //

        lda     sp, DvFrameLength(sp)   // deallocate stack frame
        ret     zero, (Jr)              // return

        .end    __2remq

        SBTTL("Unsigned Quad Integer Remainder")
//++
//
// ULONGLONG
// __2remqu (
//    IN ULONGLONG Dividend,
//    IN ULONGLONG Divisor
//    )
//
// Routine Description:
//
//    This function divides an unsigned 64-bit integer by an unsigned 64-bit
//    integer and returns the unsigned 64-bit integer remainder result.
//
// Arguments:
//
//    Dividend (t10) - Supplies the dividend (numerator) value.
//
//    Divisor (t11) - Supplies the divisor (denominator) value.
//
// Return Value:
//
//    The 64-bit integer result (remainder) is returned in register t12.
//
// Note:
//
//    This function uses a non-standard calling procedure. The return address
//    is stored in the t9 register and the return value is in the t10 register.
//    No other registers are modified.
//
//--

        NESTED_ENTRY(__2remqu, DvFrameLength, Jr)

//
// This prologue is magic. When executed during a call, it will save the
// value of register ra (twice) and register t9 in the stack frame, even
// though these registers are not modified by this function. The stores
// appear to unnecessary.
//
// But if an exception occurs (e.g., divide by zero GENTRAP), the prologue
// is reverse executed by virtual unwind to reset the stack pointer and to
// obtain the return address. The return address is the value of RA the
// first time it is restored, which will be the saved value of t9.
//

        .set    noreorder
        .set    noat
        lda     sp, -DvFrameLength(sp)  // allocate stack frame

        stq     ra, DvRa(sp)            // save ra register
        stq     ra, DvJr(sp)            // backtrace return address
        stq     Jr, DvJr(sp)            // save actual return address

        stq     t0, DvT0(sp)            // save temp registers
        stq     t1, DvT1(sp)            //
        stq     t2, DvT2(sp)            //
        stq     t3, DvT3(sp)            //
        stq     T4, DvT4(sp)            //
        .set    at
        .set    reorder

        PROLOGUE_END

//
// Set up defines and include the main body of the division code.
//

#define FASTDIV_OPTIONS (SIXTY_FOUR_BIT | UNSIGNED | REMAINDER)

#include "fastdiv.s"

//
// Restore all saved registers and return with remainder in register Qu.
//

        ldq     Jr, DvJr(sp)            // restore return address

        ldq     t0, DvT0(sp)            // restore temp registers
        ldq     t1, DvT1(sp)            //
        ldq     t2, DvT2(sp)            //
        ldq     t3, DvT3(sp)            //
        ldq     T4, DvT4(sp)            //

        lda     sp, DvFrameLength(sp)   // deallocate stack frame
        ret     zero, (Jr)              // return

        .end    __2remqu

//
// Now get one copy of the tables needed by the division code.
//

#define FASTDIV_TABLES

#include "fastdiv.s"
