|
1 // Copyright (c) 1995-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\arm\uc_exec.cia |
|
15 // |
|
16 // |
|
17 |
|
18 #define __GEN_USER_EXEC_CODE__ |
|
19 |
|
20 #include "uc_std.h" |
|
21 #include <e32svr.h> |
|
22 #include <u32exec.h> |
|
23 |
|
24 /****************************************************************************** |
|
25 * Slow executive calls with preprocessing or extra arguments |
|
26 ******************************************************************************/ |
|
27 |
|
28 __NAKED__ TInt Exec::SessionSend(TInt /*aHandle*/, TInt /*aFunction*/, TAny* /*aPtr*/, TRequestStatus* /*aStatus*/) |
|
29 // |
|
30 // Send a blind message to the server. |
|
31 // |
|
32 { |
|
33 asm("stmfd sp!, {r4-r8,lr} "); |
|
34 asm("movs r8, r2 "); // test for aPtr==NULL, set iArgFlags=0 if so |
|
35 asm("ldmneia r2, {r4-r8} "); // else get args into r4-r8 |
|
36 asm("swi %a0" : : "i" (EExecSessionSend|EXECUTIVE_SLOW)); |
|
37 __POPRET("r4-r8,"); |
|
38 } |
|
39 |
|
40 __NAKED__ TInt Exec::SessionSendSync(TInt /*aHandle*/, TInt /*aFunction*/, TAny* /*aPtr*/, TRequestStatus* /*aStatus*/) |
|
41 // |
|
42 // Send a blind message to the server using thread's dedicated message slot. |
|
43 // |
|
44 { |
|
45 asm("stmfd sp!, {r4-r8,lr} "); |
|
46 asm("movs r8, r2 "); // test for aPtr==NULL, set iArgFlags=0 if so |
|
47 asm("ldmneia r2, {r4-r8} "); // else get args into r4-r8 |
|
48 asm("swi %a0" : : "i" (EExecSessionSendSync|EXECUTIVE_SLOW)); |
|
49 __POPRET("r4-r8,"); |
|
50 } |
|
51 |
|
52 __NAKED__ TInt Exec::MessageIpcCopy(TInt /*aHandle*/, TInt /*aParam*/, SIpcCopyInfo& /*aInfo*/, TInt /*anOffset*/) |
|
53 // |
|
54 // IPC transfer using message handle |
|
55 // |
|
56 { |
|
57 asm("stmfd sp!, {r4-r6,lr} "); |
|
58 asm("ldmia r2, {r4-r6} "); // load SIpcCopyInfo into r4-r6 |
|
59 asm("swi %a0" : : "i" (EExecMessageIpcCopy|EXECUTIVE_SLOW)); |
|
60 __POPRET("r4-r6,"); |
|
61 } |
|
62 |
|
63 __NAKED__ EXPORT_C TBool BTrace::Out(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) |
|
64 { |
|
65 // fall through... |
|
66 } |
|
67 |
|
68 __NAKED__ EXPORT_C TBool BTrace::OutX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) |
|
69 { |
|
70 asm("stmfd sp!, {r4-r6,lr}"); |
|
71 asm("mov r4, r2"); |
|
72 asm("mov r5, r3"); |
|
73 asm("mov r6, lr"); |
|
74 asm("mov r3, #0"); |
|
75 asm("swi %a0" : : "i" (EExecBTraceOut|EXECUTIVE_SLOW)); |
|
76 __POPRET("r4-r6,"); |
|
77 } |
|
78 |
|
79 __NAKED__ EXPORT_C TBool BTrace::OutN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) |
|
80 { |
|
81 // fall through... |
|
82 } |
|
83 |
|
84 __NAKED__ EXPORT_C TBool BTrace::OutNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) |
|
85 { |
|
86 asm("stmfd sp!, {r4-r6,lr}"); |
|
87 asm("mov r4, r2"); |
|
88 asm("mov r5, r3"); |
|
89 asm("ldr r3, [sp,#16]"); |
|
90 asm("mov r6, lr"); |
|
91 asm("swi %a0" : : "i" (EExecBTraceOut|EXECUTIVE_SLOW)); |
|
92 __POPRET("r4-r6,"); |
|
93 } |
|
94 |
|
95 __NAKED__ EXPORT_C TBool BTrace::OutBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize) |
|
96 { |
|
97 asm("stmfd sp!, {r4-r6,lr}"); |
|
98 asm("mov r4, #0"); |
|
99 asm("mov r5, r2"); |
|
100 asm("mov r6, lr"); |
|
101 |
|
102 asm("cmp r3, #8"); |
|
103 asm("bls 0f"); |
|
104 asm("cmp r3, #%a0" : : "i" (KMaxBTraceDataArray+4u)); |
|
105 asm("bls 1f"); |
|
106 asm("swi %a0" : : "i" (EExecBTraceOutBig|EXECUTIVE_SLOW)); |
|
107 __POPRET("r4-r6,"); |
|
108 |
|
109 asm("1:"); |
|
110 asm("add r0, r0, #4"); |
|
111 asm("sub r3, r3, #4"); |
|
112 asm("ldr r4, [r5] ,#4"); |
|
113 asm("swi %a0" : : "i" (EExecBTraceOut|EXECUTIVE_SLOW)); |
|
114 __POPRET("r4-r6,"); |
|
115 |
|
116 asm("0:"); |
|
117 asm("cmp r3, #0"); |
|
118 asm("ldrne r4, [r2]"); |
|
119 asm("cmp r3, #4"); |
|
120 asm("ldrhi r5, [r2, #4]"); |
|
121 asm("add r0, r0, r3"); |
|
122 asm("mov r3, #0"); |
|
123 asm("swi %a0" : : "i" (EExecBTraceOut|EXECUTIVE_SLOW)); |
|
124 __POPRET("r4-r6,"); |
|
125 } |
|
126 |
|
127 __NAKED__ EXPORT_C TBool BTrace::OutFiltered(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) |
|
128 { |
|
129 // fall through... |
|
130 } |
|
131 |
|
132 __NAKED__ EXPORT_C TBool BTrace::OutFilteredX(TUint32 a0, TUint32 a1, TUint32 a2, TUint32 a3) |
|
133 { |
|
134 asm("stmfd sp!, {r4-r6,lr}"); |
|
135 asm("orr r0, r0, #%a0" : : "i" (EMissingRecord<<BTrace::EFlagsIndex*8)); // overload meaning of this flag to indicate filtered trace |
|
136 asm("mov r4, r2"); |
|
137 asm("mov r5, r3"); |
|
138 asm("mov r6, lr"); |
|
139 asm("mov r3, #0"); |
|
140 asm("swi %a0" : : "i" (EExecBTraceOut|EXECUTIVE_SLOW)); |
|
141 __POPRET("r4-r6,"); |
|
142 } |
|
143 |
|
144 __NAKED__ EXPORT_C TBool BTrace::OutFilteredN(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) |
|
145 { |
|
146 // fall through... |
|
147 } |
|
148 |
|
149 __NAKED__ EXPORT_C TBool BTrace::OutFilteredNX(TUint32 a0, TUint32 a1, TUint32 a2, const TAny* aData, TInt aDataSize) |
|
150 { |
|
151 asm("stmfd sp!, {r4-r6,lr}"); |
|
152 asm("orr r0, r0, #%a0" : : "i" (EMissingRecord<<BTrace::EFlagsIndex*8)); // overload meaning of this flag to indicate filtered trace |
|
153 asm("mov r4, r2"); |
|
154 asm("mov r5, r3"); |
|
155 asm("ldr r3, [sp,#16]"); |
|
156 asm("mov r6, lr"); |
|
157 asm("swi %a0" : : "i" (EExecBTraceOut|EXECUTIVE_SLOW)); |
|
158 __POPRET("r4-r6,"); |
|
159 } |
|
160 |
|
161 __NAKED__ EXPORT_C TBool BTrace::OutFilteredBig(TUint32 a0, TUint32 a1, const TAny* aData, TInt aDataSize) |
|
162 { |
|
163 asm("stmfd sp!, {r4-r6,lr}"); |
|
164 asm("orr r0, r0, #%a0" : : "i" (EMissingRecord<<BTrace::EFlagsIndex*8)); // overload meaning of this flag to indicate filtered trace |
|
165 asm("mov r4, #0"); |
|
166 asm("mov r5, r2"); |
|
167 asm("mov r6, lr"); |
|
168 |
|
169 asm("cmp r3, #8"); |
|
170 asm("bls 0f"); |
|
171 asm("cmp r3, #%a0" : : "i" (KMaxBTraceDataArray+4u)); |
|
172 asm("bls 1f"); |
|
173 asm("swi %a0" : : "i" (EExecBTraceOutBig|EXECUTIVE_SLOW)); |
|
174 __POPRET("r4-r6,"); |
|
175 |
|
176 asm("1:"); |
|
177 asm("add r0, r0, #4"); |
|
178 asm("sub r3, r3, #4"); |
|
179 asm("ldr r4, [r5] ,#4"); |
|
180 asm("swi %a0" : : "i" (EExecBTraceOut|EXECUTIVE_SLOW)); |
|
181 __POPRET("r4-r6,"); |
|
182 |
|
183 asm("0:"); |
|
184 asm("cmp r3, #0"); |
|
185 asm("ldrne r4, [r2]"); |
|
186 asm("cmp r3, #4"); |
|
187 asm("ldrhi r5, [r2, #4]"); |
|
188 asm("add r0, r0, r3"); |
|
189 asm("mov r3, #0"); |
|
190 asm("swi %a0" : : "i" (EExecBTraceOut|EXECUTIVE_SLOW)); |
|
191 __POPRET("r4-r6,"); |
|
192 } |
|
193 |
|
194 __NAKED__ EXPORT_C TBool BTrace::OutFilteredPcFormatBig(TUint32 a0, TUint32 aModuleUid, TUint32 aPc, TUint16 aFormatId, const TAny* aData, TInt aDataSize) |
|
195 { |
|
196 asm("stmfd sp!, {r4-r6,lr}"); |
|
197 asm("orr r0, r0, #%a0" : : "i" (EMissingRecord<<BTrace::EFlagsIndex*8)); // overload meaning of this flag to indicate filtered trace |
|
198 asm("mov r4, r3"); |
|
199 asm("ldr r5, [sp, #16]"); |
|
200 asm("mov r6, r2"); |
|
201 asm("ldr r3, [sp, #20]"); |
|
202 |
|
203 asm("cmp r3, #%a0" : : "i" (KMaxBTraceDataArray+0u)); |
|
204 asm("bls 0f"); |
|
205 asm("swi %a0" : : "i" (EExecUTraceOut|EXECUTIVE_SLOW)); |
|
206 __POPRET("r4-r6,"); |
|
207 |
|
208 asm("0:"); |
|
209 asm("add r0, r0, #4"); |
|
210 asm("swi %a0" : : "i" (EExecBTraceOut|EXECUTIVE_SLOW)); |
|
211 __POPRET("r4-r6,"); |
|
212 } |
|
213 |
|
214 EXPORT_C __NAKED__ void RThread::RequestComplete(TRequestStatus*& aStatus, TInt aReason) const |
|
215 /** |
|
216 Signals this thread that an asynchronous request originating from this thread, |
|
217 is complete. |
|
218 |
|
219 The request is associated with the specified request status object supplied |
|
220 by this thread. |
|
221 |
|
222 Typically, the caller of this function is the service provider responsible |
|
223 for satisfying the request made by this thread. |
|
224 |
|
225 The request is completed with the completion code passed in aReason. This |
|
226 value is copied into this thread's request status, *aStatus, before signalling |
|
227 this thread's request semaphore. |
|
228 |
|
229 The meaning of the completion code is a matter of convention to be decided |
|
230 between the service provider and this thread. |
|
231 |
|
232 In a client-server situation, completion of a request takes place in the context |
|
233 of the server thread, but the pointer is interpreted in the address space |
|
234 of the client. |
|
235 |
|
236 It is often the case in client-server situations that the client and the server |
|
237 are in the same address space (i.e. the same process). |
|
238 |
|
239 Setting the pointer to the request status to NULL is a convenience, not all |
|
240 servers need it. |
|
241 |
|
242 @param aStatus A reference to a pointer to the request status originally |
|
243 supplied by this thread. This is a pointer into this thread's |
|
244 address space, which may be different to the thread currently |
|
245 executing (this code). On return, the pointer to the request |
|
246 status is set to NULL. |
|
247 |
|
248 @param aReason The completion code of this request. |
|
249 */ |
|
250 // |
|
251 // Signal a request completion. |
|
252 // |
|
253 { |
|
254 asm("mov r3, #0 "); |
|
255 #ifdef __CPU_ARM_HAS_LDREX_STREX |
|
256 #ifdef __SMP__ |
|
257 __DATA_MEMORY_BARRIER__(r3); // release semantics |
|
258 #endif |
|
259 asm(" str r14, [sp, #-4]! "); |
|
260 asm("tryagain: "); |
|
261 LDREX(12, 1); // read |
|
262 STREX(14, 3, 1); // write |
|
263 asm(" teq r14, #0 "); // success? |
|
264 asm(" bne tryagain "); // no! |
|
265 asm(" cmp r12, #0 "); // if pointer not null... |
|
266 asm(" ldrne r0, [r0] "); |
|
267 asm(" strne r2, [r12] "); // store aReason into request status |
|
268 asm(" swine %a0" : : "i" (EExecThreadRequestSignal|EXECUTIVE_SLOW)); |
|
269 asm(" ldr pc, [sp], #4 "); // return |
|
270 #else |
|
271 asm("swp r3, r3, [r1] "); // clear TRequestStatus pointer, pointer into r3 |
|
272 asm("ldr r0, [r0] "); |
|
273 asm("cmp r3, #0 "); // if pointer not null... |
|
274 asm("strne r2, [r3] "); // store aReason into request status |
|
275 asm("swine %a0" : : "i" (EExecThreadRequestSignal|EXECUTIVE_SLOW)); |
|
276 __JUMP(,lr); |
|
277 #endif |
|
278 } |
|
279 |
|
280 /** |
|
281 Signal this threads request semaphore. |
|
282 |
|
283 This is similar to RThread::RequestComplete() except that no TRequestStatus object |
|
284 is modified. |
|
285 |
|
286 May only be used to signal a thread in the same process as the callers. |
|
287 |
|
288 @panic KERN-EXEC 46 if the thread is not in the same process as the callers |
|
289 */ |
|
290 EXPORT_C __NAKED__ void RThread::RequestSignal() const |
|
291 { |
|
292 asm("ldr r0, [r0] "); |
|
293 asm("swi %a0" : : "i" (EExecThreadRequestSignal|EXECUTIVE_SLOW)); |
|
294 __JUMP(,lr); |
|
295 } |
|
296 |
|
297 |
|
298 |
|
299 __NAKED__ void ExitCurrentThread(TExitType /*aType*/, TInt /*aReason*/, const TDesC8* /*aCategory*/) |
|
300 { |
|
301 asm("mov r3, r2 "); |
|
302 asm("mov r2, r1 "); |
|
303 asm("mov r1, r0 "); |
|
304 asm("mvn r0, #0xfe "); // r0=0xffffff01 |
|
305 asm("bic r0, r0, #0x7f00 "); // r0=0xffff8001=KCurrentThreadHandle |
|
306 asm("swi %a0" : : "i" (EExecThreadKill|EXECUTIVE_SLOW)); |
|
307 __JUMP(,lr); |
|
308 } |