Path: blob/master/arch/mn10300/include/asm/div64.h
15126 views
/* MN10300 64-bit division1*2* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.3* Written by David Howells ([email protected])4*5* This program is free software; you can redistribute it and/or6* modify it under the terms of the GNU General Public Licence7* as published by the Free Software Foundation; either version8* 2 of the Licence, or (at your option) any later version.9*/10#ifndef _ASM_DIV6411#define _ASM_DIV641213#include <linux/types.h>1415extern void ____unhandled_size_in_do_div___(void);1617/*18* Beginning with gcc 4.6, the MDR register is represented explicitly. We19* must, therefore, at least explicitly clobber the register when we make20* changes to it. The following assembly fragments *could* be rearranged in21* order to leave the moves to/from the MDR register to the compiler, but the22* gains would be minimal at best.23*/24#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)25# define CLOBBER_MDR_CC "mdr", "cc"26#else27# define CLOBBER_MDR_CC "cc"28#endif2930/*31* divide n by base, leaving the result in n and returning the remainder32* - we can do this quite efficiently on the MN10300 by cascading the divides33* through the MDR register34*/35#define do_div(n, base) \36({ \37unsigned __rem = 0; \38if (sizeof(n) <= 4) { \39asm("mov %1,mdr \n" \40"divu %2,%0 \n" \41"mov mdr,%1 \n" \42: "+r"(n), "=d"(__rem) \43: "r"(base), "1"(__rem) \44: CLOBBER_MDR_CC \45); \46} else if (sizeof(n) <= 8) { \47union { \48unsigned long long l; \49u32 w[2]; \50} __quot; \51__quot.l = n; \52asm("mov %0,mdr \n" /* MDR = 0 */ \53"divu %3,%1 \n" \54/* __quot.MSL = __div.MSL / base, */ \55/* MDR = MDR:__div.MSL % base */ \56"divu %3,%2 \n" \57/* __quot.LSL = MDR:__div.LSL / base, */ \58/* MDR = MDR:__div.LSL % base */ \59"mov mdr,%0 \n" \60: "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0]) \61: "r"(base), "0"(__rem), "1"(__quot.w[1]), \62"2"(__quot.w[0]) \63: CLOBBER_MDR_CC \64); \65n = __quot.l; \66} else { \67____unhandled_size_in_do_div___(); \68} \69__rem; \70})7172/*73* do an unsigned 32-bit multiply and divide with intermediate 64-bit product74* so as not to lose accuracy75* - we use the MDR register to hold the MSW of the product76*/77static inline __attribute__((const))78unsigned __muldiv64u(unsigned val, unsigned mult, unsigned div)79{80unsigned result;8182asm("mulu %2,%0 \n" /* MDR:val = val*mult */83"divu %3,%0 \n" /* val = MDR:val/div;84* MDR = MDR:val%div */85: "=r"(result)86: "0"(val), "ir"(mult), "r"(div)87: CLOBBER_MDR_CC88);8990return result;91}9293/*94* do a signed 32-bit multiply and divide with intermediate 64-bit product so95* as not to lose accuracy96* - we use the MDR register to hold the MSW of the product97*/98static inline __attribute__((const))99signed __muldiv64s(signed val, signed mult, signed div)100{101signed result;102103asm("mul %2,%0 \n" /* MDR:val = val*mult */104"div %3,%0 \n" /* val = MDR:val/div;105* MDR = MDR:val%div */106: "=r"(result)107: "0"(val), "ir"(mult), "r"(div)108: CLOBBER_MDR_CC109);110111return result;112}113114#endif /* _ASM_DIV64 */115116117