tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

os_SunOS_ultrasparc.s (6894B)


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