Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

/*
 *      ulong
 *      _udiv(ulong num, ulong den)
 *      {
 *              int i;
 *              ulong quo;
 *
 *              if(den == 0)
 *                      *(ulong*)-1 = 0;
 *              quo = num;
 *              if(quo > 1<<(32-1))
 *                      quo = 1<<(32-1);
 *              for(i=0; den<quo; i++)
 *                      den <<= 1;
 *              quo = 0;
 *              for(; i>=0; i--) {
 *                      quo <<= 1;
 *                      if(num >= den) {
 *                              num -= den;
 *                              quo |= 1;
 *                      }
 *                      den >>= 1;
 *              }
 *              return quo::num;
 *      }
 */

#define NOPROF  1

/*
 * calling sequence:
 *      num: 4(R1)
 *      den: 8(R1)
 * returns
 *      quo: 4(R1)
 *      rem: 8(R1)
 */
TEXT    _udivmod(SB), NOPROF, $-4

        MOVW    $(1<<31), R11
        MOVW    4(R1), R13      /* numerator */
        MOVW    8(R1), R10      /* denominator */
        CMP     R10, R0
        BNE     udm20
        MOVW    R0, -1(R0)      /* fault -- divide by zero */
udm20:
        MOVW    R13, R12
        CMP     R13, R11
        BLEU    udm34
        MOVW    R11, R12
udm34:
        MOVW    R0, R11
udm38:
        CMP     R10, R12
        BCC     udm54
        SLL     $1, R10
        ADD     $1, R11
        BA      udm38
udm54:
        MOVW    R0, R12
udm58:
        CMP     R11, R0
        BL      udm8c
        SLL     $1, R12
        CMP     R13, R10
        BCS     udm7c
        SUB     R10, R13
        OR      $1, R12
udm7c:
        SRL     $1, R10
        SUB     $1, R11
        BA      udm58
udm8c:
        MOVW    R12, 4(R1)      /* quotent */
        MOVW    R13, 8(R1)      /* remainder */
        JMPL    8(R15)

/*
 * save working registers
 * and bring in num/den parameters
 */
TEXT    _unsarg(SB), NOPROF, $-4
        MOVW    R10, 12(R1)
        MOVW    R11, 16(R1)
        MOVW    R12, 20(R1)
        MOVW    R13, 24(R1)

        MOVW    R14, 4(R1)
        MOVW    32(R1), R14
        MOVW    R14, 8(R1)

        JMPL    8(R15)

/*
 * save working registers
 * and bring in absolute value
 * of num/den parameters
 */
TEXT    _absarg(SB), NOPROF, $-4
        MOVW    R10, 12(R1)
        MOVW    R11, 16(R1)
        MOVW    R12, 20(R1)
        MOVW    R13, 24(R1)

        MOVW    R14, 28(R1)
        CMP     R14, R0
        BGE     ab1
        SUB     R14, R0, R14
ab1:
        MOVW    R14, 4(R1)      /* numerator */

        MOVW    32(R1), R14
        CMP     R14, R0
        BGE     ab2
        SUB     R14, R0, R14
ab2:
        MOVW    R14, 8(R1)      /* denominator */
        JMPL    8(R15)

/*
 * restore registers and
 * return to original caller
 * answer is in R14
 */
TEXT    _retarg(SB), NOPROF, $-4
        MOVW    12(R1), R10
        MOVW    16(R1), R11
        MOVW    20(R1), R12
        MOVW    24(R1), R13
        MOVW    0(R1), R15

        ADD     $28, R1
        JMP     8(R15)          /* back to main sequence */

/*
 * calling sequence
 *      num: R14
 *      den: 8(R1)
 * returns
 *      quo: R14
 */
TEXT    _div(SB), NOPROF, $-4
        SUB     $28, R1         /* 4 reg save, 2 parameters, link */
        MOVW    R15, 0(R1)

        JMPL    _absarg(SB)
        JMPL    _udivmod(SB)
        MOVW    4(R1), R14

        MOVW    28(R1), R10     /* clean up the sign */
        MOVW    32(R1), R11
        XORCC   R11, R10, R0
        BGE     div1
        SUB     R14, R0, R14
div1:

        JMPL    _retarg(SB)
        JMP     8(R15)          /* not executed */

/*
 * calling sequence
 *      num: R14
 *      den: 8(R1)
 * returns
 *      quo: R14
 */
TEXT    _divl(SB), NOPROF, $-4
        SUB     $((4+2+1)*4), R1        /* 4 reg save, 2 parameters, link */
        MOVW    R15, 0(R1)

        JMPL    _unsarg(SB)
        JMPL    _udivmod(SB)
        MOVW    4(R1), R14

        JMPL    _retarg(SB)
        JMP     8(R15)          /* not executed */

/*
 * calling sequence
 *      num: R14
 *      den: 8(R1)
 * returns
 *      rem: R14
 */
