VirtualBox

Changeset 101609 in vbox


Ignore:
Timestamp:
Oct 27, 2023 1:59:06 AM (18 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
159693
Message:

iprt/armv8.h: Worked out the two immediates for logical instructions (AND,ORR,EOR,++) and work conversion functions for them. bugref:10371

Location:
trunk
Files:
1 added
3 edited

Legend:

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

    r101602 r101609  
    26462646
    26472647/**
     2648 * Converts immS and immR values (to logical instructions) to a 32-bit mask.
     2649 *
     2650 * @returns The decoded mask.
     2651 * @param   uImm6SizeLen    The immS value from the instruction.  (No N part
     2652 *                          here, as that must be zero for instructions
     2653 *                          operating on 32-bit wide registers.)
     2654 * @param   uImm6Rotations  The immR value from the instruction.
     2655 */
     2656DECLEXPORT(uint32_t) Armv8A64ConvertImmRImmS2Mask32(uint32_t uImm6SizeLen, uint32_t uImm6Rotations)
     2657{
     2658    Assert(uImm6SizeLen < 64); Assert(uImm6Rotations < 64);
     2659
     2660    /* Determine the element size. */
     2661    unsigned const cBitsElementLog2 = ASMBitLastSetU32(uImm6SizeLen ^ 0x3f) - 1U;
     2662    Assert(cBitsElementLog2 + 1U != 0U);
     2663
     2664    unsigned const cBitsElement = RT_BIT_32(cBitsElementLog2);
     2665    Assert(uImm6Rotations < cBitsElement);
     2666
     2667    /* Extract the number of bits set to 1: */
     2668    unsigned const cBitsSetTo1  = (uImm6SizeLen & (cBitsElement - 1U)) + 1;
     2669    Assert(cBitsSetTo1 < cBitsElement);
     2670    uint32_t const uElement     = RT_BIT_32(cBitsSetTo1) - 1U;
     2671
     2672    /* Produce the unrotated pattern. */
     2673    static const uint32_t s_auReplicate[]
     2674        = { UINT32_MAX, UINT32_MAX / 3, UINT32_MAX / 15, UINT32_MAX / 255, UINT32_MAX / 65535, 1 };
     2675    uint32_t const uPattern     = s_auReplicate[cBitsElementLog2] * uElement;
     2676
     2677    /* Rotate it and return. */
     2678    return ASMRotateRightU32(uPattern, uImm6Rotations & (cBitsElement - 1U));
     2679}
     2680
     2681
     2682/**
     2683 * Converts N+immS and immR values (to logical instructions) to a 64-bit mask.
     2684 *
     2685 * @returns The decoded mask.
     2686 * @param   uImm7SizeLen    The N:immS value from the instruction.
     2687 * @param   uImm6Rotations  The immR value from the instruction.
     2688 */
     2689DECLEXPORT(uint64_t) Armv8A64ConvertImmRImmS2Mask64(uint32_t uImm7SizeLen, uint32_t uImm6Rotations)
     2690{
     2691    Assert(uImm7SizeLen < 128); Assert(uImm6Rotations < 64);
     2692
     2693    /* Determine the element size. */
     2694    unsigned const cBitsElementLog2 = ASMBitLastSetU32(uImm7SizeLen ^ 0x3f) - 1U;
     2695    Assert(cBitsElementLog2 + 1U != 0U);
     2696
     2697    unsigned const cBitsElement = RT_BIT_32(cBitsElementLog2);
     2698    Assert(uImm6Rotations < cBitsElement);
     2699
     2700    /* Extract the number of bits set to 1: */
     2701    unsigned const cBitsSetTo1  = (uImm7SizeLen & (cBitsElement - 1U)) + 1;
     2702    Assert(cBitsSetTo1 < cBitsElement);
     2703    uint64_t const uElement     = RT_BIT_64(cBitsSetTo1) - 1U;
     2704
     2705    /* Produce the unrotated pattern. */
     2706    static const uint64_t s_auReplicate[]
     2707        = { UINT64_MAX, UINT64_MAX / 3, UINT64_MAX / 15, UINT64_MAX / 255, UINT64_MAX / 65535, UINT64_MAX / UINT32_MAX, 1 };
     2708    uint64_t const uPattern     = s_auReplicate[cBitsElementLog2] * uElement;
     2709
     2710    /* Rotate it and return. */
     2711    return ASMRotateRightU64(uPattern, uImm6Rotations & (cBitsElement - 1U));
     2712}
     2713
     2714
     2715/**
     2716 * Variant of Armv8A64ConvertImmRImmS2Mask64 where the N bit is separate from
     2717 * the immS value.
     2718 */
     2719DECLEXPORT(uint64_t) Armv8A64ConvertImmRImmS2Mask64(uint32_t uN, uint32_t uImm6SizeLen, uint32_t uImm6Rotations)
     2720{
     2721    return Armv8A64ConvertImmRImmS2Mask64((uN << 6) | uImm6SizeLen, uImm6Rotations);
     2722}
     2723
     2724
     2725/**
     2726 * Helper for Armv8A64MkInstrLogicalImm and friends that tries to convert a
     2727 * 32-bit bitmask to a set of immediates for those instructions.
     2728 *
     2729 * @returns true if successful, false if not.
     2730 * @param   fMask           The mask value to convert.
     2731 * @param   puImm6SizeLen   Where to return the immS part (N is always zero for
     2732 *                          32-bit wide masks).
     2733 * @param   puImm6Rotations Where to return the immR.
     2734 */
     2735DECLINLINE(bool) Armv8A64ConvertMask32ToImmRImmS(uint32_t fMask, uint32_t *puImm6SizeLen, uint32_t *puImm6Rotations)
     2736{
     2737    /* Fend off 0 and UINT32_MAX as these cannot be represented. */
     2738    if ((uint32_t)(fMask + 1U) <= 1)
     2739        return false;
     2740
     2741    /* Rotate the value will we get all 1s at the bottom and the zeros at the top. */
     2742    unsigned const cRor = ASMCountTrailingZerosU32(fMask);
     2743    unsigned const cRol = ASMCountLeadingZerosU32(~fMask);
     2744    if (cRor)
     2745        fMask = ASMRotateRightU32(fMask, cRor);
     2746    else
     2747        fMask = ASMRotateLeftU32(fMask, cRol);
     2748    Assert(fMask & RT_BIT_32(0));
     2749    Assert(!(fMask & RT_BIT_32(31)));
     2750
     2751    /* Count the trailing ones and leading zeros. */
     2752    unsigned const cOnes  = ASMCountTrailingZerosU32(~fMask);
     2753    unsigned const cZeros = ASMCountLeadingZerosU32(fMask);
     2754
     2755    /* The potential element length is then the sum of the two above. */
     2756    unsigned const cBitsElement = cOnes + cZeros;
     2757    if (!RT_IS_POWER_OF_TWO(cBitsElement) || cBitsElement < 2)
     2758        return false;
     2759
     2760    /* Special case: 32 bits element size. Since we're done here. */
     2761    if (cBitsElement == 32)
     2762        *puImm6SizeLen = cOnes - 1;
     2763    else
     2764    {
     2765        /* Extract the element bits and check that these are replicated in the whole pattern. */
     2766        uint32_t const uElement         = RT_BIT_32(cOnes) - 1U;
     2767        unsigned const cBitsElementLog2 = ASMBitFirstSetU32(cBitsElement) - 1;
     2768
     2769        static const uint32_t s_auReplicate[]
     2770            = { UINT32_MAX, UINT32_MAX / 3, UINT32_MAX / 15, UINT32_MAX / 255, UINT32_MAX / 65535, 1 };
     2771        if (s_auReplicate[cBitsElementLog2] * uElement == fMask)
     2772            *puImm6SizeLen = (cOnes - 1) | ((0x3e << cBitsElementLog2) & 0x3f);
     2773        else
     2774            return false;
     2775    }
     2776    *puImm6Rotations = cRor ? cBitsElement - cRor : cRol;
     2777
     2778    return true;
     2779}
     2780
     2781
     2782/**
     2783 * Helper for Armv8A64MkInstrLogicalImm and friends that tries to convert a
     2784 * 64-bit bitmask to a set of immediates for those instructions.
     2785 *
     2786 * @returns true if successful, false if not.
     2787 * @param   fMask           The mask value to convert.
     2788 * @param   puImm7SizeLen   Where to return the N:immS part.
     2789 * @param   puImm6Rotations Where to return the immR.
     2790 */
     2791DECLINLINE(bool) Armv8A64ConvertMask64ToImmRImmS(uint64_t fMask, uint32_t *puImm7SizeLen, uint32_t *puImm6Rotations)
     2792{
     2793    /* Fend off 0 and UINT64_MAX as these cannot be represented. */
     2794    if ((uint64_t)(fMask + 1U) <= 1)
     2795        return false;
     2796
     2797    /* Rotate the value will we get all 1s at the bottom and the zeros at the top. */
     2798    unsigned const cRor = ASMCountTrailingZerosU64(fMask);
     2799    unsigned const cRol = ASMCountLeadingZerosU64(~fMask);
     2800    if (cRor)
     2801        fMask = ASMRotateRightU64(fMask, cRor);
     2802    else
     2803        fMask = ASMRotateLeftU64(fMask, cRol);
     2804    Assert(fMask & RT_BIT_64(0));
     2805    Assert(!(fMask & RT_BIT_64(63)));
     2806
     2807    /* Count the trailing ones and leading zeros. */
     2808    unsigned const cOnes  = ASMCountTrailingZerosU64(~fMask);
     2809    unsigned const cZeros = ASMCountLeadingZerosU64(fMask);
     2810
     2811    /* The potential element length is then the sum of the two above. */
     2812    unsigned const cBitsElement = cOnes + cZeros;
     2813    if (!RT_IS_POWER_OF_TWO(cBitsElement) || cBitsElement < 2)
     2814        return false;
     2815
     2816    /* Special case: 64 bits element size. Since we're done here. */
     2817    if (cBitsElement == 64)
     2818        *puImm7SizeLen = (cOnes - 1) | 0x40 /*N*/;
     2819    else
     2820    {
     2821        /* Extract the element bits and check that these are replicated in the whole pattern. */
     2822        uint64_t const uElement         = RT_BIT_64(cOnes) - 1U;
     2823        unsigned const cBitsElementLog2 = ASMBitFirstSetU64(cBitsElement) - 1;
     2824
     2825        static const uint64_t s_auReplicate[]
     2826            = { UINT64_MAX, UINT64_MAX / 3, UINT64_MAX / 15, UINT64_MAX / 255, UINT64_MAX / 65535, UINT64_MAX / UINT32_MAX, 1 };
     2827        if (s_auReplicate[cBitsElementLog2] * uElement == fMask)
     2828            *puImm7SizeLen = (cOnes - 1) | ((0x3e << cBitsElementLog2) & 0x3f);
     2829        else
     2830            return false;
     2831    }
     2832    *puImm6Rotations = cRor ? cBitsElement - cRor : cRol;
     2833
     2834    return true;
     2835}
     2836
     2837
     2838/**
    26482839 * A64: Encodes a logical instruction with an complicated immediate mask.
     2840 *
     2841 * The @a uImm7SizeLen parameter specifies two things:
     2842 *      1. the element size and
     2843 *      2. the number of bits set to 1 in the pattern.
     2844 *
     2845 * The element size is extracted by NOT'ing bits 5:0 (excludes the N bit at the
     2846 * top) and using the position of the first bit set as a power of two.
     2847 *
     2848 * | N | 5 | 4 | 3 | 2 | 1 | 0 | element size |
     2849 * |---|---|---|---|---|---|---|--------------|
     2850 * | 0 | 1 | 1 | 1 | 1 | 0 | x | 2 bits       |
     2851 * | 0 | 1 | 1 | 1 | 0 | x | x | 4 bits       |
     2852 * | 0 | 1 | 1 | 0 | x | x | x | 8 bits       |
     2853 * | 0 | 1 | 0 | x | x | x | x | 16 bits      |
     2854 * | 0 | 0 | x | x | x | x | x | 32 bits      |
     2855 * | 1 | x | x | x | x | x | x | 64 bits      |
     2856 *
     2857 * The 'x' forms the number of 1 bits in the pattern, minus one (i.e.
     2858 * there is always one zero bit in the pattern).
     2859 *
     2860 * The @a uImm6Rotations parameter specifies how many bits to the right,
     2861 * the element pattern is rotated. The rotation count must be less than the
     2862 * element bit count (size).
    26492863 *
    26502864 * @returns The encoded instruction.
     
    26542868 * @param   uImm7SizeLen    The size/pattern length.  We've combined the 1-bit N
    26552869 *                          field at the top of the 6-bit 'imms' field.
     2870 *
    26562871 * @param   uImm6Rotations  The rotation count.
    26572872 * @param   f64Bit          true for 64-bit GPRs, @c false for 32-bit GPRs.
     
    27642979                                               uint32_t offFirstBit, uint32_t cBitsWidth, bool f64Bit = true)
    27652980{
    2766     Assert(cBitsWidth > 0U); Assert(cBitsWidth < (f64Bit ? 64U : 32U)); Assert(offFirstBit < (f64Bit ? 64U : 32U)); RT_NOREF(offFirstBit);
    2767     return Armv8A64MkInstrBfm(iRegResult, iRegSrc, (uint32_t)-(int32_t)cBitsWidth & (f64Bit ? 0x3f : 0x1f),
     2981    Assert(cBitsWidth > 0U); Assert(cBitsWidth < (f64Bit ? 64U : 32U)); Assert(offFirstBit < (f64Bit ? 64U : 32U));
     2982    return Armv8A64MkInstrBfm(iRegResult, iRegSrc, (uint32_t)-(int32_t)offFirstBit & (f64Bit ? 0x3f : 0x1f),
    27682983                              cBitsWidth - 1, f64Bit);
    27692984}
  • trunk/include/iprt/asm.h

    r101228 r101609  
    77567756 * The counting starts with the least significate bit, i.e. the zero bit.
    77577757 *
    7758  * @returns Number of lest significant zero bits.
     7758 * @returns Number of least significant zero bits.
    77597759 * @returns 32 if all bits are cleared.
    77607760 * @param   u32     Integer to consider.
  • trunk/src/VBox/Runtime/testcase/Makefile.kmk

    r99960 r101609  
    6767 ifndef VBOX_ONLY_VALIDATIONKIT
    6868  PROGRAMS += \
     69        tstRTArmv8 \
    6970        tstRTAssertCompile \
    7071        tstRTAvl \
     
    277278 # Target configs in almost alphabetical order.
    278279 #
     280 tstRTArmv8_TEMPLATE = VBoxR3TstExe
     281 tstRTArmv8_SOURCES = tstRTArmv8.cpp
    279282
    280283 tstRTAssertCompile_TEMPLATE = VBoxR3TstExe
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