1 /*
2 * Copyright (c) 2009-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2009-07-25
13 * Description: 64位除法文件。
14 */
15 #include "prt_typedef.h"
16 #include "prt_lib_external.h"
17 #include "prt_attr_external.h"
18
19 #define OS_32_BITS_COUNT 32
20
21 /*
22 * 描述:前导0个数获取
23 */
OsleadingZeroCount(U64 data)24 OS_SEC_TEXT U32 OsleadingZeroCount(U64 data)
25 {
26 U32 high = (U32)OS_GET_64BIT_HIGH_32BIT(data);
27 U32 low = (U32)OS_GET_64BIT_LOW_32BIT(data);
28 U32 count = 0;
29
30 if (high == 0) {
31 OS_EMBED_ASM("CLZ %0, %1" : "=r"(count) : "r"(low));
32 count += OS_32_BITS_COUNT;
33 } else {
34 OS_EMBED_ASM("CLZ %0, %1" : "=r"(count) : "r"(high));
35 }
36
37 return count;
38 }
39
OsU64Div(U64 dividend,U64 divisor,U64 * quotient,U64 * remainder)40 OS_SEC_TEXT void OsU64Div(U64 dividend, U64 divisor, U64 *quotient, U64 *remainder)
41 {
42 U32 alignShift;
43 U32 i;
44 U64 tmpDivisor;
45 U64 tmpRemainder;
46 U64 tmpQuotient = 0;
47
48 if (divisor == 0) {
49 return; // 除数为0返回1
50 }
51
52 if (dividend < divisor) {
53 /* 被除数小于除数,商为0,余数即被除数 */
54 *remainder = dividend;
55 *quotient = 0;
56 return;
57 }
58
59 alignShift = OsleadingZeroCount(divisor) - OsleadingZeroCount(dividend);
60 tmpDivisor = divisor << alignShift;
61 tmpRemainder = dividend;
62
63 /* 竖式除法, 类大数相除 */
64 for (i = 0; i <= alignShift; i++) {
65 tmpQuotient <<= 1;
66 if (tmpRemainder >= tmpDivisor) {
67 tmpRemainder -= tmpDivisor;
68 tmpQuotient += 1;
69 }
70 tmpDivisor >>= 1;
71 }
72
73 *quotient = tmpQuotient;
74 *remainder = tmpRemainder;
75
76 return;
77 }
78
OsU64DivGetQuotient(U64 dividend,U64 divisor)79 OS_SEC_TEXT U64 OsU64DivGetQuotient(U64 dividend, U64 divisor)
80 {
81 U64 quotient = 0;
82 U64 remainder;
83
84 OsU64Div(dividend, divisor, "ient, &remainder);
85
86 return quotient;
87 }
88
OsU64DivGetRemainder(U64 dividend,U64 divisor)89 OS_SEC_TEXT U64 OsU64DivGetRemainder(U64 dividend, U64 divisor)
90 {
91 U64 quotient;
92 U64 remainder = 0;
93
94 OsU64Div(dividend, divisor, "ient, &remainder);
95
96 return remainder;
97 }