1530d68baSNigel Croxon /*++
2530d68baSNigel Croxon
3530d68baSNigel Croxon Copyright (c) 1998 Intel Corporation
4530d68baSNigel Croxon
5530d68baSNigel Croxon Module Name:
6530d68baSNigel Croxon
7530d68baSNigel Croxon math.c
8530d68baSNigel Croxon
9530d68baSNigel Croxon Abstract:
10530d68baSNigel Croxon
11530d68baSNigel Croxon
12530d68baSNigel Croxon
13530d68baSNigel Croxon
14530d68baSNigel Croxon Revision History
15530d68baSNigel Croxon
16530d68baSNigel Croxon --*/
17530d68baSNigel Croxon
18530d68baSNigel Croxon #include "lib.h"
19530d68baSNigel Croxon
20530d68baSNigel Croxon
21530d68baSNigel Croxon //
22530d68baSNigel Croxon // Declare runtime functions
23530d68baSNigel Croxon //
24530d68baSNigel Croxon
25530d68baSNigel Croxon #ifdef RUNTIME_CODE
26530d68baSNigel Croxon #ifndef __GNUC__
27530d68baSNigel Croxon #pragma RUNTIME_CODE(LShiftU64)
28530d68baSNigel Croxon #pragma RUNTIME_CODE(RShiftU64)
29530d68baSNigel Croxon #pragma RUNTIME_CODE(MultU64x32)
30530d68baSNigel Croxon #pragma RUNTIME_CODE(DivU64x32)
31530d68baSNigel Croxon #endif
32530d68baSNigel Croxon #endif
33530d68baSNigel Croxon
34530d68baSNigel Croxon //
35530d68baSNigel Croxon //
36530d68baSNigel Croxon //
37530d68baSNigel Croxon
38530d68baSNigel Croxon UINT64
LShiftU64(IN UINT64 Operand,IN UINTN Count)39530d68baSNigel Croxon LShiftU64 (
40530d68baSNigel Croxon IN UINT64 Operand,
41530d68baSNigel Croxon IN UINTN Count
42530d68baSNigel Croxon )
43530d68baSNigel Croxon // Left shift 64bit by 32bit and get a 64bit result
44530d68baSNigel Croxon {
45*09027207SNigel Croxon #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
46530d68baSNigel Croxon return Operand << Count;
47530d68baSNigel Croxon #else
48530d68baSNigel Croxon UINT64 Result;
49530d68baSNigel Croxon _asm {
50530d68baSNigel Croxon mov eax, dword ptr Operand[0]
51530d68baSNigel Croxon mov edx, dword ptr Operand[4]
52530d68baSNigel Croxon mov ecx, Count
53530d68baSNigel Croxon and ecx, 63
54530d68baSNigel Croxon
55530d68baSNigel Croxon shld edx, eax, cl
56530d68baSNigel Croxon shl eax, cl
57530d68baSNigel Croxon
58530d68baSNigel Croxon cmp ecx, 32
59530d68baSNigel Croxon jc short ls10
60530d68baSNigel Croxon
61530d68baSNigel Croxon mov edx, eax
62530d68baSNigel Croxon xor eax, eax
63530d68baSNigel Croxon
64530d68baSNigel Croxon ls10:
65530d68baSNigel Croxon mov dword ptr Result[0], eax
66530d68baSNigel Croxon mov dword ptr Result[4], edx
67530d68baSNigel Croxon }
68530d68baSNigel Croxon
69530d68baSNigel Croxon return Result;
70530d68baSNigel Croxon #endif
71530d68baSNigel Croxon }
72530d68baSNigel Croxon
73530d68baSNigel Croxon UINT64
RShiftU64(IN UINT64 Operand,IN UINTN Count)74530d68baSNigel Croxon RShiftU64 (
75530d68baSNigel Croxon IN UINT64 Operand,
76530d68baSNigel Croxon IN UINTN Count
77530d68baSNigel Croxon )
78530d68baSNigel Croxon // Right shift 64bit by 32bit and get a 64bit result
79530d68baSNigel Croxon {
80*09027207SNigel Croxon #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
81530d68baSNigel Croxon return Operand >> Count;
82530d68baSNigel Croxon #else
83530d68baSNigel Croxon UINT64 Result;
84530d68baSNigel Croxon _asm {
85530d68baSNigel Croxon mov eax, dword ptr Operand[0]
86530d68baSNigel Croxon mov edx, dword ptr Operand[4]
87530d68baSNigel Croxon mov ecx, Count
88530d68baSNigel Croxon and ecx, 63
89530d68baSNigel Croxon
90530d68baSNigel Croxon shrd eax, edx, cl
91530d68baSNigel Croxon shr edx, cl
92530d68baSNigel Croxon
93530d68baSNigel Croxon cmp ecx, 32
94530d68baSNigel Croxon jc short rs10
95530d68baSNigel Croxon
96530d68baSNigel Croxon mov eax, edx
97530d68baSNigel Croxon xor edx, edx
98530d68baSNigel Croxon
99530d68baSNigel Croxon rs10:
100530d68baSNigel Croxon mov dword ptr Result[0], eax
101530d68baSNigel Croxon mov dword ptr Result[4], edx
102530d68baSNigel Croxon }
103530d68baSNigel Croxon
104530d68baSNigel Croxon return Result;
105530d68baSNigel Croxon #endif
106530d68baSNigel Croxon }
107530d68baSNigel Croxon
108530d68baSNigel Croxon
109530d68baSNigel Croxon UINT64
MultU64x32(IN UINT64 Multiplicand,IN UINTN Multiplier)110530d68baSNigel Croxon MultU64x32 (
111530d68baSNigel Croxon IN UINT64 Multiplicand,
112530d68baSNigel Croxon IN UINTN Multiplier
113530d68baSNigel Croxon )
114530d68baSNigel Croxon // Multiple 64bit by 32bit and get a 64bit result
115530d68baSNigel Croxon {
116*09027207SNigel Croxon #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
117530d68baSNigel Croxon return Multiplicand * Multiplier;
118530d68baSNigel Croxon #else
119530d68baSNigel Croxon UINT64 Result;
120530d68baSNigel Croxon _asm {
121530d68baSNigel Croxon mov eax, dword ptr Multiplicand[0]
122530d68baSNigel Croxon mul Multiplier
123530d68baSNigel Croxon mov dword ptr Result[0], eax
124530d68baSNigel Croxon mov dword ptr Result[4], edx
125530d68baSNigel Croxon mov eax, dword ptr Multiplicand[4]
126530d68baSNigel Croxon mul Multiplier
127530d68baSNigel Croxon add dword ptr Result[4], eax
128530d68baSNigel Croxon }
129530d68baSNigel Croxon
130530d68baSNigel Croxon return Result;
131530d68baSNigel Croxon #endif
132530d68baSNigel Croxon }
133530d68baSNigel Croxon
134530d68baSNigel Croxon UINT64
DivU64x32(IN UINT64 Dividend,IN UINTN Divisor,OUT UINTN * Remainder OPTIONAL)135530d68baSNigel Croxon DivU64x32 (
136530d68baSNigel Croxon IN UINT64 Dividend,
137530d68baSNigel Croxon IN UINTN Divisor,
138530d68baSNigel Croxon OUT UINTN *Remainder OPTIONAL
139530d68baSNigel Croxon )
140530d68baSNigel Croxon // divide 64bit by 32bit and get a 64bit result
141530d68baSNigel Croxon // N.B. only works for 31bit divisors!!
142530d68baSNigel Croxon {
143*09027207SNigel Croxon #if defined(__GNUC__) || defined(_MSC_EXTENSIONS)
144530d68baSNigel Croxon if (Remainder)
145530d68baSNigel Croxon *Remainder = Dividend % Divisor;
146530d68baSNigel Croxon return Dividend / Divisor;
147530d68baSNigel Croxon #else
148530d68baSNigel Croxon UINT32 Rem;
149530d68baSNigel Croxon UINT32 bit;
150530d68baSNigel Croxon
151530d68baSNigel Croxon ASSERT (Divisor != 0);
152530d68baSNigel Croxon ASSERT ((Divisor >> 31) == 0);
153530d68baSNigel Croxon
154530d68baSNigel Croxon //
155530d68baSNigel Croxon // For each bit in the dividend
156530d68baSNigel Croxon //
157530d68baSNigel Croxon
158530d68baSNigel Croxon Rem = 0;
159530d68baSNigel Croxon for (bit=0; bit < 64; bit++) {
160530d68baSNigel Croxon _asm {
161530d68baSNigel Croxon shl dword ptr Dividend[0], 1 ; shift rem:dividend left one
162530d68baSNigel Croxon rcl dword ptr Dividend[4], 1
163530d68baSNigel Croxon rcl dword ptr Rem, 1
164530d68baSNigel Croxon
165530d68baSNigel Croxon mov eax, Rem
166530d68baSNigel Croxon cmp eax, Divisor ; Is Rem >= Divisor?
167530d68baSNigel Croxon cmc ; No - do nothing
168530d68baSNigel Croxon sbb eax, eax ; Else,
169530d68baSNigel Croxon sub dword ptr Dividend[0], eax ; set low bit in dividen
170530d68baSNigel Croxon and eax, Divisor ; and
171530d68baSNigel Croxon sub Rem, eax ; subtract divisor
172530d68baSNigel Croxon }
173530d68baSNigel Croxon }
174530d68baSNigel Croxon
175530d68baSNigel Croxon if (Remainder) {
176530d68baSNigel Croxon *Remainder = Rem;
177530d68baSNigel Croxon }
178530d68baSNigel Croxon
179530d68baSNigel Croxon return Dividend;
180530d68baSNigel Croxon #endif
181530d68baSNigel Croxon }
182