TEXT    _mod(SB), NOPROF, $-4
        SUB     $28, R1         /* 4 reg save, 2 parameters, link */

        MOVW    R15, 0(R1)
        JMPL    _absarg(SB)
        JMPL    _udivmod(SB)
        MOVW    8(R1), R14

        MOVW    28(R1), R10     /* clean up the sign */
        CMP     R10, R0
        BGE     mod1
        SUB     R14, R0, R14
mod1:

        JMPL    _retarg(SB)
        JMP     8(R15)          /* not executed */

/*
 * calling sequence
 *      num: R14
 *      den: 8(R1)
 * returns
 *      rem: R14
 */
TEXT    _modl(SB), NOPROF, $-4
        SUB     $28, R1         /* 4 reg save, 2 parameters, link */


        MOVW    R15, 0(R1)
        JMPL    _unsarg(SB)
        JMPL    _udivmod(SB)
        MOVW    8(R1), R14

        JMPL    _retarg(SB)
        JMP     8(R15)          /* not executed */

/*
 * special calling sequence:
 *      arg1 in R14
 *      arg2 in 4(R1),    will save R9
 *      nothing in 0(R1), will save R8
 *      result in R14
 */
TEXT    _mul+0(SB), NOPROF, $-4

        /*
         * exchange stack and registers
         */
        MOVW    R8, 0(R1)
        MOVW    4(R1), R8
        MOVW    R9, 4(R1)

        CMP     R14, R8
        BLE     mul1
        MOVW    R14, R9
        MOVW    R8, R14
        MOVW    R9, R8
mul1:
        MOVW    R14, Y
        ANDNCC  $0xFFF, R14, R0
        BE      mul_shortway
        ANDCC   R0, R0, R9      /* zero partial product and clear N and V cond's */

        /* long multiply */
        MULSCC  R8, R9, R9              /* 0 */
        MULSCC  R8, R9, R9              /* 1 */
        MULSCC  R8, R9, R9              /* 2 */
        MULSCC  R8, R9, R9              /* 3 */
        MULSCC  R8, R9, R9              /* 4 */
        MULSCC  R8, R9, R9              /* 5 */
        MULSCC  R8, R9, R9              /* 6 */
        MULSCC  R8, R9, R9              /* 7 */
        MULSCC  R8, R9, R9              /* 8 */
        MULSCC  R8, R9, R9              /* 9 */
        MULSCC  R8, R9, R9              /* 10 */
        MULSCC  R8, R9, R9              /* 11 */
        MULSCC  R8, R9, R9              /* 12 */
        MULSCC  R8, R9, R9              /* 13 */
        MULSCC  R8, R9, R9              /* 14 */
        MULSCC  R8, R9, R9              /* 15 */
        MULSCC  R8, R9, R9              /* 16 */
        MULSCC  R8, R9, R9              /* 17 */
        MULSCC  R8, R9, R9              /* 18 */
        MULSCC  R8, R9, R9              /* 19 */
        MULSCC  R8, R9, R9              /* 20 */
        MULSCC  R8, R9, R9              /* 21 */
        MULSCC  R8, R9, R9              /* 22 */
        MULSCC  R8, R9, R9              /* 23 */
        MULSCC  R8, R9, R9              /* 24 */
        MULSCC  R8, R9, R9              /* 25 */
        MULSCC  R8, R9, R9              /* 26 */
        MULSCC  R8, R9, R9              /* 27 */
        MULSCC  R8, R9, R9              /* 28 */
        MULSCC  R8, R9, R9              /* 29 */
        MULSCC  R8, R9, R9              /* 30 */
        MULSCC  R8, R9, R9              /* 31 */
        MULSCC  R0, R9, R9              /* 32; shift only */

        MOVW    Y, R14                  /* get low part */
        BA      mul_return

mul_shortway:
        ANDCC   R0, R0, R9      /* zero partial product and clear N and V cond's */
        MULSCC  R8, R9, R9              /*  0 */
        MULSCC  R8, R9, R9              /*  1 */
        MULSCC  R8, R9, R9              /*  2 */
        MULSCC  R8, R9, R9              /*  3 */
        MULSCC  R8, R9, R9              /*  4 */
        MULSCC  R8, R9, R9              /*  5 */
        MULSCC  R8, R9, R9              /*  6 */
        MULSCC  R8, R9, R9              /*  7 */
        MULSCC  R8, R9, R9              /*  8 */
        MULSCC  R8, R9, R9              /*  9 */
        MULSCC  R8, R9, R9              /* 10 */
        MULSCC  R8, R9, R9              /* 11 */
        MULSCC  R0, R9, R9              /* 12; shift only */

        MOVW    Y, R8
        SLL     $12, R9
        SRL     $20, R8
        OR      R8, R9, R14

mul_return:
        MOVW    0(R1), R8
        MOVW    4(R1), R9
        JMP     8(R15)