math.c revision 1.1.1.1.6.2 1 1.1.1.1.6.2 yamt /* $NetBSD: math.c,v 1.1.1.1.6.2 2014/05/22 11:40:58 yamt Exp $ */
2 1.1.1.1.6.2 yamt
3 1.1.1.1.6.2 yamt /*++
4 1.1.1.1.6.2 yamt
5 1.1.1.1.6.2 yamt Copyright (c) 1998 Intel Corporation
6 1.1.1.1.6.2 yamt
7 1.1.1.1.6.2 yamt Module Name:
8 1.1.1.1.6.2 yamt
9 1.1.1.1.6.2 yamt math.c
10 1.1.1.1.6.2 yamt
11 1.1.1.1.6.2 yamt Abstract:
12 1.1.1.1.6.2 yamt
13 1.1.1.1.6.2 yamt
14 1.1.1.1.6.2 yamt
15 1.1.1.1.6.2 yamt
16 1.1.1.1.6.2 yamt Revision History
17 1.1.1.1.6.2 yamt
18 1.1.1.1.6.2 yamt --*/
19 1.1.1.1.6.2 yamt
20 1.1.1.1.6.2 yamt #include "lib.h"
21 1.1.1.1.6.2 yamt
22 1.1.1.1.6.2 yamt
23 1.1.1.1.6.2 yamt //
24 1.1.1.1.6.2 yamt // Declare runtime functions
25 1.1.1.1.6.2 yamt //
26 1.1.1.1.6.2 yamt
27 1.1.1.1.6.2 yamt #ifdef RUNTIME_CODE
28 1.1.1.1.6.2 yamt #ifndef __GNUC__
29 1.1.1.1.6.2 yamt #pragma RUNTIME_CODE(LShiftU64)
30 1.1.1.1.6.2 yamt #pragma RUNTIME_CODE(RShiftU64)
31 1.1.1.1.6.2 yamt #pragma RUNTIME_CODE(MultU64x32)
32 1.1.1.1.6.2 yamt #pragma RUNTIME_CODE(DivU64x32)
33 1.1.1.1.6.2 yamt #endif
34 1.1.1.1.6.2 yamt #endif
35 1.1.1.1.6.2 yamt
36 1.1.1.1.6.2 yamt //
37 1.1.1.1.6.2 yamt //
38 1.1.1.1.6.2 yamt //
39 1.1.1.1.6.2 yamt
40 1.1.1.1.6.2 yamt UINT64
41 1.1.1.1.6.2 yamt LShiftU64 (
42 1.1.1.1.6.2 yamt IN UINT64 Operand,
43 1.1.1.1.6.2 yamt IN UINTN Count
44 1.1.1.1.6.2 yamt )
45 1.1.1.1.6.2 yamt // Left shift 64bit by 32bit and get a 64bit result
46 1.1.1.1.6.2 yamt {
47 1.1.1.1.6.2 yamt #ifdef __GNUC__
48 1.1.1.1.6.2 yamt return Operand << Count;
49 1.1.1.1.6.2 yamt #else
50 1.1.1.1.6.2 yamt UINT64 Result;
51 1.1.1.1.6.2 yamt _asm {
52 1.1.1.1.6.2 yamt mov eax, dword ptr Operand[0]
53 1.1.1.1.6.2 yamt mov edx, dword ptr Operand[4]
54 1.1.1.1.6.2 yamt mov ecx, Count
55 1.1.1.1.6.2 yamt and ecx, 63
56 1.1.1.1.6.2 yamt
57 1.1.1.1.6.2 yamt shld edx, eax, cl
58 1.1.1.1.6.2 yamt shl eax, cl
59 1.1.1.1.6.2 yamt
60 1.1.1.1.6.2 yamt cmp ecx, 32
61 1.1.1.1.6.2 yamt jc short ls10
62 1.1.1.1.6.2 yamt
63 1.1.1.1.6.2 yamt mov edx, eax
64 1.1.1.1.6.2 yamt xor eax, eax
65 1.1.1.1.6.2 yamt
66 1.1.1.1.6.2 yamt ls10:
67 1.1.1.1.6.2 yamt mov dword ptr Result[0], eax
68 1.1.1.1.6.2 yamt mov dword ptr Result[4], edx
69 1.1.1.1.6.2 yamt }
70 1.1.1.1.6.2 yamt
71 1.1.1.1.6.2 yamt return Result;
72 1.1.1.1.6.2 yamt #endif
73 1.1.1.1.6.2 yamt }
74 1.1.1.1.6.2 yamt
75 1.1.1.1.6.2 yamt UINT64
76 1.1.1.1.6.2 yamt RShiftU64 (
77 1.1.1.1.6.2 yamt IN UINT64 Operand,
78 1.1.1.1.6.2 yamt IN UINTN Count
79 1.1.1.1.6.2 yamt )
80 1.1.1.1.6.2 yamt // Right shift 64bit by 32bit and get a 64bit result
81 1.1.1.1.6.2 yamt {
82 1.1.1.1.6.2 yamt #ifdef __GNUC__
83 1.1.1.1.6.2 yamt return Operand >> Count;
84 1.1.1.1.6.2 yamt #else
85 1.1.1.1.6.2 yamt UINT64 Result;
86 1.1.1.1.6.2 yamt _asm {
87 1.1.1.1.6.2 yamt mov eax, dword ptr Operand[0]
88 1.1.1.1.6.2 yamt mov edx, dword ptr Operand[4]
89 1.1.1.1.6.2 yamt mov ecx, Count
90 1.1.1.1.6.2 yamt and ecx, 63
91 1.1.1.1.6.2 yamt
92 1.1.1.1.6.2 yamt shrd eax, edx, cl
93 1.1.1.1.6.2 yamt shr edx, cl
94 1.1.1.1.6.2 yamt
95 1.1.1.1.6.2 yamt cmp ecx, 32
96 1.1.1.1.6.2 yamt jc short rs10
97 1.1.1.1.6.2 yamt
98 1.1.1.1.6.2 yamt mov eax, edx
99 1.1.1.1.6.2 yamt xor edx, edx
100 1.1.1.1.6.2 yamt
101 1.1.1.1.6.2 yamt rs10:
102 1.1.1.1.6.2 yamt mov dword ptr Result[0], eax
103 1.1.1.1.6.2 yamt mov dword ptr Result[4], edx
104 1.1.1.1.6.2 yamt }
105 1.1.1.1.6.2 yamt
106 1.1.1.1.6.2 yamt return Result;
107 1.1.1.1.6.2 yamt #endif
108 1.1.1.1.6.2 yamt }
109 1.1.1.1.6.2 yamt
110 1.1.1.1.6.2 yamt
111 1.1.1.1.6.2 yamt UINT64
112 1.1.1.1.6.2 yamt MultU64x32 (
113 1.1.1.1.6.2 yamt IN UINT64 Multiplicand,
114 1.1.1.1.6.2 yamt IN UINTN Multiplier
115 1.1.1.1.6.2 yamt )
116 1.1.1.1.6.2 yamt // Multiple 64bit by 32bit and get a 64bit result
117 1.1.1.1.6.2 yamt {
118 1.1.1.1.6.2 yamt #ifdef __GNUC__
119 1.1.1.1.6.2 yamt return Multiplicand * Multiplier;
120 1.1.1.1.6.2 yamt #else
121 1.1.1.1.6.2 yamt UINT64 Result;
122 1.1.1.1.6.2 yamt _asm {
123 1.1.1.1.6.2 yamt mov eax, dword ptr Multiplicand[0]
124 1.1.1.1.6.2 yamt mul Multiplier
125 1.1.1.1.6.2 yamt mov dword ptr Result[0], eax
126 1.1.1.1.6.2 yamt mov dword ptr Result[4], edx
127 1.1.1.1.6.2 yamt mov eax, dword ptr Multiplicand[4]
128 1.1.1.1.6.2 yamt mul Multiplier
129 1.1.1.1.6.2 yamt add dword ptr Result[4], eax
130 1.1.1.1.6.2 yamt }
131 1.1.1.1.6.2 yamt
132 1.1.1.1.6.2 yamt return Result;
133 1.1.1.1.6.2 yamt #endif
134 1.1.1.1.6.2 yamt }
135 1.1.1.1.6.2 yamt
136 1.1.1.1.6.2 yamt UINT64
137 1.1.1.1.6.2 yamt DivU64x32 (
138 1.1.1.1.6.2 yamt IN UINT64 Dividend,
139 1.1.1.1.6.2 yamt IN UINTN Divisor,
140 1.1.1.1.6.2 yamt OUT UINTN *Remainder OPTIONAL
141 1.1.1.1.6.2 yamt )
142 1.1.1.1.6.2 yamt // divide 64bit by 32bit and get a 64bit result
143 1.1.1.1.6.2 yamt // N.B. only works for 31bit divisors!!
144 1.1.1.1.6.2 yamt {
145 1.1.1.1.6.2 yamt #ifdef __GNUC__
146 1.1.1.1.6.2 yamt if (Remainder)
147 1.1.1.1.6.2 yamt *Remainder = Dividend % Divisor;
148 1.1.1.1.6.2 yamt return Dividend / Divisor;
149 1.1.1.1.6.2 yamt #else
150 1.1.1.1.6.2 yamt UINT32 Rem;
151 1.1.1.1.6.2 yamt UINT32 bit;
152 1.1.1.1.6.2 yamt
153 1.1.1.1.6.2 yamt ASSERT (Divisor != 0);
154 1.1.1.1.6.2 yamt ASSERT ((Divisor >> 31) == 0);
155 1.1.1.1.6.2 yamt
156 1.1.1.1.6.2 yamt //
157 1.1.1.1.6.2 yamt // For each bit in the dividend
158 1.1.1.1.6.2 yamt //
159 1.1.1.1.6.2 yamt
160 1.1.1.1.6.2 yamt Rem = 0;
161 1.1.1.1.6.2 yamt for (bit=0; bit < 64; bit++) {
162 1.1.1.1.6.2 yamt _asm {
163 1.1.1.1.6.2 yamt shl dword ptr Dividend[0], 1 ; shift rem:dividend left one
164 1.1.1.1.6.2 yamt rcl dword ptr Dividend[4], 1
165 1.1.1.1.6.2 yamt rcl dword ptr Rem, 1
166 1.1.1.1.6.2 yamt
167 1.1.1.1.6.2 yamt mov eax, Rem
168 1.1.1.1.6.2 yamt cmp eax, Divisor ; Is Rem >= Divisor?
169 1.1.1.1.6.2 yamt cmc ; No - do nothing
170 1.1.1.1.6.2 yamt sbb eax, eax ; Else,
171 1.1.1.1.6.2 yamt sub dword ptr Dividend[0], eax ; set low bit in dividen
172 1.1.1.1.6.2 yamt and eax, Divisor ; and
173 1.1.1.1.6.2 yamt sub Rem, eax ; subtract divisor
174 1.1.1.1.6.2 yamt }
175 1.1.1.1.6.2 yamt }
176 1.1.1.1.6.2 yamt
177 1.1.1.1.6.2 yamt if (Remainder) {
178 1.1.1.1.6.2 yamt *Remainder = Rem;
179 1.1.1.1.6.2 yamt }
180 1.1.1.1.6.2 yamt
181 1.1.1.1.6.2 yamt return Dividend;
182 1.1.1.1.6.2 yamt #endif
183 1.1.1.1.6.2 yamt }
184