nsprpub/pr/src/md/unix/os_SunOS_ultrasparc.s

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

michael@0 1 ! -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 !
michael@0 3 ! This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 ! License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 ! file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 6
michael@0 7 !
michael@0 8 ! atomic increment, decrement and swap routines for V8+ sparc (ultrasparc)
michael@0 9 ! using CAS (compare-and-swap) atomic instructions
michael@0 10 !
michael@0 11 ! this MUST be compiled with an ultrasparc-aware assembler
michael@0 12 !
michael@0 13 ! standard asm linkage macros; this module must be compiled
michael@0 14 ! with the -P option (use C preprocessor)
michael@0 15
michael@0 16 #include <sys/asm_linkage.h>
michael@0 17
michael@0 18 ! ======================================================================
michael@0 19 !
michael@0 20 ! Perform the sequence a = a + 1 atomically with respect to other
michael@0 21 ! fetch-and-adds to location a in a wait-free fashion.
michael@0 22 !
michael@0 23 ! usage : val = PR_AtomicIncrement(address)
michael@0 24 ! return: current value (you'd think this would be old val)
michael@0 25 !
michael@0 26 ! -----------------------
michael@0 27 ! Note on REGISTER USAGE:
michael@0 28 ! as this is a LEAF procedure, a new stack frame is not created;
michael@0 29 ! we use the caller's stack frame so what would normally be %i (input)
michael@0 30 ! registers are actually %o (output registers). Also, we must not
michael@0 31 ! overwrite the contents of %l (local) registers as they are not
michael@0 32 ! assumed to be volatile during calls.
michael@0 33 !
michael@0 34 ! So, the registers used are:
michael@0 35 ! %o0 [input] - the address of the value to increment
michael@0 36 ! %o1 [local] - work register
michael@0 37 ! %o2 [local] - work register
michael@0 38 ! %o3 [local] - work register
michael@0 39 ! -----------------------
michael@0 40
michael@0 41 ENTRY(PR_AtomicIncrement) ! standard assembler/ELF prologue
michael@0 42
michael@0 43 retryAI:
michael@0 44 ld [%o0], %o2 ! set o2 to the current value
michael@0 45 add %o2, 0x1, %o3 ! calc the new value
michael@0 46 mov %o3, %o1 ! save the return value
michael@0 47 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
michael@0 48 cmp %o2, %o3 ! see if we set the value
michael@0 49 bne retryAI ! if not, try again
michael@0 50 nop ! empty out the branch pipeline
michael@0 51 retl ! return back to the caller
michael@0 52 mov %o1, %o0 ! set the return code to the new value
michael@0 53
michael@0 54 SET_SIZE(PR_AtomicIncrement) ! standard assembler/ELF epilogue
michael@0 55
michael@0 56 !
michael@0 57 ! end
michael@0 58 !
michael@0 59 ! ======================================================================
michael@0 60 !
michael@0 61
michael@0 62 ! ======================================================================
michael@0 63 !
michael@0 64 ! Perform the sequence a = a - 1 atomically with respect to other
michael@0 65 ! fetch-and-decs to location a in a wait-free fashion.
michael@0 66 !
michael@0 67 ! usage : val = PR_AtomicDecrement(address)
michael@0 68 ! return: current value (you'd think this would be old val)
michael@0 69 !
michael@0 70 ! -----------------------
michael@0 71 ! Note on REGISTER USAGE:
michael@0 72 ! as this is a LEAF procedure, a new stack frame is not created;
michael@0 73 ! we use the caller's stack frame so what would normally be %i (input)
michael@0 74 ! registers are actually %o (output registers). Also, we must not
michael@0 75 ! overwrite the contents of %l (local) registers as they are not
michael@0 76 ! assumed to be volatile during calls.
michael@0 77 !
michael@0 78 ! So, the registers used are:
michael@0 79 ! %o0 [input] - the address of the value to increment
michael@0 80 ! %o1 [local] - work register
michael@0 81 ! %o2 [local] - work register
michael@0 82 ! %o3 [local] - work register
michael@0 83 ! -----------------------
michael@0 84
michael@0 85 ENTRY(PR_AtomicDecrement) ! standard assembler/ELF prologue
michael@0 86
michael@0 87 retryAD:
michael@0 88 ld [%o0], %o2 ! set o2 to the current value
michael@0 89 sub %o2, 0x1, %o3 ! calc the new value
michael@0 90 mov %o3, %o1 ! save the return value
michael@0 91 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
michael@0 92 cmp %o2, %o3 ! see if we set the value
michael@0 93 bne retryAD ! if not, try again
michael@0 94 nop ! empty out the branch pipeline
michael@0 95 retl ! return back to the caller
michael@0 96 mov %o1, %o0 ! set the return code to the new value
michael@0 97
michael@0 98 SET_SIZE(PR_AtomicDecrement) ! standard assembler/ELF epilogue
michael@0 99
michael@0 100 !
michael@0 101 ! end
michael@0 102 !
michael@0 103 ! ======================================================================
michael@0 104 !
michael@0 105
michael@0 106 ! ======================================================================
michael@0 107 !
michael@0 108 ! Perform the sequence a = b atomically with respect to other
michael@0 109 ! fetch-and-stores to location a in a wait-free fashion.
michael@0 110 !
michael@0 111 ! usage : old_val = PR_AtomicSet(address, newval)
michael@0 112 !
michael@0 113 ! -----------------------
michael@0 114 ! Note on REGISTER USAGE:
michael@0 115 ! as this is a LEAF procedure, a new stack frame is not created;
michael@0 116 ! we use the caller's stack frame so what would normally be %i (input)
michael@0 117 ! registers are actually %o (output registers). Also, we must not
michael@0 118 ! overwrite the contents of %l (local) registers as they are not
michael@0 119 ! assumed to be volatile during calls.
michael@0 120 !
michael@0 121 ! So, the registers used are:
michael@0 122 ! %o0 [input] - the address of the value to increment
michael@0 123 ! %o1 [input] - the new value to set for [%o0]
michael@0 124 ! %o2 [local] - work register
michael@0 125 ! %o3 [local] - work register
michael@0 126 ! -----------------------
michael@0 127
michael@0 128 ENTRY(PR_AtomicSet) ! standard assembler/ELF prologue
michael@0 129
michael@0 130 retryAS:
michael@0 131 ld [%o0], %o2 ! set o2 to the current value
michael@0 132 mov %o1, %o3 ! set up the new value
michael@0 133 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
michael@0 134 cmp %o2, %o3 ! see if we set the value
michael@0 135 bne retryAS ! if not, try again
michael@0 136 nop ! empty out the branch pipeline
michael@0 137 retl ! return back to the caller
michael@0 138 mov %o3, %o0 ! set the return code to the prev value
michael@0 139
michael@0 140 SET_SIZE(PR_AtomicSet) ! standard assembler/ELF epilogue
michael@0 141
michael@0 142 !
michael@0 143 ! end
michael@0 144 !
michael@0 145 ! ======================================================================
michael@0 146 !
michael@0 147
michael@0 148 ! ======================================================================
michael@0 149 !
michael@0 150 ! Perform the sequence a = a + b atomically with respect to other
michael@0 151 ! fetch-and-adds to location a in a wait-free fashion.
michael@0 152 !
michael@0 153 ! usage : newval = PR_AtomicAdd(address, val)
michael@0 154 ! return: the value after addition
michael@0 155 !
michael@0 156 ENTRY(PR_AtomicAdd) ! standard assembler/ELF prologue
michael@0 157
michael@0 158 retryAA:
michael@0 159 ld [%o0], %o2 ! set o2 to the current value
michael@0 160 add %o2, %o1, %o3 ! calc the new value
michael@0 161 mov %o3, %o4 ! save the return value
michael@0 162 cas [%o0], %o2, %o3 ! atomically set if o0 hasn't changed
michael@0 163 cmp %o2, %o3 ! see if we set the value
michael@0 164 bne retryAA ! if not, try again
michael@0 165 nop ! empty out the branch pipeline
michael@0 166 retl ! return back to the caller
michael@0 167 mov %o4, %o0 ! set the return code to the new value
michael@0 168
michael@0 169 SET_SIZE(PR_AtomicAdd) ! standard assembler/ELF epilogue
michael@0 170
michael@0 171 !
michael@0 172 ! end
michael@0 173 !

mercurial