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.

     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/.
     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)
    16 #include <sys/asm_linkage.h>
    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 !  -----------------------
    41         ENTRY(PR_AtomicIncrement)       ! standard assembler/ELF prologue
    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
    54         SET_SIZE(PR_AtomicIncrement)    ! standard assembler/ELF epilogue
    56 !
    57 !  end
    58 !
    59 !  ======================================================================
    60 !
    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 !  -----------------------
    85         ENTRY(PR_AtomicDecrement)       ! standard assembler/ELF prologue
    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
    98         SET_SIZE(PR_AtomicDecrement)    ! standard assembler/ELF epilogue
   100 !
   101 !  end
   102 !
   103 !  ======================================================================
   104 !
   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 !  -----------------------
   128         ENTRY(PR_AtomicSet)             ! standard assembler/ELF prologue
   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
   140         SET_SIZE(PR_AtomicSet)          ! standard assembler/ELF epilogue
   142 !
   143 !  end
   144 !
   145 !  ======================================================================
   146 !
   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
   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
   169         SET_SIZE(PR_AtomicAdd)    		! standard assembler/ELF epilogue
   171 !
   172 !  end
   173 !

mercurial