/* SPDX-License-Identifier: GPL-2.0 */1/*2* arch/alpha/lib/divide.S3*4* (C) 1995 Linus Torvalds5*6* Alpha division..7*/89/*10* The alpha chip doesn't provide hardware division, so we have to do it11* by hand. The compiler expects the functions12*13* __divqu: 64-bit unsigned long divide14* __remqu: 64-bit unsigned long remainder15* __divqs/__remqs: signed 64-bit16* __divlu/__remlu: unsigned 32-bit17* __divls/__remls: signed 32-bit18*19* These are not normal C functions: instead of the normal20* calling sequence, these expect their arguments in registers21* $24 and $25, and return the result in $27. Register $28 may22* 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 good27* at dividing random 64-bit numbers, but the more usual case where28* the divisor is small is handled better by the DEC algorithm29* using lookup tables. This uses much less memory, though, and is30* nicer on the cache.. Besides, I don't know the copyright status31* of the DEC code.32*/3334/*35* My temporaries:36* $0 - current bit37* $1 - shifted divisor38* $2 - modulus/quotient39*40* $23 - return address41* $24 - dividend42* $25 - divisor43*44* $27 - quotient/modulus45* $28 - compare status46*/4748#include <linux/export.h>49#define halt .long 05051/*52* Select function type and registers53*/54#define mask $055#define divisor $156#define compare $2857#define tmp1 $358#define tmp2 $45960#ifdef DIV61#define DIV_ONLY(x,y...) x,##y62#define MOD_ONLY(x,y...)63#define func(x) __div##x64#define modulus $265#define quotient $2766#define GETSIGN(x) xor $24,$25,x67#define STACK 4868#else69#define DIV_ONLY(x,y...)70#define MOD_ONLY(x,y...) x,##y71#define func(x) __rem##x72#define modulus $2773#define quotient $274#define GETSIGN(x) bis $24,$24,x75#define STACK 3276#endif7778/*79* For 32-bit operations, we need to extend to 64-bit80*/81#ifdef INTSIZE82#define ufunction func(lu)83#define sfunction func(l)84#define LONGIFY(x) zapnot x,15,x85#define SLONGIFY(x) addl x,0,x86#else87#define ufunction func(qu)88#define sfunction func(q)89#define LONGIFY(x)90#define SLONGIFY(x)91#endif9293.set noat94.align 395.globl ufunction96.ent ufunction97ufunction:98subq $30,STACK,$3099.frame $30,STACK,$23100.prologue 01011027: stq $1, 0($30)103bis $25,$25,divisor104stq $2, 8($30)105bis $24,$24,modulus106stq $0,16($30)107bis $31,$31,quotient108LONGIFY(divisor)109stq tmp1,24($30)110LONGIFY(modulus)111bis $31,1,mask112DIV_ONLY(stq tmp2,32($30))113beq divisor, 9f /* div by zero */114115#ifdef INTSIZE116/*117* shift divisor left, using 3-bit shifts for118* 32-bit divides as we can't overflow. Three-bit119* shifts will result in looping three times less120* here, but can result in two loops more later.121* Thus using a large shift isn't worth it (and122* s8add pairs better than a sll..)123*/1241: cmpult divisor,modulus,compare125s8addq divisor,$31,divisor126s8addq mask,$31,mask127bne compare,1b128#else1291: cmpult divisor,modulus,compare130blt divisor, 2f131addq divisor,divisor,divisor132addq mask,mask,mask133bne compare,1b134unop135#endif136137/* ok, start to go right again.. */1382: DIV_ONLY(addq quotient,mask,tmp2)139srl mask,1,mask140cmpule divisor,modulus,compare141subq modulus,divisor,tmp1142DIV_ONLY(cmovne compare,tmp2,quotient)143srl divisor,1,divisor144cmovne compare,tmp1,modulus145bne mask,2b1461479: ldq $1, 0($30)148ldq $2, 8($30)149ldq $0,16($30)150ldq tmp1,24($30)151DIV_ONLY(ldq tmp2,32($30))152addq $30,STACK,$30153ret $31,($23),1154.end ufunction155EXPORT_SYMBOL(ufunction)156157/*158* Uhh.. Ugly signed division. I'd rather not have it at all, but159* it's needed in some circumstances. There are different ways to160* handle this, really. This does:161* -a / b = a / -b = -(a / b)162* -a % b = -(a % b)163* a % -b = a % b164* which is probably not the best solution, but at least should165* have the property that (x/y)*y + (x%y) = x.166*/167.align 3168.globl sfunction169.ent sfunction170sfunction:171subq $30,STACK,$30172.frame $30,STACK,$23173.prologue 0174bis $24,$25,$28175SLONGIFY($28)176bge $28,7b177stq $24,0($30)178subq $31,$24,$28179stq $25,8($30)180cmovlt $24,$28,$24 /* abs($24) */181stq $23,16($30)182subq $31,$25,$28183stq tmp1,24($30)184cmovlt $25,$28,$25 /* abs($25) */185unop186bsr $23,ufunction187ldq $24,0($30)188ldq $25,8($30)189GETSIGN($28)190subq $31,$27,tmp1191SLONGIFY($28)192ldq $23,16($30)193cmovlt $28,tmp1,$27194ldq tmp1,24($30)195addq $30,STACK,$30196ret $31,($23),1197.end sfunction198EXPORT_SYMBOL(sfunction)199200201