root / op-arm.c @ 4021dab0
History | View | Annotate | Download (12.5 kB)
1 |
/*
|
---|---|
2 |
* ARM micro operations
|
3 |
*
|
4 |
* Copyright (c) 2003 Fabrice Bellard
|
5 |
*
|
6 |
* This library is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU Lesser General Public
|
8 |
* License as published by the Free Software Foundation; either
|
9 |
* version 2 of the License, or (at your option) any later version.
|
10 |
*
|
11 |
* This library is distributed in the hope that it will be useful,
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 |
* Lesser General Public License for more details.
|
15 |
*
|
16 |
* You should have received a copy of the GNU Lesser General Public
|
17 |
* License along with this library; if not, write to the Free Software
|
18 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19 |
*/
|
20 |
#include "exec-arm.h" |
21 |
|
22 |
#define REGNAME r0
|
23 |
#define REG (env->regs[0]) |
24 |
#include "op-arm-template.h" |
25 |
|
26 |
#define REGNAME r1
|
27 |
#define REG (env->regs[1]) |
28 |
#include "op-arm-template.h" |
29 |
|
30 |
#define REGNAME r2
|
31 |
#define REG (env->regs[2]) |
32 |
#include "op-arm-template.h" |
33 |
|
34 |
#define REGNAME r3
|
35 |
#define REG (env->regs[3]) |
36 |
#include "op-arm-template.h" |
37 |
|
38 |
#define REGNAME r4
|
39 |
#define REG (env->regs[4]) |
40 |
#include "op-arm-template.h" |
41 |
|
42 |
#define REGNAME r5
|
43 |
#define REG (env->regs[5]) |
44 |
#include "op-arm-template.h" |
45 |
|
46 |
#define REGNAME r6
|
47 |
#define REG (env->regs[6]) |
48 |
#include "op-arm-template.h" |
49 |
|
50 |
#define REGNAME r7
|
51 |
#define REG (env->regs[7]) |
52 |
#include "op-arm-template.h" |
53 |
|
54 |
#define REGNAME r8
|
55 |
#define REG (env->regs[8]) |
56 |
#include "op-arm-template.h" |
57 |
|
58 |
#define REGNAME r9
|
59 |
#define REG (env->regs[9]) |
60 |
#include "op-arm-template.h" |
61 |
|
62 |
#define REGNAME r10
|
63 |
#define REG (env->regs[10]) |
64 |
#include "op-arm-template.h" |
65 |
|
66 |
#define REGNAME r11
|
67 |
#define REG (env->regs[11]) |
68 |
#include "op-arm-template.h" |
69 |
|
70 |
#define REGNAME r12
|
71 |
#define REG (env->regs[12]) |
72 |
#include "op-arm-template.h" |
73 |
|
74 |
#define REGNAME r13
|
75 |
#define REG (env->regs[13]) |
76 |
#include "op-arm-template.h" |
77 |
|
78 |
#define REGNAME r14
|
79 |
#define REG (env->regs[14]) |
80 |
#include "op-arm-template.h" |
81 |
|
82 |
#define REGNAME r15
|
83 |
#define REG (env->regs[15]) |
84 |
#include "op-arm-template.h" |
85 |
|
86 |
void OPPROTO op_movl_T0_0(void) |
87 |
{ |
88 |
T0 = 0;
|
89 |
} |
90 |
|
91 |
void OPPROTO op_movl_T0_im(void) |
92 |
{ |
93 |
T0 = PARAM1; |
94 |
} |
95 |
|
96 |
void OPPROTO op_movl_T1_im(void) |
97 |
{ |
98 |
T1 = PARAM1; |
99 |
} |
100 |
|
101 |
void OPPROTO op_movl_T2_im(void) |
102 |
{ |
103 |
T2 = PARAM1; |
104 |
} |
105 |
|
106 |
void OPPROTO op_addl_T1_im(void) |
107 |
{ |
108 |
T1 += PARAM1; |
109 |
} |
110 |
|
111 |
void OPPROTO op_addl_T1_T2(void) |
112 |
{ |
113 |
T1 += T2; |
114 |
} |
115 |
|
116 |
void OPPROTO op_subl_T1_T2(void) |
117 |
{ |
118 |
T1 -= T2; |
119 |
} |
120 |
|
121 |
void OPPROTO op_addl_T0_T1(void) |
122 |
{ |
123 |
T0 += T1; |
124 |
} |
125 |
|
126 |
void OPPROTO op_addl_T0_T1_cc(void) |
127 |
{ |
128 |
unsigned int src1; |
129 |
src1 = T0; |
130 |
T0 += T1; |
131 |
env->NZF = T0; |
132 |
env->CF = T0 < src1; |
133 |
env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
|
134 |
} |
135 |
|
136 |
void OPPROTO op_adcl_T0_T1(void) |
137 |
{ |
138 |
T0 += T1 + env->CF; |
139 |
} |
140 |
|
141 |
void OPPROTO op_adcl_T0_T1_cc(void) |
142 |
{ |
143 |
unsigned int src1; |
144 |
src1 = T0; |
145 |
if (!env->CF) {
|
146 |
T0 += T1; |
147 |
env->CF = T0 < src1; |
148 |
} else {
|
149 |
T0 += T1 + 1;
|
150 |
env->CF = T0 <= src1; |
151 |
} |
152 |
env->VF = (src1 ^ T1 ^ -1) & (src1 ^ T0);
|
153 |
env->NZF = T0; |
154 |
FORCE_RET(); |
155 |
} |
156 |
|
157 |
#define OPSUB(sub, sbc, res, T0, T1) \
|
158 |
\ |
159 |
void OPPROTO op_ ## sub ## l_T0_T1(void) \ |
160 |
{ \ |
161 |
res = T0 - T1; \ |
162 |
} \ |
163 |
\ |
164 |
void OPPROTO op_ ## sub ## l_T0_T1_cc(void) \ |
165 |
{ \ |
166 |
unsigned int src1; \ |
167 |
src1 = T0; \ |
168 |
T0 -= T1; \ |
169 |
env->NZF = T0; \ |
170 |
env->CF = src1 >= T1; \ |
171 |
env->VF = (src1 ^ T1) & (src1 ^ T0); \ |
172 |
res = T0; \ |
173 |
} \ |
174 |
\ |
175 |
void OPPROTO op_ ## sbc ## l_T0_T1(void) \ |
176 |
{ \ |
177 |
res = T0 - T1 + env->CF - 1; \
|
178 |
} \ |
179 |
\ |
180 |
void OPPROTO op_ ## sbc ## l_T0_T1_cc(void) \ |
181 |
{ \ |
182 |
unsigned int src1; \ |
183 |
src1 = T0; \ |
184 |
if (!env->CF) { \
|
185 |
T0 = T0 - T1 - 1; \
|
186 |
env->CF = src1 >= T1; \ |
187 |
} else { \
|
188 |
T0 = T0 - T1; \ |
189 |
env->CF = src1 > T1; \ |
190 |
} \ |
191 |
env->VF = (src1 ^ T1) & (src1 ^ T0); \ |
192 |
env->NZF = T0; \ |
193 |
res = T0; \ |
194 |
FORCE_RET(); \ |
195 |
} |
196 |
|
197 |
OPSUB(sub, sbc, T0, T0, T1) |
198 |
|
199 |
OPSUB(rsb, rsc, T0, T1, T0) |
200 |
|
201 |
void OPPROTO op_andl_T0_T1(void) |
202 |
{ |
203 |
T0 &= T1; |
204 |
} |
205 |
|
206 |
void OPPROTO op_xorl_T0_T1(void) |
207 |
{ |
208 |
T0 ^= T1; |
209 |
} |
210 |
|
211 |
void OPPROTO op_orl_T0_T1(void) |
212 |
{ |
213 |
T0 |= T1; |
214 |
} |
215 |
|
216 |
void OPPROTO op_bicl_T0_T1(void) |
217 |
{ |
218 |
T0 &= ~T1; |
219 |
} |
220 |
|
221 |
void OPPROTO op_notl_T1(void) |
222 |
{ |
223 |
T1 = ~T1; |
224 |
} |
225 |
|
226 |
void OPPROTO op_logic_T0_cc(void) |
227 |
{ |
228 |
env->NZF = T0; |
229 |
} |
230 |
|
231 |
void OPPROTO op_logic_T1_cc(void) |
232 |
{ |
233 |
env->NZF = T1; |
234 |
} |
235 |
|
236 |
#define EIP (env->regs[15]) |
237 |
|
238 |
void OPPROTO op_test_eq(void) |
239 |
{ |
240 |
if (env->NZF == 0) |
241 |
JUMP_TB(PARAM1, 0, PARAM2);
|
242 |
FORCE_RET(); |
243 |
} |
244 |
|
245 |
void OPPROTO op_test_ne(void) |
246 |
{ |
247 |
if (env->NZF != 0) |
248 |
JUMP_TB(PARAM1, 0, PARAM2);
|
249 |
FORCE_RET(); |
250 |
} |
251 |
|
252 |
void OPPROTO op_test_cs(void) |
253 |
{ |
254 |
if (env->CF != 0) |
255 |
JUMP_TB(PARAM1, 0, PARAM2);
|
256 |
FORCE_RET(); |
257 |
} |
258 |
|
259 |
void OPPROTO op_test_cc(void) |
260 |
{ |
261 |
if (env->CF == 0) |
262 |
JUMP_TB(PARAM1, 0, PARAM2);
|
263 |
FORCE_RET(); |
264 |
} |
265 |
|
266 |
void OPPROTO op_test_mi(void) |
267 |
{ |
268 |
if ((env->NZF & 0x80000000) != 0) |
269 |
JUMP_TB(PARAM1, 0, PARAM2);
|
270 |
FORCE_RET(); |
271 |
} |
272 |
|
273 |
void OPPROTO op_test_pl(void) |
274 |
{ |
275 |
if ((env->NZF & 0x80000000) == 0) |
276 |
JUMP_TB(PARAM1, 0, PARAM2);
|
277 |
FORCE_RET(); |
278 |
} |
279 |
|
280 |
void OPPROTO op_test_vs(void) |
281 |
{ |
282 |
if ((env->VF & 0x80000000) != 0) |
283 |
JUMP_TB(PARAM1, 0, PARAM2);
|
284 |
FORCE_RET(); |
285 |
} |
286 |
|
287 |
void OPPROTO op_test_vc(void) |
288 |
{ |
289 |
if ((env->VF & 0x80000000) == 0) |
290 |
JUMP_TB(PARAM1, 0, PARAM2);
|
291 |
FORCE_RET(); |
292 |
} |
293 |
|
294 |
void OPPROTO op_test_hi(void) |
295 |
{ |
296 |
if (env->CF != 0 && env->NZF != 0) |
297 |
JUMP_TB(PARAM1, 0, PARAM2);
|
298 |
FORCE_RET(); |
299 |
} |
300 |
|
301 |
void OPPROTO op_test_ls(void) |
302 |
{ |
303 |
if (env->CF == 0 || env->NZF == 0) |
304 |
JUMP_TB(PARAM1, 0, PARAM2);
|
305 |
FORCE_RET(); |
306 |
} |
307 |
|
308 |
void OPPROTO op_test_ge(void) |
309 |
{ |
310 |
if (((env->VF ^ env->NZF) & 0x80000000) == 0) |
311 |
JUMP_TB(PARAM1, 0, PARAM2);
|
312 |
FORCE_RET(); |
313 |
} |
314 |
|
315 |
void OPPROTO op_test_lt(void) |
316 |
{ |
317 |
if (((env->VF ^ env->NZF) & 0x80000000) != 0) |
318 |
JUMP_TB(PARAM1, 0, PARAM2);
|
319 |
FORCE_RET(); |
320 |
} |
321 |
|
322 |
void OPPROTO op_test_gt(void) |
323 |
{ |
324 |
if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0) |
325 |
JUMP_TB(PARAM1, 0, PARAM2);
|
326 |
FORCE_RET(); |
327 |
} |
328 |
|
329 |
void OPPROTO op_test_le(void) |
330 |
{ |
331 |
if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0) |
332 |
JUMP_TB(PARAM1, 0, PARAM2);
|
333 |
FORCE_RET(); |
334 |
} |
335 |
|
336 |
void OPPROTO op_jmp(void) |
337 |
{ |
338 |
JUMP_TB(PARAM1, 1, PARAM2);
|
339 |
} |
340 |
|
341 |
void OPPROTO op_exit_tb(void) |
342 |
{ |
343 |
EXIT_TB(); |
344 |
} |
345 |
|
346 |
void OPPROTO op_movl_T0_psr(void) |
347 |
{ |
348 |
T0 = compute_cpsr(); |
349 |
} |
350 |
|
351 |
/* NOTE: N = 1 and Z = 1 cannot be stored currently */
|
352 |
void OPPROTO op_movl_psr_T0(void) |
353 |
{ |
354 |
unsigned int psr; |
355 |
psr = T0; |
356 |
env->CF = (psr >> 29) & 1; |
357 |
env->NZF = (psr & 0xc0000000) ^ 0x40000000; |
358 |
env->VF = (psr << 3) & 0x80000000; |
359 |
/* for user mode we do not update other state info */
|
360 |
} |
361 |
|
362 |
void OPPROTO op_mul_T0_T1(void) |
363 |
{ |
364 |
T0 = T0 * T1; |
365 |
} |
366 |
|
367 |
/* 64 bit unsigned mul */
|
368 |
void OPPROTO op_mull_T0_T1(void) |
369 |
{ |
370 |
uint64_t res; |
371 |
res = T0 * T1; |
372 |
T1 = res >> 32;
|
373 |
T0 = res; |
374 |
} |
375 |
|
376 |
/* 64 bit signed mul */
|
377 |
void OPPROTO op_imull_T0_T1(void) |
378 |
{ |
379 |
uint64_t res; |
380 |
res = (int32_t)T0 * (int32_t)T1; |
381 |
T1 = res >> 32;
|
382 |
T0 = res; |
383 |
} |
384 |
|
385 |
void OPPROTO op_addq_T0_T1(void) |
386 |
{ |
387 |
uint64_t res; |
388 |
res = ((uint64_t)T1 << 32) | T0;
|
389 |
res += ((uint64_t)(env->regs[PARAM2]) << 32) | (env->regs[PARAM1]);
|
390 |
T1 = res >> 32;
|
391 |
T0 = res; |
392 |
} |
393 |
|
394 |
void OPPROTO op_logicq_cc(void) |
395 |
{ |
396 |
env->NZF = (T1 & 0x80000000) | ((T0 | T1) != 0); |
397 |
} |
398 |
|
399 |
/* memory access */
|
400 |
|
401 |
void OPPROTO op_ldub_T0_T1(void) |
402 |
{ |
403 |
T0 = ldub((void *)T1);
|
404 |
} |
405 |
|
406 |
void OPPROTO op_ldsb_T0_T1(void) |
407 |
{ |
408 |
T0 = ldsb((void *)T1);
|
409 |
} |
410 |
|
411 |
void OPPROTO op_lduw_T0_T1(void) |
412 |
{ |
413 |
T0 = lduw((void *)T1);
|
414 |
} |
415 |
|
416 |
void OPPROTO op_ldsw_T0_T1(void) |
417 |
{ |
418 |
T0 = ldsw((void *)T1);
|
419 |
} |
420 |
|
421 |
void OPPROTO op_ldl_T0_T1(void) |
422 |
{ |
423 |
T0 = ldl((void *)T1);
|
424 |
} |
425 |
|
426 |
void OPPROTO op_stb_T0_T1(void) |
427 |
{ |
428 |
stb((void *)T1, T0);
|
429 |
} |
430 |
|
431 |
void OPPROTO op_stw_T0_T1(void) |
432 |
{ |
433 |
stw((void *)T1, T0);
|
434 |
} |
435 |
|
436 |
void OPPROTO op_stl_T0_T1(void) |
437 |
{ |
438 |
stl((void *)T1, T0);
|
439 |
} |
440 |
|
441 |
void OPPROTO op_swpb_T0_T1(void) |
442 |
{ |
443 |
int tmp;
|
444 |
|
445 |
cpu_lock(); |
446 |
tmp = ldub((void *)T1);
|
447 |
stb((void *)T1, T0);
|
448 |
T0 = tmp; |
449 |
cpu_unlock(); |
450 |
} |
451 |
|
452 |
void OPPROTO op_swpl_T0_T1(void) |
453 |
{ |
454 |
int tmp;
|
455 |
|
456 |
cpu_lock(); |
457 |
tmp = ldl((void *)T1);
|
458 |
stl((void *)T1, T0);
|
459 |
T0 = tmp; |
460 |
cpu_unlock(); |
461 |
} |
462 |
|
463 |
/* shifts */
|
464 |
|
465 |
/* T1 based */
|
466 |
void OPPROTO op_shll_T1_im(void) |
467 |
{ |
468 |
T1 = T1 << PARAM1; |
469 |
} |
470 |
|
471 |
void OPPROTO op_shrl_T1_im(void) |
472 |
{ |
473 |
T1 = (uint32_t)T1 >> PARAM1; |
474 |
} |
475 |
|
476 |
void OPPROTO op_sarl_T1_im(void) |
477 |
{ |
478 |
T1 = (int32_t)T1 >> PARAM1; |
479 |
} |
480 |
|
481 |
void OPPROTO op_rorl_T1_im(void) |
482 |
{ |
483 |
int shift;
|
484 |
shift = PARAM1; |
485 |
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
486 |
} |
487 |
|
488 |
/* T1 based, set C flag */
|
489 |
void OPPROTO op_shll_T1_im_cc(void) |
490 |
{ |
491 |
env->CF = (T1 >> (32 - PARAM1)) & 1; |
492 |
T1 = T1 << PARAM1; |
493 |
} |
494 |
|
495 |
void OPPROTO op_shrl_T1_im_cc(void) |
496 |
{ |
497 |
env->CF = (T1 >> (PARAM1 - 1)) & 1; |
498 |
T1 = (uint32_t)T1 >> PARAM1; |
499 |
} |
500 |
|
501 |
void OPPROTO op_sarl_T1_im_cc(void) |
502 |
{ |
503 |
env->CF = (T1 >> (PARAM1 - 1)) & 1; |
504 |
T1 = (int32_t)T1 >> PARAM1; |
505 |
} |
506 |
|
507 |
void OPPROTO op_rorl_T1_im_cc(void) |
508 |
{ |
509 |
int shift;
|
510 |
shift = PARAM1; |
511 |
env->CF = (T1 >> (shift - 1)) & 1; |
512 |
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
513 |
} |
514 |
|
515 |
/* T2 based */
|
516 |
void OPPROTO op_shll_T2_im(void) |
517 |
{ |
518 |
T2 = T2 << PARAM1; |
519 |
} |
520 |
|
521 |
void OPPROTO op_shrl_T2_im(void) |
522 |
{ |
523 |
T2 = (uint32_t)T2 >> PARAM1; |
524 |
} |
525 |
|
526 |
void OPPROTO op_sarl_T2_im(void) |
527 |
{ |
528 |
T2 = (int32_t)T2 >> PARAM1; |
529 |
} |
530 |
|
531 |
void OPPROTO op_rorl_T2_im(void) |
532 |
{ |
533 |
int shift;
|
534 |
shift = PARAM1; |
535 |
T2 = ((uint32_t)T2 >> shift) | (T2 << (32 - shift));
|
536 |
} |
537 |
|
538 |
/* T1 based, use T0 as shift count */
|
539 |
|
540 |
void OPPROTO op_shll_T1_T0(void) |
541 |
{ |
542 |
int shift;
|
543 |
shift = T0 & 0xff;
|
544 |
if (shift >= 32) |
545 |
T1 = 0;
|
546 |
else
|
547 |
T1 = T1 << shift; |
548 |
FORCE_RET(); |
549 |
} |
550 |
|
551 |
void OPPROTO op_shrl_T1_T0(void) |
552 |
{ |
553 |
int shift;
|
554 |
shift = T0 & 0xff;
|
555 |
if (shift >= 32) |
556 |
T1 = 0;
|
557 |
else
|
558 |
T1 = (uint32_t)T1 >> shift; |
559 |
FORCE_RET(); |
560 |
} |
561 |
|
562 |
void OPPROTO op_sarl_T1_T0(void) |
563 |
{ |
564 |
int shift;
|
565 |
shift = T0 & 0xff;
|
566 |
if (shift >= 32) |
567 |
shift = 31;
|
568 |
T1 = (int32_t)T1 >> shift; |
569 |
} |
570 |
|
571 |
void OPPROTO op_rorl_T1_T0(void) |
572 |
{ |
573 |
int shift;
|
574 |
shift = T0 & 0x1f;
|
575 |
if (shift) {
|
576 |
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
577 |
} |
578 |
FORCE_RET(); |
579 |
} |
580 |
|
581 |
/* T1 based, use T0 as shift count and compute CF */
|
582 |
|
583 |
void OPPROTO op_shll_T1_T0_cc(void) |
584 |
{ |
585 |
int shift;
|
586 |
shift = T0 & 0xff;
|
587 |
if (shift >= 32) { |
588 |
if (shift == 32) |
589 |
env->CF = T1 & 1;
|
590 |
else
|
591 |
env->CF = 0;
|
592 |
T1 = 0;
|
593 |
} else if (shift != 0) { |
594 |
env->CF = (T1 >> (32 - shift)) & 1; |
595 |
T1 = T1 << shift; |
596 |
} |
597 |
FORCE_RET(); |
598 |
} |
599 |
|
600 |
void OPPROTO op_shrl_T1_T0_cc(void) |
601 |
{ |
602 |
int shift;
|
603 |
shift = T0 & 0xff;
|
604 |
if (shift >= 32) { |
605 |
if (shift == 32) |
606 |
env->CF = (T1 >> 31) & 1; |
607 |
else
|
608 |
env->CF = 0;
|
609 |
T1 = 0;
|
610 |
} else if (shift != 0) { |
611 |
env->CF = (T1 >> (shift - 1)) & 1; |
612 |
T1 = (uint32_t)T1 >> shift; |
613 |
} |
614 |
FORCE_RET(); |
615 |
} |
616 |
|
617 |
void OPPROTO op_sarl_T1_T0_cc(void) |
618 |
{ |
619 |
int shift;
|
620 |
shift = T0 & 0xff;
|
621 |
if (shift >= 32) { |
622 |
env->CF = (T1 >> 31) & 1; |
623 |
T1 = (int32_t)T1 >> 31;
|
624 |
} else {
|
625 |
env->CF = (T1 >> (shift - 1)) & 1; |
626 |
T1 = (int32_t)T1 >> shift; |
627 |
} |
628 |
FORCE_RET(); |
629 |
} |
630 |
|
631 |
void OPPROTO op_rorl_T1_T0_cc(void) |
632 |
{ |
633 |
int shift1, shift;
|
634 |
shift1 = T0 & 0xff;
|
635 |
shift = shift1 & 0x1f;
|
636 |
if (shift == 0) { |
637 |
if (shift1 != 0) |
638 |
env->CF = (T1 >> 31) & 1; |
639 |
} else {
|
640 |
env->CF = (T1 >> (shift - 1)) & 1; |
641 |
T1 = ((uint32_t)T1 >> shift) | (T1 << (32 - shift));
|
642 |
} |
643 |
FORCE_RET(); |
644 |
} |
645 |
|
646 |
/* exceptions */
|
647 |
|
648 |
void OPPROTO op_swi(void) |
649 |
{ |
650 |
env->exception_index = EXCP_SWI; |
651 |
cpu_loop_exit(); |
652 |
} |
653 |
|
654 |
void OPPROTO op_undef_insn(void) |
655 |
{ |
656 |
env->exception_index = EXCP_UDEF; |
657 |
cpu_loop_exit(); |
658 |
} |
659 |
|
660 |
/* thread support */
|
661 |
|
662 |
spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED; |
663 |
|
664 |
void cpu_lock(void) |
665 |
{ |
666 |
spin_lock(&global_cpu_lock); |
667 |
} |
668 |
|
669 |
void cpu_unlock(void) |
670 |
{ |
671 |
spin_unlock(&global_cpu_lock); |
672 |
} |
673 |
|