VirtualBox

Changeset 87155 in vbox for trunk/include/iprt


Ignore:
Timestamp:
Jan 2, 2021 5:56:13 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
142067
Message:

iprt/asm.h: ASMAtomicXchgUxx and some ASMAtomicCmpXchgXx. bugref:9898 bugref:9026

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/asm.h

    r87154 r87155  
    301301
    302302# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
    303     RTCCUINTREG uOld;
    304     RTCCUINTREG rcSpill;
     303    uint32_t uOld;
     304    uint32_t rcSpill;
    305305    __asm__ __volatile__("try_again%=:\n\t"
    306306#  if defined(RT_ARCH_ARM64)
    307                          "ldaxrb %w0, [%3]\n\t"
    308                          "stlxrb %w1, %w2, [%3]\n\t"
    309                          "cbnz %w1, try_again%=\n\t"
    310 #  else
    311                          "ldrexb %0, [%3]\n\t"      /* ARMv6+ */
    312                          "strex %1, %2, [%3]\n\t"
    313                          "cmp %1, #0\n\t"
    314                          "bne try_again%=\n\t"
     307                         "ldaxrb    %w0, [%3]\n\t"
     308                         "stlxrb    %w1, %w2, [%3]\n\t"
     309                         "cbnz      %w1, try_again%=\n\t"
     310#  else
     311                         "ldrexb    %0, [%3]\n\t"      /* ARMv6+ */
     312                         "strexb    %1, %2, [%3]\n\t"
     313                         "cmp       %1, #0\n\t"
     314                         "bne       try_again%=\n\t"
    315315#  endif
    316316                         : "=&r" (uOld),
    317317                           "=&r" (rcSpill)
    318                          : "r" ((RTCCUINTREG)u8),
     318                         : "r" ((uint32_t)u8),
    319319                           "r" (pu8)
    320                          : "memory");
     320                         : "memory",
     321                           "cc");
    321322    return (uint8_t)uOld;
    322323
     
    365366 * @param   u16     The 16-bit value to assign to *pu16.
    366367 */
    367 #if RT_INLINE_ASM_EXTERNAL
     368#if RT_INLINE_ASM_EXTERNAL_TMP_ARM
    368369RT_ASM_DECL_PRAGMA_WATCOM(uint16_t) ASMAtomicXchgU16(volatile uint16_t RT_FAR *pu16, uint16_t u16) RT_NOTHROW_PROTO;
    369370#else
    370371DECLINLINE(uint16_t) ASMAtomicXchgU16(volatile uint16_t RT_FAR *pu16, uint16_t u16) RT_NOTHROW_DEF
    371372{
    372 # if RT_INLINE_ASM_GNU_STYLE
     373# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     374#  if RT_INLINE_ASM_GNU_STYLE
    373375    __asm__ __volatile__("xchgw %0, %1\n\t"
    374376                         : "=m" (*pu16),
     
    376378                         : "1" (u16),
    377379                           "m" (*pu16));
    378 # else
     380#  else
    379381    __asm
    380382    {
    381 ifdef RT_ARCH_AMD64
     383 ifdef RT_ARCH_AMD64
    382384        mov     rdx, [pu16]
    383385        mov     ax, [u16]
    384386        xchg    [rdx], ax
    385387        mov     [u16], ax
    386 else
     388 else
    387389        mov     edx, [pu16]
    388390        mov     ax, [u16]
    389391        xchg    [edx], ax
    390392        mov     [u16], ax
    391 endif
    392     }
    393 # endif
     393 endif
     394    }
     395#  endif
    394396    return u16;
     397
     398# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
     399    uint32_t uOld;
     400    uint32_t rcSpill;
     401    __asm__ __volatile__("try_again%=:\n\t"
     402#  if defined(RT_ARCH_ARM64)
     403                         "ldaxrh    %w0, [%3]\n\t"
     404                         "stlxrh    %w1, %w2, [%3]\n\t"
     405                         "cbnz      %w1, try_again%=\n\t"
     406#  else
     407                         "ldrexh    %0, [%3]\n\t"      /* ARMv6+ */
     408                         "strexh    %1, %2, [%3]\n\t"
     409                         "cmp       %1, #0\n\t"
     410                         "bne       try_again%=\n\t"
     411#  endif
     412                         : "=&r" (uOld),
     413                           "=&r" (rcSpill)
     414                         : "r" ((uint32_t)u16),
     415                           "r" (pu16)
     416                         : "memory",
     417                           "cc");
     418    return (uint16_t)uOld;
     419
     420# else
     421#  error "Port me"
     422# endif
    395423}
    396424#endif
     
    419447 * @remarks Does not work on 286 and earlier.
    420448 */
    421 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
     449#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
    422450RT_ASM_DECL_PRAGMA_WATCOM(uint32_t) ASMAtomicXchgU32(volatile uint32_t RT_FAR *pu32, uint32_t u32) RT_NOTHROW_PROTO;
    423451#else
    424452DECLINLINE(uint32_t) ASMAtomicXchgU32(volatile uint32_t RT_FAR *pu32, uint32_t u32) RT_NOTHROW_DEF
    425453{
    426 # if RT_INLINE_ASM_GNU_STYLE
     454# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     455#  if RT_INLINE_ASM_GNU_STYLE
    427456    __asm__ __volatile__("xchgl %0, %1\n\t"
    428457                         : "=m" (*pu32),
     
    431460                           "m" (*pu32));
    432461
    433 # elif RT_INLINE_ASM_USES_INTRIN
     462#  elif RT_INLINE_ASM_USES_INTRIN
    434463   u32 = _InterlockedExchange((long RT_FAR *)pu32, u32);
    435464
    436 # else
     465#  else
    437466    __asm
    438467    {
    439 ifdef RT_ARCH_AMD64
     468 ifdef RT_ARCH_AMD64
    440469        mov     rdx, [pu32]
    441470        mov     eax, u32
    442471        xchg    [rdx], eax
    443472        mov     [u32], eax
    444 else
     473 else
    445474        mov     edx, [pu32]
    446475        mov     eax, u32
    447476        xchg    [edx], eax
    448477        mov     [u32], eax
    449 endif
    450     }
    451 # endif
     478 endif
     479    }
     480#  endif
    452481    return u32;
     482
     483# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
     484    uint32_t uOld;
     485    uint32_t rcSpill;
     486    __asm__ __volatile__("try_again%=:\n\t"
     487#  if defined(RT_ARCH_ARM64)
     488                         "ldaxr     %w0, [%3]\n\t"
     489                         "stlxr     %w1, %w2, [%3]\n\t"
     490                         "cbnz      %w1, try_again%=\n\t"
     491#  else
     492                         "ldrex     %0, [%3]\n\t"      /* ARMv6+ */
     493                         "strex     %1, %2, [%3]\n\t"
     494                         "cmp       %1, #0\n\t"
     495                         "bne       try_again%=\n\t"
     496#  endif
     497                         : "=&r" (uOld),
     498                           "=&r" (rcSpill)
     499                         : "r" ((uint32_t)u32),
     500                           "r" (pu32)
     501                         : "memory",
     502                           "cc");
     503    return (uint32_t)uOld;
     504
     505# else
     506#  error "Port me"
     507# endif
    453508}
    454509#endif
     
    477532 * @remarks Works on 32-bit x86 CPUs starting with Pentium.
    478533 */
    479 #if (RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN) \
     534#if (RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN) \
    480535 || RT_INLINE_DONT_MIX_CMPXCHG8B_AND_PIC
    481536RT_ASM_DECL_PRAGMA_WATCOM(uint64_t) ASMAtomicXchgU64(volatile uint64_t RT_FAR *pu64, uint64_t u64) RT_NOTHROW_PROTO;
     
    502557    }
    503558#  endif
    504 # else /* !RT_ARCH_AMD64 */
     559
     560# elif defined(RT_ARCH_X86)
    505561#  if RT_INLINE_ASM_GNU_STYLE
    506562#   if defined(PIC) || defined(__PIC__)
     
    544600    }
    545601#  endif
    546 # endif /* !RT_ARCH_AMD64 */
     602
     603# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
     604    uint32_t rcSpill;
     605    __asm__ __volatile__("try_again%=:\n\t"
     606#  if defined(RT_ARCH_ARM64)
     607                         "ldaxr     %0, [%3]\n\t"
     608                         "stlxr     %w1, %2, [%3]\n\t"
     609                         "cbnz      %w1, try_again%=\n\t"
     610#  else
     611                         "ldrexd    %H0, [%3]\n\t"      /* ARMv6+ */
     612                         "strexd    %1, %H2, [%3]\n\t"
     613                         "cmp       %1, #0\n\t"
     614                         "bne       try_again%=\n\t"
     615#  endif
     616                         : "=&r" (u64),
     617                           "=&r" (rcSpill)
     618                         : "r" (u64),
     619                           "r" (pu64)
     620                         : "memory",
     621                           "cc");
     622# else
     623#  error "Port me"
     624# endif
    547625    return u64;
    548626}
     
    758836 * @remarks x86: Requires a 486 or later.
    759837 */
    760 #if RT_INLINE_ASM_EXTERNAL || !RT_INLINE_ASM_GNU_STYLE
     838#if RT_INLINE_ASM_EXTERNAL_TMP_ARM || !RT_INLINE_ASM_GNU_STYLE
    761839RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicCmpXchgU8(volatile uint8_t RT_FAR *pu8, const uint8_t u8New, const uint8_t u8Old) RT_NOTHROW_PROTO;
    762840#else
    763841DECLINLINE(bool) ASMAtomicCmpXchgU8(volatile uint8_t RT_FAR *pu8, const uint8_t u8New, uint8_t u8Old) RT_NOTHROW_DEF
    764842{
     843# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    765844    uint8_t u8Ret;
    766845    __asm__ __volatile__("lock; cmpxchgb %3, %0\n\t"
     
    773852                           "m" (*pu8));
    774853    return (bool)u8Ret;
     854
     855# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
     856    uint32_t fXchg;
     857    uint32_t u32Spill;
     858    uint32_t rcSpill;
     859    __asm__ __volatile__("try_again%=:\n\t"
     860#  if defined(RT_ARCH_ARM64)
     861                         "ldaxrb    %w0, [%5]\n\t"
     862                         "cmp       %w0, %w3\n\t"
     863                         "bne       1f\n\t"   /* stop here if not equal */
     864                         "stlxrb    %w1, %w4, [%5]\n\t"
     865                         "cbnz      %w1, try_again%=\n\t"
     866                         "mov       %w2, #1\n\t"
     867#  else
     868                         "ldrexb    %0, [%5]\n\t"
     869                         "teq       %0, %3\n\t"
     870                         "strexbeq  %1, %4, [%5]\n\t"
     871                         "bne       1f\n\t"   /* stop here if not equal */
     872                         "cmp       %1, #0\n\t"
     873                         "bne       try_again%=\n\t"
     874                         "mov       %2, #1\n\t"
     875#  endif
     876                         "1:\n\t"
     877                         : "=&r" (u32Spill),
     878                           "=&r" (rcSpill),
     879                           "=&r" (fXchg)
     880                         : "r" ((uint32_t)u8Old),
     881                           "r" ((uint32_t)u8New),
     882                           "r" (pu8),
     883                           "2" (0) /*fXchg*/
     884                         : "memory",
     885                           "cc");
     886    return (bool)fXchg;
     887# else
     888#  error "Port me"
     889# endif /* RT_ARCH_ARM */
    775890}
    776891#endif
     
    825940 * @remarks x86: Requires a 486 or later.
    826941 */
    827 #if RT_INLINE_ASM_EXTERNAL && !RT_INLINE_ASM_USES_INTRIN
     942#if RT_INLINE_ASM_EXTERNAL_TMP_ARM && !RT_INLINE_ASM_USES_INTRIN
    828943RT_ASM_DECL_PRAGMA_WATCOM(bool) ASMAtomicCmpXchgU32(volatile uint32_t RT_FAR *pu32, const uint32_t u32New, const uint32_t u32Old) RT_NOTHROW_PROTO;
    829944#else
    830945DECLINLINE(bool) ASMAtomicCmpXchgU32(volatile uint32_t RT_FAR *pu32, const uint32_t u32New, uint32_t u32Old) RT_NOTHROW_DEF
    831946{
    832 # if RT_INLINE_ASM_GNU_STYLE
     947# if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     948#  if RT_INLINE_ASM_GNU_STYLE
    833949    uint8_t u8Ret;
    834950    __asm__ __volatile__("lock; cmpxchgl %3, %0\n\t"
     
    842958    return (bool)u8Ret;
    843959
    844 # elif RT_INLINE_ASM_USES_INTRIN
     960#  elif RT_INLINE_ASM_USES_INTRIN
    845961    return (uint32_t)_InterlockedCompareExchange((long RT_FAR *)pu32, u32New, u32Old) == u32Old;
    846962
    847 # else
     963#  else
    848964    uint32_t u32Ret;
    849965    __asm
    850966    {
    851 ifdef RT_ARCH_AMD64
     967 ifdef RT_ARCH_AMD64
    852968        mov     rdx, [pu32]
    853 else
     969 else
    854970        mov     edx, [pu32]
    855 endif
     971 endif
    856972        mov     eax, [u32Old]
    857973        mov     ecx, [u32New]
    858 ifdef RT_ARCH_AMD64
     974 ifdef RT_ARCH_AMD64
    859975        lock cmpxchg [rdx], ecx
    860 else
     976 else
    861977        lock cmpxchg [edx], ecx
    862 endif
     978 endif
    863979        setz    al
    864980        movzx   eax, al
     
    866982    }
    867983    return !!u32Ret;
    868 # endif
     984#  endif
     985
     986# elif defined(RT_ARCH_ARM64) || defined(RT_ARCH_ARM32)
     987    uint32_t fXchg;
     988    uint32_t u32Spill;
     989    uint32_t rcSpill;
     990    __asm__ __volatile__("try_again%=:\n\t"
     991#  if defined(RT_ARCH_ARM64)
     992                         "ldaxr     %w0, [%5]\n\t"
     993                         "cmp       %w0, %w3\n\t"
     994                         "bne       1f\n\t"   /* stop here if not equal */
     995                         "stlxr     %w1, %w4, [%5]\n\t"
     996                         "cbnz      %w1, try_again%=\n\t"
     997                         "mov       %w2, #1\n\t"
     998#  else
     999                         "ldrex     %0, [%5]\n\t"
     1000                         "teq       %0, %3\n\t"
     1001                         "strexeq   %1, %4, [%5]\n\t"
     1002                         "bne       1f\n\t"   /* stop here if not equal */
     1003                         "cmp       %1, #0\n\t"
     1004                         "bne       try_again%=\n\t"
     1005                         "mov       %2, #1\n\t"
     1006#  endif
     1007                         "1:\n\t"
     1008                         : "=&r" (u32Spill),
     1009                           "=&r" (rcSpill),
     1010                           "=&r" (fXchg)
     1011                         : "r" (u32Old),
     1012                           "r" (u32New),
     1013                           "r" (pu32),
     1014                           "2" (0) /*fXchg*/
     1015                         : "memory",
     1016                           "cc");
     1017    return (bool)fXchg;
     1018# else
     1019#  error "Port me"
     1020# endif /* RT_ARCH_ARM */
    8691021}
    8701022#endif
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette