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