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