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