Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/blackfin/mach-bf561/atomic.S
10817 views
1
/*
2
* Copyright 2007-2008 Analog Devices Inc.
3
* Philippe Gerum <[email protected]>
4
*
5
* Licensed under the GPL-2 or later.
6
*/
7
8
#include <linux/linkage.h>
9
#include <asm/blackfin.h>
10
#include <asm/cache.h>
11
#include <asm/asm-offsets.h>
12
#include <asm/rwlock.h>
13
#include <asm/cplb.h>
14
15
.text
16
17
.macro coreslot_loadaddr reg:req
18
\reg\().l = _corelock;
19
\reg\().h = _corelock;
20
.endm
21
22
.macro safe_testset addr:req, scratch:req
23
#if ANOMALY_05000477
24
cli \scratch;
25
testset (\addr);
26
sti \scratch;
27
#else
28
testset (\addr);
29
#endif
30
.endm
31
32
/*
33
* r0 = address of atomic data to flush and invalidate (32bit).
34
*
35
* Clear interrupts and return the old mask.
36
* We assume that no atomic data can span cachelines.
37
*
38
* Clobbers: r2:0, p0
39
*/
40
ENTRY(_get_core_lock)
41
r1 = -L1_CACHE_BYTES;
42
r1 = r0 & r1;
43
cli r0;
44
coreslot_loadaddr p0;
45
.Lretry_corelock:
46
safe_testset p0, r2;
47
if cc jump .Ldone_corelock;
48
SSYNC(r2);
49
jump .Lretry_corelock
50
.Ldone_corelock:
51
p0 = r1;
52
/* flush core internal write buffer before invalidate dcache */
53
CSYNC(r2);
54
flushinv[p0];
55
SSYNC(r2);
56
rts;
57
ENDPROC(_get_core_lock)
58
59
/*
60
* r0 = address of atomic data in uncacheable memory region (32bit).
61
*
62
* Clear interrupts and return the old mask.
63
*
64
* Clobbers: r0, p0
65
*/
66
ENTRY(_get_core_lock_noflush)
67
cli r0;
68
coreslot_loadaddr p0;
69
.Lretry_corelock_noflush:
70
safe_testset p0, r2;
71
if cc jump .Ldone_corelock_noflush;
72
SSYNC(r2);
73
jump .Lretry_corelock_noflush
74
.Ldone_corelock_noflush:
75
rts;
76
ENDPROC(_get_core_lock_noflush)
77
78
/*
79
* r0 = interrupt mask to restore.
80
* r1 = address of atomic data to flush and invalidate (32bit).
81
*
82
* Interrupts are masked on entry (see _get_core_lock).
83
* Clobbers: r2:0, p0
84
*/
85
ENTRY(_put_core_lock)
86
/* Write-through cache assumed, so no flush needed here. */
87
coreslot_loadaddr p0;
88
r1 = 0;
89
[p0] = r1;
90
SSYNC(r2);
91
sti r0;
92
rts;
93
ENDPROC(_put_core_lock)
94
95
#ifdef __ARCH_SYNC_CORE_DCACHE
96
97
ENTRY(___raw_smp_mark_barrier_asm)
98
[--sp] = rets;
99
[--sp] = ( r7:5 );
100
[--sp] = r0;
101
[--sp] = p1;
102
[--sp] = p0;
103
call _get_core_lock_noflush;
104
105
/*
106
* Calculate current core mask
107
*/
108
GET_CPUID(p1, r7);
109
r6 = 1;
110
r6 <<= r7;
111
112
/*
113
* Set bit of other cores in barrier mask. Don't change current core bit.
114
*/
115
p1.l = _barrier_mask;
116
p1.h = _barrier_mask;
117
r7 = [p1];
118
r5 = r7 & r6;
119
r7 = ~r6;
120
cc = r5 == 0;
121
if cc jump 1f;
122
r7 = r7 | r6;
123
1:
124
[p1] = r7;
125
SSYNC(r2);
126
127
call _put_core_lock;
128
p0 = [sp++];
129
p1 = [sp++];
130
r0 = [sp++];
131
( r7:5 ) = [sp++];
132
rets = [sp++];
133
rts;
134
ENDPROC(___raw_smp_mark_barrier_asm)
135
136
ENTRY(___raw_smp_check_barrier_asm)
137
[--sp] = rets;
138
[--sp] = ( r7:5 );
139
[--sp] = r0;
140
[--sp] = p1;
141
[--sp] = p0;
142
call _get_core_lock_noflush;
143
144
/*
145
* Calculate current core mask
146
*/
147
GET_CPUID(p1, r7);
148
r6 = 1;
149
r6 <<= r7;
150
151
/*
152
* Clear current core bit in barrier mask if it is set.
153
*/
154
p1.l = _barrier_mask;
155
p1.h = _barrier_mask;
156
r7 = [p1];
157
r5 = r7 & r6;
158
cc = r5 == 0;
159
if cc jump 1f;
160
r6 = ~r6;
161
r7 = r7 & r6;
162
[p1] = r7;
163
SSYNC(r2);
164
165
call _put_core_lock;
166
167
/*
168
* Invalidate the entire D-cache of current core.
169
*/
170
sp += -12;
171
call _resync_core_dcache
172
sp += 12;
173
jump 2f;
174
1:
175
call _put_core_lock;
176
2:
177
p0 = [sp++];
178
p1 = [sp++];
179
r0 = [sp++];
180
( r7:5 ) = [sp++];
181
rets = [sp++];
182
rts;
183
ENDPROC(___raw_smp_check_barrier_asm)
184
185
/*
186
* r0 = irqflags
187
* r1 = address of atomic data
188
*
189
* Clobbers: r2:0, p1:0
190
*/
191
_start_lock_coherent:
192
193
[--sp] = rets;
194
[--sp] = ( r7:6 );
195
r7 = r0;
196
p1 = r1;
197
198
/*
199
* Determine whether the atomic data was previously
200
* owned by another CPU (=r6).
201
*/
202
GET_CPUID(p0, r2);
203
r1 = 1;
204
r1 <<= r2;
205
r2 = ~r1;
206
207
r1 = [p1];
208
r1 >>= 28; /* CPU fingerprints are stored in the high nibble. */
209
r6 = r1 & r2;
210
r1 = [p1];
211
r1 <<= 4;
212
r1 >>= 4;
213
[p1] = r1;
214
215
/*
216
* Release the core lock now, but keep IRQs disabled while we are
217
* performing the remaining housekeeping chores for the current CPU.
218
*/
219
coreslot_loadaddr p0;
220
r1 = 0;
221
[p0] = r1;
222
223
/*
224
* If another CPU has owned the same atomic section before us,
225
* then our D-cached copy of the shared data protected by the
226
* current spin/write_lock may be obsolete.
227
*/
228
cc = r6 == 0;
229
if cc jump .Lcache_synced
230
231
/*
232
* Invalidate the entire D-cache of the current core.
233
*/
234
sp += -12;
235
call _resync_core_dcache
236
sp += 12;
237
238
.Lcache_synced:
239
SSYNC(r2);
240
sti r7;
241
( r7:6 ) = [sp++];
242
rets = [sp++];
243
rts
244
245
/*
246
* r0 = irqflags
247
* r1 = address of atomic data
248
*
249
* Clobbers: r2:0, p1:0
250
*/
251
_end_lock_coherent:
252
253
p1 = r1;
254
GET_CPUID(p0, r2);
255
r2 += 28;
256
r1 = 1;
257
r1 <<= r2;
258
r2 = [p1];
259
r2 = r1 | r2;
260
[p1] = r2;
261
r1 = p1;
262
jump _put_core_lock;
263
264
#endif /* __ARCH_SYNC_CORE_DCACHE */
265
266
/*
267
* r0 = &spinlock->lock
268
*
269
* Clobbers: r3:0, p1:0
270
*/
271
ENTRY(___raw_spin_is_locked_asm)
272
p1 = r0;
273
[--sp] = rets;
274
call _get_core_lock;
275
r3 = [p1];
276
cc = bittst( r3, 0 );
277
r3 = cc;
278
r1 = p1;
279
call _put_core_lock;
280
rets = [sp++];
281
r0 = r3;
282
rts;
283
ENDPROC(___raw_spin_is_locked_asm)
284
285
/*
286
* r0 = &spinlock->lock
287
*
288
* Clobbers: r3:0, p1:0
289
*/
290
ENTRY(___raw_spin_lock_asm)
291
p1 = r0;
292
[--sp] = rets;
293
.Lretry_spinlock:
294
call _get_core_lock;
295
r1 = p1;
296
r2 = [p1];
297
cc = bittst( r2, 0 );
298
if cc jump .Lbusy_spinlock
299
#ifdef __ARCH_SYNC_CORE_DCACHE
300
r3 = p1;
301
bitset ( r2, 0 ); /* Raise the lock bit. */
302
[p1] = r2;
303
call _start_lock_coherent
304
#else
305
r2 = 1;
306
[p1] = r2;
307
call _put_core_lock;
308
#endif
309
rets = [sp++];
310
rts;
311
312
.Lbusy_spinlock:
313
/* We don't touch the atomic area if busy, so that flush
314
will behave like nop in _put_core_lock. */
315
call _put_core_lock;
316
SSYNC(r2);
317
r0 = p1;
318
jump .Lretry_spinlock
319
ENDPROC(___raw_spin_lock_asm)
320
321
/*
322
* r0 = &spinlock->lock
323
*
324
* Clobbers: r3:0, p1:0
325
*/
326
ENTRY(___raw_spin_trylock_asm)
327
p1 = r0;
328
[--sp] = rets;
329
call _get_core_lock;
330
r1 = p1;
331
r3 = [p1];
332
cc = bittst( r3, 0 );
333
if cc jump .Lfailed_trylock
334
#ifdef __ARCH_SYNC_CORE_DCACHE
335
bitset ( r3, 0 ); /* Raise the lock bit. */
336
[p1] = r3;
337
call _start_lock_coherent
338
#else
339
r2 = 1;
340
[p1] = r2;
341
call _put_core_lock;
342
#endif
343
r0 = 1;
344
rets = [sp++];
345
rts;
346
.Lfailed_trylock:
347
call _put_core_lock;
348
r0 = 0;
349
rets = [sp++];
350
rts;
351
ENDPROC(___raw_spin_trylock_asm)
352
353
/*
354
* r0 = &spinlock->lock
355
*
356
* Clobbers: r2:0, p1:0
357
*/
358
ENTRY(___raw_spin_unlock_asm)
359
p1 = r0;
360
[--sp] = rets;
361
call _get_core_lock;
362
r2 = [p1];
363
bitclr ( r2, 0 );
364
[p1] = r2;
365
r1 = p1;
366
#ifdef __ARCH_SYNC_CORE_DCACHE
367
call _end_lock_coherent
368
#else
369
call _put_core_lock;
370
#endif
371
rets = [sp++];
372
rts;
373
ENDPROC(___raw_spin_unlock_asm)
374
375
/*
376
* r0 = &rwlock->lock
377
*
378
* Clobbers: r2:0, p1:0
379
*/
380
ENTRY(___raw_read_lock_asm)
381
p1 = r0;
382
[--sp] = rets;
383
call _get_core_lock;
384
.Lrdlock_try:
385
r1 = [p1];
386
r1 += -1;
387
[p1] = r1;
388
cc = r1 < 0;
389
if cc jump .Lrdlock_failed
390
r1 = p1;
391
#ifdef __ARCH_SYNC_CORE_DCACHE
392
call _start_lock_coherent
393
#else
394
call _put_core_lock;
395
#endif
396
rets = [sp++];
397
rts;
398
399
.Lrdlock_failed:
400
r1 += 1;
401
[p1] = r1;
402
.Lrdlock_wait:
403
r1 = p1;
404
call _put_core_lock;
405
SSYNC(r2);
406
r0 = p1;
407
call _get_core_lock;
408
r1 = [p1];
409
cc = r1 < 2;
410
if cc jump .Lrdlock_wait;
411
jump .Lrdlock_try
412
ENDPROC(___raw_read_lock_asm)
413
414
/*
415
* r0 = &rwlock->lock
416
*
417
* Clobbers: r3:0, p1:0
418
*/
419
ENTRY(___raw_read_trylock_asm)
420
p1 = r0;
421
[--sp] = rets;
422
call _get_core_lock;
423
r1 = [p1];
424
cc = r1 <= 0;
425
if cc jump .Lfailed_tryrdlock;
426
r1 += -1;
427
[p1] = r1;
428
r1 = p1;
429
#ifdef __ARCH_SYNC_CORE_DCACHE
430
call _start_lock_coherent
431
#else
432
call _put_core_lock;
433
#endif
434
rets = [sp++];
435
r0 = 1;
436
rts;
437
.Lfailed_tryrdlock:
438
r1 = p1;
439
call _put_core_lock;
440
rets = [sp++];
441
r0 = 0;
442
rts;
443
ENDPROC(___raw_read_trylock_asm)
444
445
/*
446
* r0 = &rwlock->lock
447
*
448
* Note: Processing controlled by a reader lock should not have
449
* any side-effect on cache issues with the other core, so we
450
* just release the core lock and exit (no _end_lock_coherent).
451
*
452
* Clobbers: r3:0, p1:0
453
*/
454
ENTRY(___raw_read_unlock_asm)
455
p1 = r0;
456
[--sp] = rets;
457
call _get_core_lock;
458
r1 = [p1];
459
r1 += 1;
460
[p1] = r1;
461
r1 = p1;
462
call _put_core_lock;
463
rets = [sp++];
464
rts;
465
ENDPROC(___raw_read_unlock_asm)
466
467
/*
468
* r0 = &rwlock->lock
469
*
470
* Clobbers: r3:0, p1:0
471
*/
472
ENTRY(___raw_write_lock_asm)
473
p1 = r0;
474
r3.l = lo(RW_LOCK_BIAS);
475
r3.h = hi(RW_LOCK_BIAS);
476
[--sp] = rets;
477
call _get_core_lock;
478
.Lwrlock_try:
479
r1 = [p1];
480
r1 = r1 - r3;
481
#ifdef __ARCH_SYNC_CORE_DCACHE
482
r2 = r1;
483
r2 <<= 4;
484
r2 >>= 4;
485
cc = r2 == 0;
486
#else
487
cc = r1 == 0;
488
#endif
489
if !cc jump .Lwrlock_wait
490
[p1] = r1;
491
r1 = p1;
492
#ifdef __ARCH_SYNC_CORE_DCACHE
493
call _start_lock_coherent
494
#else
495
call _put_core_lock;
496
#endif
497
rets = [sp++];
498
rts;
499
500
.Lwrlock_wait:
501
r1 = p1;
502
call _put_core_lock;
503
SSYNC(r2);
504
r0 = p1;
505
call _get_core_lock;
506
r1 = [p1];
507
#ifdef __ARCH_SYNC_CORE_DCACHE
508
r1 <<= 4;
509
r1 >>= 4;
510
#endif
511
cc = r1 == r3;
512
if !cc jump .Lwrlock_wait;
513
jump .Lwrlock_try
514
ENDPROC(___raw_write_lock_asm)
515
516
/*
517
* r0 = &rwlock->lock
518
*
519
* Clobbers: r3:0, p1:0
520
*/
521
ENTRY(___raw_write_trylock_asm)
522
p1 = r0;
523
[--sp] = rets;
524
call _get_core_lock;
525
r1 = [p1];
526
r2.l = lo(RW_LOCK_BIAS);
527
r2.h = hi(RW_LOCK_BIAS);
528
cc = r1 == r2;
529
if !cc jump .Lfailed_trywrlock;
530
#ifdef __ARCH_SYNC_CORE_DCACHE
531
r1 >>= 28;
532
r1 <<= 28;
533
#else
534
r1 = 0;
535
#endif
536
[p1] = r1;
537
r1 = p1;
538
#ifdef __ARCH_SYNC_CORE_DCACHE
539
call _start_lock_coherent
540
#else
541
call _put_core_lock;
542
#endif
543
rets = [sp++];
544
r0 = 1;
545
rts;
546
547
.Lfailed_trywrlock:
548
r1 = p1;
549
call _put_core_lock;
550
rets = [sp++];
551
r0 = 0;
552
rts;
553
ENDPROC(___raw_write_trylock_asm)
554
555
/*
556
* r0 = &rwlock->lock
557
*
558
* Clobbers: r3:0, p1:0
559
*/
560
ENTRY(___raw_write_unlock_asm)
561
p1 = r0;
562
r3.l = lo(RW_LOCK_BIAS);
563
r3.h = hi(RW_LOCK_BIAS);
564
[--sp] = rets;
565
call _get_core_lock;
566
r1 = [p1];
567
r1 = r1 + r3;
568
[p1] = r1;
569
r1 = p1;
570
#ifdef __ARCH_SYNC_CORE_DCACHE
571
call _end_lock_coherent
572
#else
573
call _put_core_lock;
574
#endif
575
rets = [sp++];
576
rts;
577
ENDPROC(___raw_write_unlock_asm)
578
579
/*
580
* r0 = ptr
581
* r1 = value
582
*
583
* Add a signed value to a 32bit word and return the new value atomically.
584
* Clobbers: r3:0, p1:0
585
*/
586
ENTRY(___raw_atomic_update_asm)
587
p1 = r0;
588
r3 = r1;
589
[--sp] = rets;
590
call _get_core_lock;
591
r2 = [p1];
592
r3 = r3 + r2;
593
[p1] = r3;
594
r1 = p1;
595
call _put_core_lock;
596
r0 = r3;
597
rets = [sp++];
598
rts;
599
ENDPROC(___raw_atomic_update_asm)
600
601
/*
602
* r0 = ptr
603
* r1 = mask
604
*
605
* Clear the mask bits from a 32bit word and return the old 32bit value
606
* atomically.
607
* Clobbers: r3:0, p1:0
608
*/
609
ENTRY(___raw_atomic_clear_asm)
610
p1 = r0;
611
r3 = ~r1;
612
[--sp] = rets;
613
call _get_core_lock;
614
r2 = [p1];
615
r3 = r2 & r3;
616
[p1] = r3;
617
r3 = r2;
618
r1 = p1;
619
call _put_core_lock;
620
r0 = r3;
621
rets = [sp++];
622
rts;
623
ENDPROC(___raw_atomic_clear_asm)
624
625
/*
626
* r0 = ptr
627
* r1 = mask
628
*
629
* Set the mask bits into a 32bit word and return the old 32bit value
630
* atomically.
631
* Clobbers: r3:0, p1:0
632
*/
633
ENTRY(___raw_atomic_set_asm)
634
p1 = r0;
635
r3 = r1;
636
[--sp] = rets;
637
call _get_core_lock;
638
r2 = [p1];
639
r3 = r2 | r3;
640
[p1] = r3;
641
r3 = r2;
642
r1 = p1;
643
call _put_core_lock;
644
r0 = r3;
645
rets = [sp++];
646
rts;
647
ENDPROC(___raw_atomic_set_asm)
648
649
/*
650
* r0 = ptr
651
* r1 = mask
652
*
653
* XOR the mask bits with a 32bit word and return the old 32bit value
654
* atomically.
655
* Clobbers: r3:0, p1:0
656
*/
657
ENTRY(___raw_atomic_xor_asm)
658
p1 = r0;
659
r3 = r1;
660
[--sp] = rets;
661
call _get_core_lock;
662
r2 = [p1];
663
r3 = r2 ^ r3;
664
[p1] = r3;
665
r3 = r2;
666
r1 = p1;
667
call _put_core_lock;
668
r0 = r3;
669
rets = [sp++];
670
rts;
671
ENDPROC(___raw_atomic_xor_asm)
672
673
/*
674
* r0 = ptr
675
* r1 = mask
676
*
677
* Perform a logical AND between the mask bits and a 32bit word, and
678
* return the masked value. We need this on this architecture in
679
* order to invalidate the local cache before testing.
680
*
681
* Clobbers: r3:0, p1:0
682
*/
683
ENTRY(___raw_atomic_test_asm)
684
p1 = r0;
685
r3 = r1;
686
r1 = -L1_CACHE_BYTES;
687
r1 = r0 & r1;
688
p0 = r1;
689
/* flush core internal write buffer before invalidate dcache */
690
CSYNC(r2);
691
flushinv[p0];
692
SSYNC(r2);
693
r0 = [p1];
694
r0 = r0 & r3;
695
rts;
696
ENDPROC(___raw_atomic_test_asm)
697
698
/*
699
* r0 = ptr
700
* r1 = value
701
*
702
* Swap *ptr with value and return the old 32bit value atomically.
703
* Clobbers: r3:0, p1:0
704
*/
705
#define __do_xchg(src, dst) \
706
p1 = r0; \
707
r3 = r1; \
708
[--sp] = rets; \
709
call _get_core_lock; \
710
r2 = src; \
711
dst = r3; \
712
r3 = r2; \
713
r1 = p1; \
714
call _put_core_lock; \
715
r0 = r3; \
716
rets = [sp++]; \
717
rts;
718
719
ENTRY(___raw_xchg_1_asm)
720
__do_xchg(b[p1] (z), b[p1])
721
ENDPROC(___raw_xchg_1_asm)
722
723
ENTRY(___raw_xchg_2_asm)
724
__do_xchg(w[p1] (z), w[p1])
725
ENDPROC(___raw_xchg_2_asm)
726
727
ENTRY(___raw_xchg_4_asm)
728
__do_xchg([p1], [p1])
729
ENDPROC(___raw_xchg_4_asm)
730
731
/*
732
* r0 = ptr
733
* r1 = new
734
* r2 = old
735
*
736
* Swap *ptr with new if *ptr == old and return the previous *ptr
737
* value atomically.
738
*
739
* Clobbers: r3:0, p1:0
740
*/
741
#define __do_cmpxchg(src, dst) \
742
[--sp] = rets; \
743
[--sp] = r4; \
744
p1 = r0; \
745
r3 = r1; \
746
r4 = r2; \
747
call _get_core_lock; \
748
r2 = src; \
749
cc = r2 == r4; \
750
if !cc jump 1f; \
751
dst = r3; \
752
1: r3 = r2; \
753
r1 = p1; \
754
call _put_core_lock; \
755
r0 = r3; \
756
r4 = [sp++]; \
757
rets = [sp++]; \
758
rts;
759
760
ENTRY(___raw_cmpxchg_1_asm)
761
__do_cmpxchg(b[p1] (z), b[p1])
762
ENDPROC(___raw_cmpxchg_1_asm)
763
764
ENTRY(___raw_cmpxchg_2_asm)
765
__do_cmpxchg(w[p1] (z), w[p1])
766
ENDPROC(___raw_cmpxchg_2_asm)
767
768
ENTRY(___raw_cmpxchg_4_asm)
769
__do_cmpxchg([p1], [p1])
770
ENDPROC(___raw_cmpxchg_4_asm)
771
772
/*
773
* r0 = ptr
774
* r1 = bitnr
775
*
776
* Set a bit in a 32bit word and return the old 32bit value atomically.
777
* Clobbers: r3:0, p1:0
778
*/
779
ENTRY(___raw_bit_set_asm)
780
r2 = r1;
781
r1 = 1;
782
r1 <<= r2;
783
jump ___raw_atomic_set_asm
784
ENDPROC(___raw_bit_set_asm)
785
786
/*
787
* r0 = ptr
788
* r1 = bitnr
789
*
790
* Clear a bit in a 32bit word and return the old 32bit value atomically.
791
* Clobbers: r3:0, p1:0
792
*/
793
ENTRY(___raw_bit_clear_asm)
794
r2 = r1;
795
r1 = 1;
796
r1 <<= r2;
797
jump ___raw_atomic_clear_asm
798
ENDPROC(___raw_bit_clear_asm)
799
800
/*
801
* r0 = ptr
802
* r1 = bitnr
803
*
804
* Toggle a bit in a 32bit word and return the old 32bit value atomically.
805
* Clobbers: r3:0, p1:0
806
*/
807
ENTRY(___raw_bit_toggle_asm)
808
r2 = r1;
809
r1 = 1;
810
r1 <<= r2;
811
jump ___raw_atomic_xor_asm
812
ENDPROC(___raw_bit_toggle_asm)
813
814
/*
815
* r0 = ptr
816
* r1 = bitnr
817
*
818
* Test-and-set a bit in a 32bit word and return the old bit value atomically.
819
* Clobbers: r3:0, p1:0
820
*/
821
ENTRY(___raw_bit_test_set_asm)
822
[--sp] = rets;
823
[--sp] = r1;
824
call ___raw_bit_set_asm
825
r1 = [sp++];
826
r2 = 1;
827
r2 <<= r1;
828
r0 = r0 & r2;
829
cc = r0 == 0;
830
if cc jump 1f
831
r0 = 1;
832
1:
833
rets = [sp++];
834
rts;
835
ENDPROC(___raw_bit_test_set_asm)
836
837
/*
838
* r0 = ptr
839
* r1 = bitnr
840
*
841
* Test-and-clear a bit in a 32bit word and return the old bit value atomically.
842
* Clobbers: r3:0, p1:0
843
*/
844
ENTRY(___raw_bit_test_clear_asm)
845
[--sp] = rets;
846
[--sp] = r1;
847
call ___raw_bit_clear_asm
848
r1 = [sp++];
849
r2 = 1;
850
r2 <<= r1;
851
r0 = r0 & r2;
852
cc = r0 == 0;
853
if cc jump 1f
854
r0 = 1;
855
1:
856
rets = [sp++];
857
rts;
858
ENDPROC(___raw_bit_test_clear_asm)
859
860
/*
861
* r0 = ptr
862
* r1 = bitnr
863
*
864
* Test-and-toggle a bit in a 32bit word,
865
* and return the old bit value atomically.
866
* Clobbers: r3:0, p1:0
867
*/
868
ENTRY(___raw_bit_test_toggle_asm)
869
[--sp] = rets;
870
[--sp] = r1;
871
call ___raw_bit_toggle_asm
872
r1 = [sp++];
873
r2 = 1;
874
r2 <<= r1;
875
r0 = r0 & r2;
876
cc = r0 == 0;
877
if cc jump 1f
878
r0 = 1;
879
1:
880
rets = [sp++];
881
rts;
882
ENDPROC(___raw_bit_test_toggle_asm)
883
884
/*
885
* r0 = ptr
886
* r1 = bitnr
887
*
888
* Test a bit in a 32bit word and return its value.
889
* We need this on this architecture in order to invalidate
890
* the local cache before testing.
891
*
892
* Clobbers: r3:0, p1:0
893
*/
894
ENTRY(___raw_bit_test_asm)
895
r2 = r1;
896
r1 = 1;
897
r1 <<= r2;
898
jump ___raw_atomic_test_asm
899
ENDPROC(___raw_bit_test_asm)
900
901
/*
902
* r0 = ptr
903
*
904
* Fetch and return an uncached 32bit value.
905
*
906
* Clobbers: r2:0, p1:0
907
*/
908
ENTRY(___raw_uncached_fetch_asm)
909
p1 = r0;
910
r1 = -L1_CACHE_BYTES;
911
r1 = r0 & r1;
912
p0 = r1;
913
/* flush core internal write buffer before invalidate dcache */
914
CSYNC(r2);
915
flushinv[p0];
916
SSYNC(r2);
917
r0 = [p1];
918
rts;
919
ENDPROC(___raw_uncached_fetch_asm)
920
921