|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32\euser\epoc\x86\uc_utl.cia |
|
15 // |
|
16 // |
|
17 |
|
18 #include <u32exec.h> |
|
19 #include <e32base.h> |
|
20 #include <e32rom.h> |
|
21 #include <e32svr.h> |
|
22 #include <e32hashtab.h> |
|
23 |
|
24 |
|
25 // Dummy so we can use same DEF file as WINS |
|
26 EXPORT_C void BootEpoc(TBool) |
|
27 { |
|
28 } |
|
29 |
|
30 |
|
31 EXPORT_C __NAKED__ void RFastLock::Wait() |
|
32 { |
|
33 THISCALL_PROLOG0() |
|
34 asm("lock sub dword ptr [ecx+4], 1"); |
|
35 asm("jnc fast_lock_wait_sem"); |
|
36 THISCALL_EPILOG0() |
|
37 asm("fast_lock_wait_sem:"); |
|
38 asm("mov eax, %0": : "i"(EExecSemaphoreWait)); |
|
39 asm("mov ecx, [ecx]"); |
|
40 asm("xor edx, edx"); |
|
41 asm("int 0x21"); |
|
42 THISCALL_EPILOG0() |
|
43 } |
|
44 |
|
45 EXPORT_C __NAKED__ void RFastLock::Signal() |
|
46 { |
|
47 THISCALL_PROLOG0() |
|
48 asm("lock add dword ptr [ecx+4], 1"); |
|
49 asm("jne fast_lock_signal_sem"); |
|
50 THISCALL_EPILOG0() |
|
51 asm("fast_lock_signal_sem:"); |
|
52 asm("mov eax, %0": : "i"(EExecSemaphoreSignal1)); |
|
53 asm("mov ecx, [ecx]"); |
|
54 asm("int 0x21"); |
|
55 THISCALL_EPILOG0() |
|
56 } |
|
57 |
|
58 #ifdef __MEM_MACHINE_CODED__ |
|
59 __NAKED__ EXPORT_C void Mem::Swap( TAny* /*aPtr1*/, TAny* /*aPtr2*/, TInt /*aLength*/ ) |
|
60 /** |
|
61 Swaps a number of bytes of data between two specified locations. |
|
62 |
|
63 The source and target areas can overlap. |
|
64 |
|
65 @param aPtr1 A pointer to the first location taking part in the swap. |
|
66 @param aPtr2 A pointer to second location taking part in the swap. |
|
67 @param aLength The number of bytes to be swapped between the two locations. |
|
68 This value must not be negative. |
|
69 |
|
70 @panic USER 94 In debug builds only, if aLength is negative. |
|
71 */ |
|
72 |
|
73 // |
|
74 // Swap the contents of *aPtr1 with *aPtr2. |
|
75 // NB We assume ES=DS on entry. |
|
76 // |
|
77 { |
|
78 asm("push esi"); |
|
79 asm("push edi"); |
|
80 asm("mov edi,[esp+12]");// aPtr1 address into edi |
|
81 asm("mov esi,[esp+16]");// aPtr2 address into esi |
|
82 asm("mov ecx,[esp+20]");// byte count into ecx |
|
83 asm("pushfd"); |
|
84 |
|
85 asm("test ecx,ecx"); // |
|
86 asm("jz short memswap0");// if length=0, nothing to do |
|
87 asm("cld"); // go forwards through array |
|
88 asm("cmp ecx,7"); // if length<7 don't bother with alignment check |
|
89 asm("jc short memswap1");// |
|
90 asm("mov edx,ecx"); // length into edx |
|
91 // number of bytes to align aPtr1 = 4-(edi mod 4) |
|
92 asm("mov ecx,4"); |
|
93 asm("sub ecx,edi"); // |
|
94 asm("and ecx,3"); // into ecx |
|
95 asm("jz short memswap2");// if aligned, proceed with dword swap |
|
96 asm("sub edx,ecx"); // subtract number of bytes from length |
|
97 asm("memswap3:"); |
|
98 asm("mov al,[edi]"); // al = *aPtr1 |
|
99 asm("mov ah,[esi]"); // ah = *aPtr2 |
|
100 asm("mov [esi],al"); // *aPtr2=al |
|
101 asm("mov [edi],ah"); // *aPtr1=ah |
|
102 asm("inc esi"); // aPtr2++ |
|
103 asm("inc edi"); // aPtr1++ |
|
104 asm("dec ecx"); // |
|
105 asm("jnz short memswap3");// loop ecx times - edi is now dword aligned |
|
106 asm("memswap2:"); |
|
107 asm("push ebx"); // preserve ebx |
|
108 asm("mov ecx,edx"); // length back into ecx |
|
109 asm("mov ah,cl"); // save lower two bits of dword count in ah bits 3,2 |
|
110 asm("add ecx,12"); // divide dword count by 4, rounding to next higher integer |
|
111 asm("shr ecx,4"); // this gives loop count for unfolded loop |
|
112 asm("shl ah,4"); // lower two bits of dword count into ah bits 7,6 |
|
113 asm("sahf"); // and into SF,ZF |
|
114 asm("jns short memswap8");// branch if lower two bits of dword count = 0 or 1 |
|
115 asm("jz short memswap5");// if lower two bits = 3, miss out first unfolding of loop |
|
116 asm("jnz short memswap6"); // if lower two bits = 2, miss out first two unfoldings |
|
117 asm("memswap8:"); |
|
118 asm("jz short memswap7");// if lower two bits = 1, miss out first three unfoldings |
|
119 asm("memswap4:"); |
|
120 asm("mov eax,[edi]"); // eax = *aPtr1 |
|
121 asm("mov ebx,[esi]"); // ebx = *aPtr2 |
|
122 asm("mov [esi],eax"); // *aPtr2=eax |
|
123 asm("mov [edi],ebx"); // *aPtr1=ebx |
|
124 asm("add edi,4"); // aPtr1++ |
|
125 asm("add esi,4"); // aPtr2++ |
|
126 asm("memswap5:"); |
|
127 asm("mov eax,[edi]"); // eax = *aPtr1 |
|
128 asm("mov ebx,[esi]"); // ebx = *aPtr2 |
|
129 asm("mov [esi],eax"); // *aPtr2=eax |
|
130 asm("mov [edi],ebx"); // *aPtr1=ebx |
|
131 asm("add edi,4"); // aPtr1++ |
|
132 asm("add esi,4"); // aPtr2++ |
|
133 asm("memswap6:"); |
|
134 asm("mov eax,[edi]"); // eax = *aPtr1 |
|
135 asm("mov ebx,[esi]"); // ebx = *aPtr2 |
|
136 asm("mov [esi],eax"); // *aPtr2=eax |
|
137 asm("mov [edi],ebx"); // *aPtr1=ebx |
|
138 asm("add edi,4"); // aPtr1++ |
|
139 asm("add esi,4"); // aPtr2++ |
|
140 asm("memswap7:"); |
|
141 asm("mov eax,[edi]"); // eax = *aPtr1 |
|
142 asm("mov ebx,[esi]"); // ebx = *aPtr2 |
|
143 asm("mov [esi],eax"); // *aPtr2=eax |
|
144 asm("mov [edi],ebx"); // *aPtr1=ebx |
|
145 asm("add edi,4"); // aPtr1++ |
|
146 asm("add esi,4"); // aPtr2++ |
|
147 asm("dec ecx"); |
|
148 asm("jnz short memswap4"); // loop ecx times to do main part of swap |
|
149 asm("mov ecx,edx"); // length back into ecx |
|
150 asm("pop ebx"); // restore ebx |
|
151 asm("and ecx,3"); // number of remaining bytes to move |
|
152 asm("jz short memswap0");// if zero, we are finished |
|
153 asm("memswap1:"); // *** come here for small swap |
|
154 asm("mov al,[edi]"); // al = *aPtr1 |
|
155 asm("mov ah,[esi]"); // ah = *aPtr2 |
|
156 asm("mov [esi],al"); // *aPtr2=al |
|
157 asm("mov [edi],ah"); // *aPtr1=ah |
|
158 asm("inc esi"); // aPtr2++ |
|
159 asm("inc edi"); // aPtr1++ |
|
160 asm("dec ecx"); // |
|
161 asm("jnz short memswap1"); // loop ecx times - edi is now dword aligned |
|
162 |
|
163 asm("memswap0:"); |
|
164 asm("popfd"); |
|
165 asm("pop edi"); |
|
166 asm("pop esi"); |
|
167 asm("ret"); |
|
168 } |
|
169 #endif |
|
170 |
|
171 // Hash an 8 bit string at aPtr, length aLen bytes. |
|
172 __NAKED__ TUint32 DefaultStringHash(const TUint8* /*aPtr*/, TInt /*aLen*/) |
|
173 { |
|
174 asm("push esi"); |
|
175 asm("mov esi, [esp+8]"); |
|
176 asm("mov ecx, [esp+12]"); |
|
177 asm("xor eax, eax"); |
|
178 asm("sub ecx, 4"); |
|
179 asm("jb lt4"); |
|
180 asm("ge4:"); |
|
181 asm("xor eax, [esi]"); |
|
182 asm("add esi, 4"); |
|
183 asm("mov edx, 0x9E3779B9"); |
|
184 asm("mul edx"); |
|
185 asm("sub ecx, 4"); |
|
186 asm("jae ge4"); |
|
187 asm("lt4:"); |
|
188 asm("add ecx, 4"); |
|
189 asm("jz done"); |
|
190 asm("xor edx, edx"); |
|
191 asm("cmp ecx, 2"); |
|
192 asm("jbe le2"); |
|
193 asm("mov dl, [esi+2]"); |
|
194 asm("shl edx, 16"); |
|
195 asm("le2:"); |
|
196 asm("cmp ecx, 2"); |
|
197 asm("jb onemore"); |
|
198 asm("mov dh, [esi+1]"); |
|
199 asm("onemore:"); |
|
200 asm("mov dl, [esi]"); |
|
201 asm("xor eax, edx"); |
|
202 asm("mov edx, 0x9E3779B9"); |
|
203 asm("mul edx"); |
|
204 asm("done:"); |
|
205 asm("pop esi"); |
|
206 asm("ret"); |
|
207 } |
|
208 |
|
209 // Hash a 16 bit string at aPtr, length aLen bytes. |
|
210 __NAKED__ TUint32 DefaultWStringHash(const TUint16* /*aPtr*/, TInt /*aLen*/) |
|
211 { |
|
212 asm("push esi"); |
|
213 asm("mov esi, [esp+8]"); |
|
214 asm("mov ecx, [esp+12]"); |
|
215 asm("xor eax, eax"); |
|
216 asm("sub ecx, 8"); |
|
217 asm("jb lt8"); |
|
218 asm("ge8:"); |
|
219 asm("mov edx, [esi+4]"); |
|
220 asm("xor eax, [esi]"); |
|
221 asm("add esi, 8"); |
|
222 asm("rol edx, 8"); |
|
223 asm("xor eax, edx"); |
|
224 asm("mov edx, 0x9E3779B9"); |
|
225 asm("mul edx"); |
|
226 asm("sub ecx, 8"); |
|
227 asm("jae ge8"); |
|
228 asm("lt8:"); |
|
229 asm("add ecx, 8"); |
|
230 asm("jz done_defwstrhash"); |
|
231 asm("xor edx, edx"); |
|
232 asm("cmp ecx, 4"); |
|
233 asm("jbe le4"); |
|
234 asm("mov dx, [esi+4]"); |
|
235 asm("rol edx, 8"); |
|
236 asm("xor eax, edx"); |
|
237 asm("xor edx, edx"); |
|
238 asm("le4:"); |
|
239 asm("cmp ecx, 4"); |
|
240 asm("jb onemore_defwstrhash"); |
|
241 asm("mov dx, [esi+2]"); |
|
242 asm("shl edx, 16"); |
|
243 asm("onemore_defwstrhash:"); |
|
244 asm("mov dx, [esi]"); |
|
245 asm("xor eax, edx"); |
|
246 asm("mov edx, 0x9E3779B9"); |
|
247 asm("mul edx"); |
|
248 asm("done_defwstrhash:"); |
|
249 asm("pop esi"); |
|
250 asm("ret"); |
|
251 } |
|
252 |
|
253 |
|
254 /** |
|
255 @publishedAll |
|
256 @released |
|
257 |
|
258 Calculate a 32 bit hash from a 32 bit integer. |
|
259 |
|
260 @param aInt The integer to be hashed. |
|
261 @return The calculated 32 bit hash value. |
|
262 */ |
|
263 EXPORT_C __NAKED__ TUint32 DefaultHash::Integer(const TInt& /*aInt*/) |
|
264 { |
|
265 asm("mov edx, [esp+4]"); |
|
266 asm("mov eax, 0x9E3779B9"); |
|
267 asm("mul dword ptr [edx]"); |
|
268 asm("ret"); |
|
269 } |
|
270 |