VirtualBox

Changeset 102941 in vbox for trunk/include


Ignore:
Timestamp:
Jan 18, 2024 12:15:14 AM (13 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
161169
Message:

iprt/asm.h: Working over the ASMAtomicXchg* functions for arm64 w/ optional use of LSE instructions. bugref:9898

File:
1 edited

Legend:

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

    r102940 r102941  
    526526# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
    527527    uint32_t uOld;
     528#  if defined(RTASM_ARM64_USE_FEAT_LSE)
     529    /* SWPALB is ~40% more expensive than the non-LSE variant (M1), but since we
     530       have the barrier we shouldn't need that, right? Ordering should be taken
     531       care of by the DMB. The SWPB is rather cheap (~70% faster). */
     532    __asm__ __volatile__("Lstart_ASMAtomicXchgU8_%=:\n\t"
     533                         RTASM_ARM_DMB_SY
     534                         "swpb      %w[uNew], %w[uOld], %[pMem]\n\t"
     535                         : [pMem] "+Q" (*pu8)
     536                         , [uOld] "=&r" (uOld)
     537                         : [uNew] "r" ((uint32_t)u8)
     538                           RTASM_ARM_DMB_SY_COMMA_IN_REG
     539                         : );
     540#  else
    528541    uint32_t rcSpill;
    529542    __asm__ __volatile__("Ltry_again_ASMAtomicXchgU8_%=:\n\t"
    530543                         RTASM_ARM_DMB_SY
    531 if defined(RT_ARCH_ARM64)
     544 if defined(RT_ARCH_ARM64)
    532545                         "ldaxrb    %w[uOld], %[pMem]\n\t"
    533546                         "stlxrb    %w[rc], %w[uNew], %[pMem]\n\t"
    534547                         "cbnz      %w[rc], Ltry_again_ASMAtomicXchgU8_%=\n\t"
    535 else
     548 else
    536549                         "ldrexb    %[uOld], %[pMem]\n\t"      /* ARMv6+ */
    537550                         "strexb    %[rc], %[uNew], %[pMem]\n\t"
    538551                         "cmp       %[rc], #0\n\t"
    539552                         "bne       Ltry_again_ASMAtomicXchgU8_%=\n\t"
    540 endif
     553 endif
    541554                         : [pMem] "+Q" (*pu8)
    542555                         , [uOld] "=&r" (uOld)
     
    545558                           RTASM_ARM_DMB_SY_COMMA_IN_REG
    546559                         : "cc");
     560#  endif
    547561    return (uint8_t)uOld;
    548562
     
    623637# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
    624638    uint32_t uOld;
     639#  if defined(RTASM_ARM64_USE_FEAT_LSE)
     640    /* SWPALH is ~40% more expensive than the non-LSE variant on an M1, 20%
     641       slower if we remove the barrier.  But since we have the barrier we
     642       shouldn't need that, right? Ordering should be taken care of by the DMB.
     643       The SWPH is rather cheap (~70% faster). */
     644    __asm__ __volatile__("Lstart_ASMAtomicXchgU16_%=:\n\t"
     645                         RTASM_ARM_DMB_SY
     646                         "swph      %w[uNew], %w[uOld], %[pMem]\n\t"
     647                         : [pMem] "+Q" (*pu16)
     648                         , [uOld] "=&r" (uOld)
     649                         : [uNew] "r" ((uint32_t)u16)
     650                           RTASM_ARM_DMB_SY_COMMA_IN_REG
     651                         : );
     652#  else
    625653    uint32_t rcSpill;
    626654    __asm__ __volatile__("Ltry_again_ASMAtomicXchgU16_%=:\n\t"
    627655                         RTASM_ARM_DMB_SY
    628 if defined(RT_ARCH_ARM64)
     656 if defined(RT_ARCH_ARM64)
    629657                         "ldaxrh    %w[uOld], %[pMem]\n\t"
    630658                         "stlxrh    %w[rc], %w[uNew], %[pMem]\n\t"
    631659                         "cbnz      %w[rc], Ltry_again_ASMAtomicXchgU16_%=\n\t"
    632 else
     660 else
    633661                         "ldrexh    %[uOld], %[pMem]\n\t"      /* ARMv6+ */
    634662                         "strexh    %[rc], %[uNew], %[pMem]\n\t"
    635663                         "cmp       %[rc], #0\n\t"
    636664                         "bne       Ltry_again_ASMAtomicXchgU16_%=\n\t"
    637 endif
     665 endif
    638666                         : [pMem] "+Q" (*pu16)
    639667                         , [uOld] "=&r" (uOld)
     
    642670                           RTASM_ARM_DMB_SY_COMMA_IN_REG
    643671                         : "cc");
     672#  endif
    644673    return (uint16_t)uOld;
    645674
     
    709738# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
    710739    uint32_t uOld;
     740#  if defined(RTASM_ARM64_USE_FEAT_LSE)
     741    /* SWPAL is ~40% more expensive than the non-LSE variant on an M1, 20%
     742       slower if we remove the barrier.  But since we have the barrier we
     743       shouldn't need that, right? Ordering should be taken care of by the DMB.
     744       The SWP is rather cheap (~70% faster). */
     745    __asm__ __volatile__("Lstart_ASMAtomicXchgU32_%=:\n\t"
     746                         RTASM_ARM_DMB_SY
     747                         "swp       %w[uNew], %w[uOld], %[pMem]\n\t"
     748                         : [pMem] "+Q" (*pu32)
     749                         , [uOld] "=&r" (uOld)
     750                         : [uNew] "r" (u32)
     751                           RTASM_ARM_DMB_SY_COMMA_IN_REG
     752                         : );
     753#  else
    711754    uint32_t rcSpill;
    712755    __asm__ __volatile__("Ltry_again_ASMAtomicXchgU32_%=:\n\t"
    713756                         RTASM_ARM_DMB_SY
    714 if defined(RT_ARCH_ARM64)
     757 if defined(RT_ARCH_ARM64)
    715758                         "ldaxr     %w[uOld], %[pMem]\n\t"
    716759                         "stlxr     %w[rc], %w[uNew], %[pMem]\n\t"
    717760                         "cbnz      %w[rc], Ltry_again_ASMAtomicXchgU32_%=\n\t"
    718 else
     761 else
    719762                         "ldrex     %[uOld], %[pMem]\n\t"      /* ARMv6+ */
    720763                         "strex     %[rc], %[uNew], %[pMem]\n\t"
    721764                         "cmp       %[rc], #0\n\t"
    722765                         "bne       Ltry_again_ASMAtomicXchgU32_%=\n\t"
    723 endif
     766 endif
    724767                         : [pMem] "+Q"  (*pu32)
    725768                         , [uOld] "=&r" (uOld)
     
    728771                           RTASM_ARM_DMB_SY_COMMA_IN_REG
    729772                         : "cc");
     773#  endif
    730774    return uOld;
    731775
     
    834878
    835879# elif defined(RT_ARCH_ARM32) || defined(RT_ARCH_ARM64)
     880    uint64_t uOld;
     881#  if defined(RTASM_ARM64_USE_FEAT_LSE)
     882    /* SWPAL is ~40% more expensive than the non-LSE variant on an M1, 20%
     883       slower if we remove the barrier.  But since we have the barrier we
     884       shouldn't need that, right? Ordering should be taken care of by the DMB.
     885       The SWP is rather cheap (~70% faster). */
     886    __asm__ __volatile__("Lstart_ASMAtomicXchgU64_%=:\n\t"
     887                         RTASM_ARM_DMB_SY
     888                         "swp       %[uNew], %[uOld], %[pMem]\n\t"
     889                         : [pMem] "+Q" (*pu64)
     890                         , [uOld] "=&r" (uOld)
     891                         : [uNew] "r" (u64)
     892                           RTASM_ARM_DMB_SY_COMMA_IN_REG
     893                         : );
     894#  else
    836895    uint32_t rcSpill;
    837     uint64_t uOld;
    838896    __asm__ __volatile__("Ltry_again_ASMAtomicXchgU64_%=:\n\t"
    839897                         RTASM_ARM_DMB_SY
    840 if defined(RT_ARCH_ARM64)
     898 if defined(RT_ARCH_ARM64)
    841899                         "ldaxr     %[uOld], %[pMem]\n\t"
    842900                         "stlxr     %w[rc], %[uNew], %[pMem]\n\t"
    843901                         "cbnz      %w[rc], Ltry_again_ASMAtomicXchgU64_%=\n\t"
    844 else
     902 else
    845903                         "ldrexd    %[uOld], %H[uOld], %[pMem]\n\t"      /* ARMv6+ */
    846904                         "strexd    %[rc], %[uNew], %H[uNew], %[pMem]\n\t"
    847905                         "cmp       %[rc], #0\n\t"
    848906                         "bne       Ltry_again_ASMAtomicXchgU64_%=\n\t"
    849 endif
     907 endif
    850908                         : [pMem] "+Q"  (*pu64)
    851909                         , [uOld] "=&r" (uOld)
     
    854912                           RTASM_ARM_DMB_SY_COMMA_IN_REG
    855913                         : "cc");
     914#  endif
    856915    return uOld;
    857916
Note: See TracChangeset for help on using the changeset viewer.

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