1 /* SPDX-License-Identifier: GPL-2.0 */ !! 1 /* bitops.S: Low level assembler bit operations. 2 /* bitops.S: Sparc64 atomic bit operations. << 3 * 2 * 4 * Copyright (C) 2000, 2007 David S. Miller (d !! 3 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) 5 */ 4 */ 6 5 7 #include <linux/export.h> !! 6 #include <linux/config.h> 8 #include <linux/linkage.h> !! 7 #include <asm/cprefix.h> 9 #include <asm/asi.h> !! 8 #include <asm/ptrace.h> 10 #include <asm/backoff.h> !! 9 #include <asm/psr.h> 11 10 12 .text 11 .text >> 12 .align 4 13 13 14 ENTRY(test_and_set_bit) /* %o0=nr, %o1=addr */ !! 14 .globl __bitops_begin 15 BACKOFF_SETUP(%o3) !! 15 __bitops_begin: 16 srlx %o0, 6, %g1 !! 16 17 mov 1, %o2 !! 17 /* Take bits in %g2 and set them in word at %g1, 18 sllx %g1, 3, %g3 !! 18 * return whether bits were set in original value 19 and %o0, 63, %g2 !! 19 * in %g2. %g4 holds value to restore into %o7 20 sllx %o2, %g2, %o2 !! 20 * in delay slot of jmpl return, %g3 + %g5 + %g7 can be 21 add %o1, %g3, %o1 !! 21 * used as temporaries and thus is considered clobbered 22 1: ldx [%o1], %g7 !! 22 * by all callers. 23 or %g7, %o2, %g1 !! 23 */ 24 casx [%o1], %g7, %g1 !! 24 .globl ___set_bit 25 cmp %g7, %g1 !! 25 ___set_bit: 26 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) !! 26 rd %psr, %g3 27 and %g7, %o2, %g2 !! 27 nop; nop; nop; 28 clr %o0 !! 28 or %g3, PSR_PIL, %g5 29 movrne %g2, 1, %o0 !! 29 wr %g5, 0x0, %psr 30 retl !! 30 nop; nop; nop 31 nop !! 31 #ifdef CONFIG_SMP 32 2: BACKOFF_SPIN(%o3, %o4, 1b) !! 32 set C_LABEL(bitops_spinlock), %g5 33 ENDPROC(test_and_set_bit) !! 33 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. 34 EXPORT_SYMBOL(test_and_set_bit) !! 34 orcc %g7, 0x0, %g0 ! Did we get it? 35 !! 35 bne 2b ! Nope... 36 ENTRY(test_and_clear_bit) /* %o0=nr, %o1=addr !! 36 #endif 37 BACKOFF_SETUP(%o3) !! 37 ld [%g1], %g7 38 srlx %o0, 6, %g1 !! 38 or %g7, %g2, %g5 39 mov 1, %o2 !! 39 and %g7, %g2, %g2 40 sllx %g1, 3, %g3 !! 40 #ifdef CONFIG_SMP 41 and %o0, 63, %g2 !! 41 st %g5, [%g1] 42 sllx %o2, %g2, %o2 !! 42 set C_LABEL(bitops_spinlock), %g5 43 add %o1, %g3, %o1 !! 43 stb %g0, [%g5] 44 1: ldx [%o1], %g7 !! 44 #else 45 andn %g7, %o2, %g1 !! 45 st %g5, [%g1] 46 casx [%o1], %g7, %g1 !! 46 #endif 47 cmp %g7, %g1 !! 47 wr %g3, 0x0, %psr 48 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) !! 48 nop; nop; nop 49 and %g7, %o2, %g2 !! 49 jmpl %o7, %g0 50 clr %o0 !! 50 mov %g4, %o7 51 movrne %g2, 1, %o0 !! 51 52 retl !! 52 /* Same as above, but clears the bits from %g2 instead. */ 53 nop !! 53 .globl ___clear_bit 54 2: BACKOFF_SPIN(%o3, %o4, 1b) !! 54 ___clear_bit: 55 ENDPROC(test_and_clear_bit) !! 55 rd %psr, %g3 56 EXPORT_SYMBOL(test_and_clear_bit) !! 56 nop; nop; nop 57 !! 57 or %g3, PSR_PIL, %g5 58 ENTRY(test_and_change_bit) /* %o0=nr, %o1=addr !! 58 wr %g5, 0x0, %psr 59 BACKOFF_SETUP(%o3) !! 59 nop; nop; nop 60 srlx %o0, 6, %g1 !! 60 #ifdef CONFIG_SMP 61 mov 1, %o2 !! 61 set C_LABEL(bitops_spinlock), %g5 62 sllx %g1, 3, %g3 !! 62 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. 63 and %o0, 63, %g2 !! 63 orcc %g7, 0x0, %g0 ! Did we get it? 64 sllx %o2, %g2, %o2 !! 64 bne 2b ! Nope... 65 add %o1, %g3, %o1 !! 65 #endif 66 1: ldx [%o1], %g7 !! 66 ld [%g1], %g7 67 xor %g7, %o2, %g1 !! 67 andn %g7, %g2, %g5 68 casx [%o1], %g7, %g1 !! 68 and %g7, %g2, %g2 69 cmp %g7, %g1 !! 69 #ifdef CONFIG_SMP 70 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) !! 70 st %g5, [%g1] 71 and %g7, %o2, %g2 !! 71 set C_LABEL(bitops_spinlock), %g5 72 clr %o0 !! 72 stb %g0, [%g5] 73 movrne %g2, 1, %o0 !! 73 #else 74 retl !! 74 st %g5, [%g1] 75 nop !! 75 #endif 76 2: BACKOFF_SPIN(%o3, %o4, 1b) !! 76 wr %g3, 0x0, %psr 77 ENDPROC(test_and_change_bit) !! 77 nop; nop; nop 78 EXPORT_SYMBOL(test_and_change_bit) !! 78 jmpl %o7, %g0 79 !! 79 mov %g4, %o7 80 ENTRY(set_bit) /* %o0=nr, %o1=addr */ !! 80 81 BACKOFF_SETUP(%o3) !! 81 /* Same thing again, but this time toggles the bits from %g2. */ 82 srlx %o0, 6, %g1 !! 82 .globl ___change_bit 83 mov 1, %o2 !! 83 ___change_bit: 84 sllx %g1, 3, %g3 !! 84 rd %psr, %g3 85 and %o0, 63, %g2 !! 85 nop; nop; nop 86 sllx %o2, %g2, %o2 !! 86 or %g3, PSR_PIL, %g5 87 add %o1, %g3, %o1 !! 87 wr %g5, 0x0, %psr 88 1: ldx [%o1], %g7 !! 88 nop; nop; nop 89 or %g7, %o2, %g1 !! 89 #ifdef CONFIG_SMP 90 casx [%o1], %g7, %g1 !! 90 set C_LABEL(bitops_spinlock), %g5 91 cmp %g7, %g1 !! 91 2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. 92 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) !! 92 orcc %g7, 0x0, %g0 ! Did we get it? 93 nop !! 93 bne 2b ! Nope... 94 retl !! 94 #endif 95 nop !! 95 ld [%g1], %g7 96 2: BACKOFF_SPIN(%o3, %o4, 1b) !! 96 xor %g7, %g2, %g5 97 ENDPROC(set_bit) !! 97 and %g7, %g2, %g2 98 EXPORT_SYMBOL(set_bit) !! 98 #ifdef CONFIG_SMP 99 !! 99 st %g5, [%g1] 100 ENTRY(clear_bit) /* %o0=nr, %o1=addr */ !! 100 set C_LABEL(bitops_spinlock), %g5 101 BACKOFF_SETUP(%o3) !! 101 stb %g0, [%g5] 102 srlx %o0, 6, %g1 !! 102 #else 103 mov 1, %o2 !! 103 st %g5, [%g1] 104 sllx %g1, 3, %g3 !! 104 #endif 105 and %o0, 63, %g2 !! 105 wr %g3, 0x0, %psr 106 sllx %o2, %g2, %o2 !! 106 nop; nop; nop 107 add %o1, %g3, %o1 !! 107 jmpl %o7, %g0 108 1: ldx [%o1], %g7 !! 108 mov %g4, %o7 109 andn %g7, %o2, %g1 !! 109 110 casx [%o1], %g7, %g1 !! 110 .globl __bitops_end 111 cmp %g7, %g1 !! 111 __bitops_end: 112 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) << 113 nop << 114 retl << 115 nop << 116 2: BACKOFF_SPIN(%o3, %o4, 1b) << 117 ENDPROC(clear_bit) << 118 EXPORT_SYMBOL(clear_bit) << 119 << 120 ENTRY(change_bit) /* %o0=nr, %o1=addr */ << 121 BACKOFF_SETUP(%o3) << 122 srlx %o0, 6, %g1 << 123 mov 1, %o2 << 124 sllx %g1, 3, %g3 << 125 and %o0, 63, %g2 << 126 sllx %o2, %g2, %o2 << 127 add %o1, %g3, %o1 << 128 1: ldx [%o1], %g7 << 129 xor %g7, %o2, %g1 << 130 casx [%o1], %g7, %g1 << 131 cmp %g7, %g1 << 132 bne,pn %xcc, BACKOFF_LABEL(2f, 1b) << 133 nop << 134 retl << 135 nop << 136 2: BACKOFF_SPIN(%o3, %o4, 1b) << 137 ENDPROC(change_bit) << 138 EXPORT_SYMBOL(change_bit) <<
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.