| 
									
										
										
										
											2008-10-22 22:26:29 -07:00
										 |  |  | #ifndef _ASM_X86_DIV64_H
 | 
					
						
							|  |  |  | #define _ASM_X86_DIV64_H
 | 
					
						
							| 
									
										
										
										
											2007-10-20 07:51:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 11:20:03 +02:00
										 |  |  | #ifdef CONFIG_X86_32
 | 
					
						
							| 
									
										
										
										
											2007-10-20 07:51:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <linux/types.h>
 | 
					
						
							| 
									
										
										
										
											2011-11-30 11:43:34 +01:00
										 |  |  | #include <linux/log2.h>
 | 
					
						
							| 
									
										
										
										
											2007-10-20 07:51:29 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * do_div() is NOT a C function. It wants to return | 
					
						
							|  |  |  |  * two values (the quotient and the remainder), but | 
					
						
							|  |  |  |  * since that doesn't work very well in C, what it | 
					
						
							|  |  |  |  * does is: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - modifies the 64-bit dividend _in_place_ | 
					
						
							|  |  |  |  * - returns the 32-bit remainder | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This ends up being the most efficient "calling | 
					
						
							|  |  |  |  * convention" on x86. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2008-03-23 01:01:59 -07:00
										 |  |  | #define do_div(n, base)						\
 | 
					
						
							|  |  |  | ({								\ | 
					
						
							|  |  |  | 	unsigned long __upper, __low, __high, __mod, __base;	\ | 
					
						
							|  |  |  | 	__base = (base);					\ | 
					
						
							| 
									
										
										
										
											2011-11-30 11:43:34 +01:00
										 |  |  | 	if (__builtin_constant_p(__base) && is_power_of_2(__base)) { \ | 
					
						
							|  |  |  | 		__mod = n & (__base - 1);			\ | 
					
						
							|  |  |  | 		n >>= ilog2(__base);				\ | 
					
						
							|  |  |  | 	} else {						\ | 
					
						
							|  |  |  | 		asm("" : "=a" (__low), "=d" (__high) : "A" (n));\ | 
					
						
							|  |  |  | 		__upper = __high;				\ | 
					
						
							|  |  |  | 		if (__high) {					\ | 
					
						
							|  |  |  | 			__upper = __high % (__base);		\ | 
					
						
							|  |  |  | 			__high = __high / (__base);		\ | 
					
						
							|  |  |  | 		}						\ | 
					
						
							|  |  |  | 		asm("divl %2" : "=a" (__low), "=d" (__mod)	\ | 
					
						
							|  |  |  | 			: "rm" (__base), "0" (__low), "1" (__upper));	\ | 
					
						
							|  |  |  | 		asm("" : "=A" (n) : "a" (__low), "d" (__high));	\ | 
					
						
							| 
									
										
										
										
											2008-03-23 01:01:59 -07:00
										 |  |  | 	}							\ | 
					
						
							|  |  |  | 	__mod;							\ | 
					
						
							| 
									
										
										
										
											2007-10-20 07:51:29 -04:00
										 |  |  | }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-05-01 04:34:25 -07:00
										 |  |  | static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	union { | 
					
						
							|  |  |  | 		u64 v64; | 
					
						
							|  |  |  | 		u32 v32[2]; | 
					
						
							|  |  |  | 	} d = { dividend }; | 
					
						
							|  |  |  | 	u32 upper; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	upper = d.v32[1]; | 
					
						
							|  |  |  | 	d.v32[1] = 0; | 
					
						
							|  |  |  | 	if (upper >= divisor) { | 
					
						
							|  |  |  | 		d.v32[1] = upper / divisor; | 
					
						
							|  |  |  | 		upper %= divisor; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	asm ("divl %2" : "=a" (d.v32[0]), "=d" (*remainder) : | 
					
						
							|  |  |  | 		"rm" (divisor), "0" (d.v32[0]), "1" (upper)); | 
					
						
							|  |  |  | 	return d.v64; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #define div_u64_rem	div_u64_rem
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-10-11 11:20:03 +02:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2007-10-20 07:51:29 -04:00
										 |  |  | # include <asm-generic/div64.h>
 | 
					
						
							|  |  |  | #endif /* CONFIG_X86_32 */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-22 22:26:29 -07:00
										 |  |  | #endif /* _ASM_X86_DIV64_H */
 |