1 /* 2 * arch/alpha/lib/divide.S 3 * 4 * (C) 1995 Linus Torvalds 5 * 6 * Alpha division.. 7 */ 8 9 /* 10 * The alpha chip doesn't provide hardware division, so we have to do it 11 * by hand. The compiler expects the functions 12 * 13 * __divqu: 64-bit unsigned long divide 14 * __remqu: 64-bit unsigned long reminder 15 * __divqs/__remqs: signed 64-bit 16 * __divlu/__remlu: unsigned 32-bit 17 * __divls/__remls: signed 32-bit 18 * 19 * These are not normal C functions: instead of the normal 20 * calling sequence, these expect their arguments in registers 21 * $24 and $25, and return the result in $27. Register $28 may 22 * be clobbered (assembly temporary), anything else must be saved. 23 * 24 * In short: painful. 25 * 26 * This is a rather simple bit-at-a-time algorithm: it's very good 27 * at dividing random 64-bit numbers, but the more usual case where 28 * the divisor is small is handled better by the DEC algorithm 29 * using lookup tables. This uses much less memory, though, and is 30 * nicer on the cache.. Besides, I don't know the copyright status 31 * of the DEC code. 32 */ 33 34 /* 35 * My temporaries: 36 * $0 - current bit 37 * $1 - shifted divisor 38 * $2 - modulus/quotient 39 * 40 * $23 - return address 41 * $24 - dividend 42 * $25 - divisor 43 * 44 * $27 - quotient/modulus 45 * $28 - compare status 46 */ 47 48 /* 49 * Select function type and registers 50 */ 51 #define mask $0 52 #define divisor $1 53 #define compare $28 54 55 #ifdef DIV 56 #define func(x) __div##x 57 #define modulus $2 58 #define quotient $27 59 #else 60 #define func(x) __rem##x 61 #define modulus $27 62 #define quotient $2 63 #endif 64 65 /* 66 * For 32-bit operations, we need to extend to 64-bit 67 */ 68 #ifdef INTSIZE 69 #define function func(lu) 70 #define LONGIFY(x) zapnot x,15,x 71 #else 72 #define function func(qu) 73 #define LONGIFY(x) 74 #endif 75 76 .set noat 77 .globl function 78 .ent function 79 function: 80 subq $30,32,$30 81 stq $0, 0($30) 82 stq $1, 8($30) 83 stq $2,16($30) 84 85 bis $25,$25,divisor 86 bis $24,$24,modulus 87 bis $31,$31,quotient 88 LONGIFY(divisor) 89 LONGIFY(modulus) 90 beq divisor, 9f /* div by zero */ 91 bis $31,1,mask 92 93 /* shift divisor left */ 94 1: cmpult divisor,modulus,compare 95 blt divisor, 3f 96 addq divisor,divisor,divisor 97 addq mask,mask,mask 98 bne compare,1b 99 100 /* ok, start to go right again.. */ 101 2: srl divisor,1,divisor 102 beq mask,9f 103 srl mask,1,mask 104 3: cmpule divisor,modulus,compare 105 beq compare,2b 106 addq quotient,mask,quotient 107 beq mask,9f 108 subq modulus,divisor,modulus 109 br 2b 110 111 9: ldq $0, 0($30) 112 ldq $1, 8($30) 113 ldq $2, 16($30) 114 addq $30,32,$30 115 ret $31,($23),1 116 .end function