123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- /*
- * uvlong
- * _udiv(uvlong num, uvlong den)
- * {
- * int i;
- * uvlong quo;
- *
- * if(den == 0)
- * *(ulong*)-1 = 0;
- * quo = num;
- * if(quo > 1<<(64-1))
- * quo = 1<<(64-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: 8(R30)
- * den: 16(R30)
- * returns
- * quo: 8(R30)
- * rem: 16(R30)
- */
- TEXT _udivmodq(SB), NOPROF, $-8
- MOVQ $1, R11
- SLLQ $63, R11
- MOVQ 8(R30), R23 /* numerator */
- MOVQ 16(R30), R10 /* denominator */
- BNE R10, udm20
- MOVQ R31, -1(R31) /* fault -- divide by zero; todo: use gentrap? */
- udm20:
- MOVQ R23, R12
- BGE R12, udm34
- MOVQ R11, R12
- udm34:
- MOVQ R31, R11
- udm38:
- CMPUGE R10, R12, R24
- BNE R24, udm54
- SLLQ $1, R10
- ADDQ $1, R11
- JMP udm38
- udm54:
- MOVQ R31, R12
- udm58:
- BLT R11, udm8c
- SLLQ $1, R12
- CMPUGE R23, R10, R24
- BEQ R24, udm7c
- SUBQ R10, R23
- OR $1, R12
- udm7c:
- SRLQ $1, R10
- SUBQ $1, R11
- JMP udm58
- udm8c:
- MOVQ R12, 8(R30) /* quotient */
- MOVQ R23, 16(R30) /* remainder */
- RET
- /*
- * save working registers
- * and bring in num/den parameters
- */
- TEXT _unsargq(SB), NOPROF, $-8
- MOVQ R10, 24(R30)
- MOVQ R11, 32(R30)
- MOVQ R12, 40(R30)
- MOVQ R23, 48(R30)
- MOVQ R24, 56(R30)
- MOVQ R27, 8(R30)
- MOVQ 72(R30), R27
- MOVQ R27, 16(R30)
- MOVQ (R30), R10 /* debug */
- RET
- /*
- * save working registers
- * and bring in absolute value
- * of num/den parameters
- */
- TEXT _absargq(SB), NOPROF, $-8
- MOVQ R10, 24(R30)
- MOVQ R11, 32(R30)
- MOVQ R12, 40(R30)
- MOVQ R23, 48(R30)
- MOVQ R24, 56(R30)
- MOVQ R27, 64(R30)
- BGE R27, ab1
- SUBQ R27, R31, R27
- ab1:
- MOVQ R27, 8(R30) /* numerator */
- MOVQ 72(R30), R27
- BGE R27, ab2
- SUBQ R27, R31, R27
- ab2:
- MOVQ R27, 16(R30) /* denominator */
- MOVQ (R30), R10 /* debug */
- RET
- /*
- * restore registers and
- * return to original caller
- * answer is in R27
- */
- TEXT _retargq(SB), NOPROF, $-8
- MOVQ 24(R30), R10
- MOVQ 32(R30), R11
- MOVQ 40(R30), R12
- MOVQ 48(R30), R23
- MOVQ 56(R30), R24
- MOVL 0(R30), R26
- ADDQ $64, R30
- RET /* back to main sequence */
- TEXT _divq(SB), NOPROF, $-8
- SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
- MOVQ R26, 0(R30)
- JSR _absargq(SB)
- JSR _udivmodq(SB)
- MOVQ 8(R30), R27
- MOVQ 64(R30), R10 /* clean up the sign */
- MOVQ 72(R30), R11
- XOR R11, R10
- BGE R10, div1
- SUBQ R27, R31, R27
- div1:
- JSR _retargq(SB)
- RET /* not executed */
- TEXT _divqu(SB), NOPROF, $-8
- SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
- MOVQ R26, 0(R30)
- JSR _unsargq(SB)
- JSR _udivmodq(SB)
- MOVQ 8(R30), R27
- JSR _retargq(SB)
- RET /* not executed */
- TEXT _modq(SB), NOPROF, $-8
- SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
- MOVQ R26, 0(R30)
- JSR _absargq(SB)
- JSR _udivmodq(SB)
- MOVQ 16(R30), R27
- MOVQ 64(R30), R10 /* clean up the sign */
- BGE R10, div2
- SUBQ R27, R31, R27
- div2:
- JSR _retargq(SB)
- RET /* not executed */
- TEXT _modqu(SB), NOPROF, $-8
- SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
- MOVQ R26, 0(R30)
- JSR _unsargq(SB)
- JSR _udivmodq(SB)
- MOVQ 16(R30), R27
- JSR _retargq(SB)
- RET /* not executed */
|