duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

instructions-aarch64.cc (38524B)


      1 // Copyright 2015, VIXL authors
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are met:
      6 //
      7 //   * Redistributions of source code must retain the above copyright notice,
      8 //     this list of conditions and the following disclaimer.
      9 //   * Redistributions in binary form must reproduce the above copyright notice,
     10 //     this list of conditions and the following disclaimer in the documentation
     11 //     and/or other materials provided with the distribution.
     12 //   * Neither the name of ARM Limited nor the names of its contributors may be
     13 //     used to endorse or promote products derived from this software without
     14 //     specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
     17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
     20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26 
     27 #include "instructions-aarch64.h"
     28 
     29 #include "assembler-aarch64.h"
     30 
     31 namespace vixl {
     32 namespace aarch64 {
     33 
     34 static uint64_t RepeatBitsAcrossReg(unsigned reg_size,
     35                                     uint64_t value,
     36                                     unsigned width) {
     37   VIXL_ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
     38               (width == 32));
     39   VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
     40               (reg_size == kSRegSize) || (reg_size == kDRegSize));
     41   uint64_t result = value & ((UINT64_C(1) << width) - 1);
     42   for (unsigned i = width; i < reg_size; i *= 2) {
     43     result |= (result << i);
     44   }
     45   return result;
     46 }
     47 
     48 bool Instruction::CanTakeSVEMovprfx(const char* form,
     49                                     const Instruction* movprfx) const {
     50   return CanTakeSVEMovprfx(Hash(form), movprfx);
     51 }
     52 
     53 bool Instruction::CanTakeSVEMovprfx(uint32_t form_hash,
     54                                     const Instruction* movprfx) const {
     55   bool movprfx_is_predicated = movprfx->Mask(SVEMovprfxMask) == MOVPRFX_z_p_z;
     56   bool movprfx_is_unpredicated =
     57       movprfx->Mask(SVEConstructivePrefix_UnpredicatedMask) == MOVPRFX_z_z;
     58   VIXL_ASSERT(movprfx_is_predicated != movprfx_is_unpredicated);
     59 
     60   int movprfx_zd = movprfx->GetRd();
     61   int movprfx_pg = movprfx_is_predicated ? movprfx->GetPgLow8() : -1;
     62   VectorFormat movprfx_vform =
     63       movprfx_is_predicated ? movprfx->GetSVEVectorFormat() : kFormatUndefined;
     64 
     65   bool pg_matches_low8 = movprfx_pg == GetPgLow8();
     66   bool vform_matches = movprfx_vform == GetSVEVectorFormat();
     67   bool zd_matches = movprfx_zd == GetRd();
     68   bool zd_isnt_zn = movprfx_zd != GetRn();
     69   bool zd_isnt_zm = movprfx_zd != GetRm();
     70 
     71   switch (form_hash) {
     72     case "cdot_z_zzzi_s"_h:
     73     case "sdot_z_zzzi_s"_h:
     74     case "sudot_z_zzzi_s"_h:
     75     case "udot_z_zzzi_s"_h:
     76     case "usdot_z_zzzi_s"_h:
     77       return (GetRd() != static_cast<int>(ExtractBits(18, 16))) &&
     78              movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
     79 
     80     case "cdot_z_zzzi_d"_h:
     81     case "sdot_z_zzzi_d"_h:
     82     case "udot_z_zzzi_d"_h:
     83       return (GetRd() != static_cast<int>(ExtractBits(19, 16))) &&
     84              movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
     85 
     86     case "fmlalb_z_zzzi_s"_h:
     87     case "fmlalt_z_zzzi_s"_h:
     88     case "fmlslb_z_zzzi_s"_h:
     89     case "fmlslt_z_zzzi_s"_h:
     90     case "smlalb_z_zzzi_d"_h:
     91     case "smlalb_z_zzzi_s"_h:
     92     case "smlalt_z_zzzi_d"_h:
     93     case "smlalt_z_zzzi_s"_h:
     94     case "smlslb_z_zzzi_d"_h:
     95     case "smlslb_z_zzzi_s"_h:
     96     case "smlslt_z_zzzi_d"_h:
     97     case "smlslt_z_zzzi_s"_h:
     98     case "sqdmlalb_z_zzzi_d"_h:
     99     case "sqdmlalb_z_zzzi_s"_h:
    100     case "sqdmlalt_z_zzzi_d"_h:
    101     case "sqdmlalt_z_zzzi_s"_h:
    102     case "sqdmlslb_z_zzzi_d"_h:
    103     case "sqdmlslb_z_zzzi_s"_h:
    104     case "sqdmlslt_z_zzzi_d"_h:
    105     case "sqdmlslt_z_zzzi_s"_h:
    106     case "umlalb_z_zzzi_d"_h:
    107     case "umlalb_z_zzzi_s"_h:
    108     case "umlalt_z_zzzi_d"_h:
    109     case "umlalt_z_zzzi_s"_h:
    110     case "umlslb_z_zzzi_d"_h:
    111     case "umlslb_z_zzzi_s"_h:
    112     case "umlslt_z_zzzi_d"_h:
    113     case "umlslt_z_zzzi_s"_h:
    114       return (GetRd() != GetSVEMulLongZmAndIndex().first) &&
    115              movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
    116 
    117     case "cmla_z_zzzi_h"_h:
    118     case "cmla_z_zzzi_s"_h:
    119     case "fcmla_z_zzzi_h"_h:
    120     case "fcmla_z_zzzi_s"_h:
    121     case "fmla_z_zzzi_d"_h:
    122     case "fmla_z_zzzi_h"_h:
    123     case "fmla_z_zzzi_s"_h:
    124     case "fmls_z_zzzi_d"_h:
    125     case "fmls_z_zzzi_h"_h:
    126     case "fmls_z_zzzi_s"_h:
    127     case "mla_z_zzzi_d"_h:
    128     case "mla_z_zzzi_h"_h:
    129     case "mla_z_zzzi_s"_h:
    130     case "mls_z_zzzi_d"_h:
    131     case "mls_z_zzzi_h"_h:
    132     case "mls_z_zzzi_s"_h:
    133     case "sqrdcmlah_z_zzzi_h"_h:
    134     case "sqrdcmlah_z_zzzi_s"_h:
    135     case "sqrdmlah_z_zzzi_d"_h:
    136     case "sqrdmlah_z_zzzi_h"_h:
    137     case "sqrdmlah_z_zzzi_s"_h:
    138     case "sqrdmlsh_z_zzzi_d"_h:
    139     case "sqrdmlsh_z_zzzi_h"_h:
    140     case "sqrdmlsh_z_zzzi_s"_h:
    141       return (GetRd() != GetSVEMulZmAndIndex().first) &&
    142              movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
    143 
    144     case "adclb_z_zzz"_h:
    145     case "adclt_z_zzz"_h:
    146     case "bcax_z_zzz"_h:
    147     case "bsl1n_z_zzz"_h:
    148     case "bsl2n_z_zzz"_h:
    149     case "bsl_z_zzz"_h:
    150     case "cdot_z_zzz"_h:
    151     case "cmla_z_zzz"_h:
    152     case "eor3_z_zzz"_h:
    153     case "eorbt_z_zz"_h:
    154     case "eortb_z_zz"_h:
    155     case "fmlalb_z_zzz"_h:
    156     case "fmlalt_z_zzz"_h:
    157     case "fmlslb_z_zzz"_h:
    158     case "fmlslt_z_zzz"_h:
    159     case "nbsl_z_zzz"_h:
    160     case "saba_z_zzz"_h:
    161     case "sabalb_z_zzz"_h:
    162     case "sabalt_z_zzz"_h:
    163     case "sbclb_z_zzz"_h:
    164     case "sbclt_z_zzz"_h:
    165     case "sdot_z_zzz"_h:
    166     case "smlalb_z_zzz"_h:
    167     case "smlalt_z_zzz"_h:
    168     case "smlslb_z_zzz"_h:
    169     case "smlslt_z_zzz"_h:
    170     case "sqdmlalb_z_zzz"_h:
    171     case "sqdmlalbt_z_zzz"_h:
    172     case "sqdmlalt_z_zzz"_h:
    173     case "sqdmlslb_z_zzz"_h:
    174     case "sqdmlslbt_z_zzz"_h:
    175     case "sqdmlslt_z_zzz"_h:
    176     case "sqrdcmlah_z_zzz"_h:
    177     case "sqrdmlah_z_zzz"_h:
    178     case "sqrdmlsh_z_zzz"_h:
    179     case "uaba_z_zzz"_h:
    180     case "uabalb_z_zzz"_h:
    181     case "uabalt_z_zzz"_h:
    182     case "udot_z_zzz"_h:
    183     case "umlalb_z_zzz"_h:
    184     case "umlalt_z_zzz"_h:
    185     case "umlslb_z_zzz"_h:
    186     case "umlslt_z_zzz"_h:
    187     case "usdot_z_zzz_s"_h:
    188     case "fmmla_z_zzz_s"_h:
    189     case "fmmla_z_zzz_d"_h:
    190     case "smmla_z_zzz"_h:
    191     case "ummla_z_zzz"_h:
    192     case "usmmla_z_zzz"_h:
    193       return movprfx_is_unpredicated && zd_isnt_zm && zd_isnt_zn && zd_matches;
    194 
    195     case "addp_z_p_zz"_h:
    196     case "cadd_z_zz"_h:
    197     case "clasta_z_p_zz"_h:
    198     case "clastb_z_p_zz"_h:
    199     case "decd_z_zs"_h:
    200     case "dech_z_zs"_h:
    201     case "decw_z_zs"_h:
    202     case "ext_z_zi_des"_h:
    203     case "faddp_z_p_zz"_h:
    204     case "fmaxnmp_z_p_zz"_h:
    205     case "fmaxp_z_p_zz"_h:
    206     case "fminnmp_z_p_zz"_h:
    207     case "fminp_z_p_zz"_h:
    208     case "ftmad_z_zzi"_h:
    209     case "incd_z_zs"_h:
    210     case "inch_z_zs"_h:
    211     case "incw_z_zs"_h:
    212     case "insr_z_v"_h:
    213     case "smaxp_z_p_zz"_h:
    214     case "sminp_z_p_zz"_h:
    215     case "splice_z_p_zz_des"_h:
    216     case "sqcadd_z_zz"_h:
    217     case "sqdecd_z_zs"_h:
    218     case "sqdech_z_zs"_h:
    219     case "sqdecw_z_zs"_h:
    220     case "sqincd_z_zs"_h:
    221     case "sqinch_z_zs"_h:
    222     case "sqincw_z_zs"_h:
    223     case "srsra_z_zi"_h:
    224     case "ssra_z_zi"_h:
    225     case "umaxp_z_p_zz"_h:
    226     case "uminp_z_p_zz"_h:
    227     case "uqdecd_z_zs"_h:
    228     case "uqdech_z_zs"_h:
    229     case "uqdecw_z_zs"_h:
    230     case "uqincd_z_zs"_h:
    231     case "uqinch_z_zs"_h:
    232     case "uqincw_z_zs"_h:
    233     case "ursra_z_zi"_h:
    234     case "usra_z_zi"_h:
    235     case "xar_z_zzi"_h:
    236       return movprfx_is_unpredicated && zd_isnt_zn && zd_matches;
    237 
    238     case "add_z_zi"_h:
    239     case "and_z_zi"_h:
    240     case "decp_z_p_z"_h:
    241     case "eor_z_zi"_h:
    242     case "incp_z_p_z"_h:
    243     case "insr_z_r"_h:
    244     case "mul_z_zi"_h:
    245     case "orr_z_zi"_h:
    246     case "smax_z_zi"_h:
    247     case "smin_z_zi"_h:
    248     case "sqadd_z_zi"_h:
    249     case "sqdecp_z_p_z"_h:
    250     case "sqincp_z_p_z"_h:
    251     case "sqsub_z_zi"_h:
    252     case "sub_z_zi"_h:
    253     case "subr_z_zi"_h:
    254     case "umax_z_zi"_h:
    255     case "umin_z_zi"_h:
    256     case "uqadd_z_zi"_h:
    257     case "uqdecp_z_p_z"_h:
    258     case "uqincp_z_p_z"_h:
    259     case "uqsub_z_zi"_h:
    260       return movprfx_is_unpredicated && zd_matches;
    261 
    262     case "cpy_z_p_i"_h:
    263       if (movprfx_is_predicated) {
    264         if (!vform_matches) return false;
    265         if (movprfx_pg != GetRx<19, 16>()) return false;
    266       }
    267       // Only the merging form can take movprfx.
    268       if (ExtractBit(14) == 0) return false;
    269       return zd_matches;
    270 
    271     case "fcpy_z_p_i"_h:
    272       return (movprfx_is_unpredicated ||
    273               ((movprfx_pg == GetRx<19, 16>()) && vform_matches)) &&
    274              zd_matches;
    275 
    276     case "flogb_z_p_z"_h:
    277       return (movprfx_is_unpredicated ||
    278               ((movprfx_vform == GetSVEVectorFormat(17)) && pg_matches_low8)) &&
    279              zd_isnt_zn && zd_matches;
    280 
    281     case "asr_z_p_zi"_h:
    282     case "asrd_z_p_zi"_h:
    283     case "lsl_z_p_zi"_h:
    284     case "lsr_z_p_zi"_h:
    285     case "sqshl_z_p_zi"_h:
    286     case "sqshlu_z_p_zi"_h:
    287     case "srshr_z_p_zi"_h:
    288     case "uqshl_z_p_zi"_h:
    289     case "urshr_z_p_zi"_h:
    290       return (movprfx_is_unpredicated ||
    291               ((movprfx_vform ==
    292                 SVEFormatFromLaneSizeInBytesLog2(
    293                     GetSVEImmShiftAndLaneSizeLog2(true).second)) &&
    294                pg_matches_low8)) &&
    295              zd_matches;
    296 
    297     case "fcvt_z_p_z_d2h"_h:
    298     case "fcvt_z_p_z_d2s"_h:
    299     case "fcvt_z_p_z_h2d"_h:
    300     case "fcvt_z_p_z_s2d"_h:
    301     case "fcvtx_z_p_z_d2s"_h:
    302     case "fcvtzs_z_p_z_d2w"_h:
    303     case "fcvtzs_z_p_z_d2x"_h:
    304     case "fcvtzs_z_p_z_fp162x"_h:
    305     case "fcvtzs_z_p_z_s2x"_h:
    306     case "fcvtzu_z_p_z_d2w"_h:
    307     case "fcvtzu_z_p_z_d2x"_h:
    308     case "fcvtzu_z_p_z_fp162x"_h:
    309     case "fcvtzu_z_p_z_s2x"_h:
    310     case "scvtf_z_p_z_w2d"_h:
    311     case "scvtf_z_p_z_x2d"_h:
    312     case "scvtf_z_p_z_x2fp16"_h:
    313     case "scvtf_z_p_z_x2s"_h:
    314     case "ucvtf_z_p_z_w2d"_h:
    315     case "ucvtf_z_p_z_x2d"_h:
    316     case "ucvtf_z_p_z_x2fp16"_h:
    317     case "ucvtf_z_p_z_x2s"_h:
    318       return (movprfx_is_unpredicated ||
    319               ((movprfx_vform == kFormatVnD) && pg_matches_low8)) &&
    320              zd_isnt_zn && zd_matches;
    321 
    322     case "fcvtzs_z_p_z_fp162h"_h:
    323     case "fcvtzu_z_p_z_fp162h"_h:
    324     case "scvtf_z_p_z_h2fp16"_h:
    325     case "ucvtf_z_p_z_h2fp16"_h:
    326       return (movprfx_is_unpredicated ||
    327               ((movprfx_vform == kFormatVnH) && pg_matches_low8)) &&
    328              zd_isnt_zn && zd_matches;
    329 
    330     case "fcvt_z_p_z_h2s"_h:
    331     case "fcvt_z_p_z_s2h"_h:
    332     case "fcvtzs_z_p_z_fp162w"_h:
    333     case "fcvtzs_z_p_z_s2w"_h:
    334     case "fcvtzu_z_p_z_fp162w"_h:
    335     case "fcvtzu_z_p_z_s2w"_h:
    336     case "scvtf_z_p_z_w2fp16"_h:
    337     case "scvtf_z_p_z_w2s"_h:
    338     case "ucvtf_z_p_z_w2fp16"_h:
    339     case "ucvtf_z_p_z_w2s"_h:
    340       return (movprfx_is_unpredicated ||
    341               ((movprfx_vform == kFormatVnS) && pg_matches_low8)) &&
    342              zd_isnt_zn && zd_matches;
    343 
    344     case "fcmla_z_p_zzz"_h:
    345     case "fmad_z_p_zzz"_h:
    346     case "fmla_z_p_zzz"_h:
    347     case "fmls_z_p_zzz"_h:
    348     case "fmsb_z_p_zzz"_h:
    349     case "fnmad_z_p_zzz"_h:
    350     case "fnmla_z_p_zzz"_h:
    351     case "fnmls_z_p_zzz"_h:
    352     case "fnmsb_z_p_zzz"_h:
    353     case "mad_z_p_zzz"_h:
    354     case "mla_z_p_zzz"_h:
    355     case "mls_z_p_zzz"_h:
    356     case "msb_z_p_zzz"_h:
    357       return (movprfx_is_unpredicated || (pg_matches_low8 && vform_matches)) &&
    358              zd_isnt_zm && zd_isnt_zn && zd_matches;
    359 
    360     case "abs_z_p_z"_h:
    361     case "add_z_p_zz"_h:
    362     case "and_z_p_zz"_h:
    363     case "asr_z_p_zw"_h:
    364     case "asr_z_p_zz"_h:
    365     case "asrr_z_p_zz"_h:
    366     case "bic_z_p_zz"_h:
    367     case "cls_z_p_z"_h:
    368     case "clz_z_p_z"_h:
    369     case "cnot_z_p_z"_h:
    370     case "cnt_z_p_z"_h:
    371     case "cpy_z_p_v"_h:
    372     case "eor_z_p_zz"_h:
    373     case "fabd_z_p_zz"_h:
    374     case "fabs_z_p_z"_h:
    375     case "fadd_z_p_zz"_h:
    376     case "fcadd_z_p_zz"_h:
    377     case "fdiv_z_p_zz"_h:
    378     case "fdivr_z_p_zz"_h:
    379     case "fmax_z_p_zz"_h:
    380     case "fmaxnm_z_p_zz"_h:
    381     case "fmin_z_p_zz"_h:
    382     case "fminnm_z_p_zz"_h:
    383     case "fmul_z_p_zz"_h:
    384     case "fmulx_z_p_zz"_h:
    385     case "fneg_z_p_z"_h:
    386     case "frecpx_z_p_z"_h:
    387     case "frinta_z_p_z"_h:
    388     case "frinti_z_p_z"_h:
    389     case "frintm_z_p_z"_h:
    390     case "frintn_z_p_z"_h:
    391     case "frintp_z_p_z"_h:
    392     case "frintx_z_p_z"_h:
    393     case "frintz_z_p_z"_h:
    394     case "fscale_z_p_zz"_h:
    395     case "fsqrt_z_p_z"_h:
    396     case "fsub_z_p_zz"_h:
    397     case "fsubr_z_p_zz"_h:
    398     case "lsl_z_p_zw"_h:
    399     case "lsl_z_p_zz"_h:
    400     case "lslr_z_p_zz"_h:
    401     case "lsr_z_p_zw"_h:
    402     case "lsr_z_p_zz"_h:
    403     case "lsrr_z_p_zz"_h:
    404     case "mul_z_p_zz"_h:
    405     case "neg_z_p_z"_h:
    406     case "not_z_p_z"_h:
    407     case "orr_z_p_zz"_h:
    408     case "rbit_z_p_z"_h:
    409     case "revb_z_z"_h:
    410     case "revh_z_z"_h:
    411     case "revw_z_z"_h:
    412     case "sabd_z_p_zz"_h:
    413     case "sadalp_z_p_z"_h:
    414     case "sdiv_z_p_zz"_h:
    415     case "sdivr_z_p_zz"_h:
    416     case "shadd_z_p_zz"_h:
    417     case "shsub_z_p_zz"_h:
    418     case "shsubr_z_p_zz"_h:
    419     case "smax_z_p_zz"_h:
    420     case "smin_z_p_zz"_h:
    421     case "smulh_z_p_zz"_h:
    422     case "sqabs_z_p_z"_h:
    423     case "sqadd_z_p_zz"_h:
    424     case "sqneg_z_p_z"_h:
    425     case "sqrshl_z_p_zz"_h:
    426     case "sqrshlr_z_p_zz"_h:
    427     case "sqshl_z_p_zz"_h:
    428     case "sqshlr_z_p_zz"_h:
    429     case "sqsub_z_p_zz"_h:
    430     case "sqsubr_z_p_zz"_h:
    431     case "srhadd_z_p_zz"_h:
    432     case "srshl_z_p_zz"_h:
    433     case "srshlr_z_p_zz"_h:
    434     case "sub_z_p_zz"_h:
    435     case "subr_z_p_zz"_h:
    436     case "suqadd_z_p_zz"_h:
    437     case "sxtb_z_p_z"_h:
    438     case "sxth_z_p_z"_h:
    439     case "sxtw_z_p_z"_h:
    440     case "uabd_z_p_zz"_h:
    441     case "uadalp_z_p_z"_h:
    442     case "udiv_z_p_zz"_h:
    443     case "udivr_z_p_zz"_h:
    444     case "uhadd_z_p_zz"_h:
    445     case "uhsub_z_p_zz"_h:
    446     case "uhsubr_z_p_zz"_h:
    447     case "umax_z_p_zz"_h:
    448     case "umin_z_p_zz"_h:
    449     case "umulh_z_p_zz"_h:
    450     case "uqadd_z_p_zz"_h:
    451     case "uqrshl_z_p_zz"_h:
    452     case "uqrshlr_z_p_zz"_h:
    453     case "uqshl_z_p_zz"_h:
    454     case "uqshlr_z_p_zz"_h:
    455     case "uqsub_z_p_zz"_h:
    456     case "uqsubr_z_p_zz"_h:
    457     case "urecpe_z_p_z"_h:
    458     case "urhadd_z_p_zz"_h:
    459     case "urshl_z_p_zz"_h:
    460     case "urshlr_z_p_zz"_h:
    461     case "ursqrte_z_p_z"_h:
    462     case "usqadd_z_p_zz"_h:
    463     case "uxtb_z_p_z"_h:
    464     case "uxth_z_p_z"_h:
    465     case "uxtw_z_p_z"_h:
    466       return (movprfx_is_unpredicated || (pg_matches_low8 && vform_matches)) &&
    467              zd_isnt_zn && zd_matches;
    468 
    469     case "cpy_z_p_r"_h:
    470     case "fadd_z_p_zs"_h:
    471     case "fmax_z_p_zs"_h:
    472     case "fmaxnm_z_p_zs"_h:
    473     case "fmin_z_p_zs"_h:
    474     case "fminnm_z_p_zs"_h:
    475     case "fmul_z_p_zs"_h:
    476     case "fsub_z_p_zs"_h:
    477     case "fsubr_z_p_zs"_h:
    478       return (movprfx_is_unpredicated || (pg_matches_low8 && vform_matches)) &&
    479              zd_matches;
    480     default:
    481       return false;
    482   }
    483 }  // NOLINT(readability/fn_size)
    484 
    485 bool Instruction::IsLoad() const {
    486   if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
    487     return false;
    488   }
    489 
    490   if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
    491     return Mask(LoadStorePairLBit) != 0;
    492   } else {
    493     LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask));
    494     switch (op) {
    495       case LDRB_w:
    496       case LDRH_w:
    497       case LDR_w:
    498       case LDR_x:
    499       case LDRSB_w:
    500       case LDRSB_x:
    501       case LDRSH_w:
    502       case LDRSH_x:
    503       case LDRSW_x:
    504       case LDR_b:
    505       case LDR_h:
    506       case LDR_s:
    507       case LDR_d:
    508       case LDR_q:
    509         return true;
    510       default:
    511         return false;
    512     }
    513   }
    514 }
    515 
    516 
    517 bool Instruction::IsStore() const {
    518   if (Mask(LoadStoreAnyFMask) != LoadStoreAnyFixed) {
    519     return false;
    520   }
    521 
    522   if (Mask(LoadStorePairAnyFMask) == LoadStorePairAnyFixed) {
    523     return Mask(LoadStorePairLBit) == 0;
    524   } else {
    525     LoadStoreOp op = static_cast<LoadStoreOp>(Mask(LoadStoreMask));
    526     switch (op) {
    527       case STRB_w:
    528       case STRH_w:
    529       case STR_w:
    530       case STR_x:
    531       case STR_b:
    532       case STR_h:
    533       case STR_s:
    534       case STR_d:
    535       case STR_q:
    536         return true;
    537       default:
    538         return false;
    539     }
    540   }
    541 }
    542 
    543 
    544 std::pair<int, int> Instruction::GetSVEPermuteIndexAndLaneSizeLog2() const {
    545   uint32_t imm_2 = ExtractBits<0x00C00000>();
    546   uint32_t tsz_5 = ExtractBits<0x001F0000>();
    547   uint32_t imm_7 = (imm_2 << 5) | tsz_5;
    548   int lane_size_in_byte_log_2 = std::min(CountTrailingZeros(tsz_5), 5);
    549   int index = ExtractUnsignedBitfield32(6, lane_size_in_byte_log_2 + 1, imm_7);
    550   return std::make_pair(index, lane_size_in_byte_log_2);
    551 }
    552 
    553 // Get the register and index for SVE indexed multiplies encoded in the forms:
    554 //  .h : Zm = <18:16>, index = <22><20:19>
    555 //  .s : Zm = <18:16>, index = <20:19>
    556 //  .d : Zm = <19:16>, index = <20>
    557 std::pair<int, int> Instruction::GetSVEMulZmAndIndex() const {
    558   int reg_code = GetRmLow16();
    559   int index = ExtractBits(20, 19);
    560 
    561   // For .h, index uses bit zero of the size field, so kFormatVnB below implies
    562   // half-word lane, with most-significant bit of the index zero.
    563   switch (GetSVEVectorFormat()) {
    564     case kFormatVnD:
    565       index >>= 1;  // Only bit 20 in the index for D lanes.
    566       break;
    567     case kFormatVnH:
    568       index += 4;  // Bit 22 is the top bit of index.
    569       VIXL_FALLTHROUGH();
    570     case kFormatVnB:
    571     case kFormatVnS:
    572       reg_code &= 7;  // Three bits used for the register.
    573       break;
    574     default:
    575       VIXL_UNIMPLEMENTED();
    576       break;
    577   }
    578   return std::make_pair(reg_code, index);
    579 }
    580 
    581 // Get the register and index for SVE indexed long multiplies encoded in the
    582 // forms:
    583 //  .h : Zm = <18:16>, index = <20:19><11>
    584 //  .s : Zm = <19:16>, index = <20><11>
    585 std::pair<int, int> Instruction::GetSVEMulLongZmAndIndex() const {
    586   int reg_code = GetRmLow16();
    587   int index = ExtractBit(11);
    588 
    589   // For long multiplies, the SVE size field <23:22> encodes the destination
    590   // element size. The source element size is half the width.
    591   switch (GetSVEVectorFormat()) {
    592     case kFormatVnS:
    593       reg_code &= 7;
    594       index |= ExtractBits(20, 19) << 1;
    595       break;
    596     case kFormatVnD:
    597       index |= ExtractBit(20) << 1;
    598       break;
    599     default:
    600       VIXL_UNIMPLEMENTED();
    601       break;
    602   }
    603   return std::make_pair(reg_code, index);
    604 }
    605 
    606 // Logical immediates can't encode zero, so a return value of zero is used to
    607 // indicate a failure case. Specifically, where the constraints on imm_s are
    608 // not met.
    609 uint64_t Instruction::GetImmLogical() const {
    610   unsigned reg_size = GetSixtyFourBits() ? kXRegSize : kWRegSize;
    611   int32_t n = GetBitN();
    612   int32_t imm_s = GetImmSetBits();
    613   int32_t imm_r = GetImmRotate();
    614   return DecodeImmBitMask(n, imm_s, imm_r, reg_size);
    615 }
    616 
    617 // Logical immediates can't encode zero, so a return value of zero is used to
    618 // indicate a failure case. Specifically, where the constraints on imm_s are
    619 // not met.
    620 uint64_t Instruction::GetSVEImmLogical() const {
    621   int n = GetSVEBitN();
    622   int imm_s = GetSVEImmSetBits();
    623   int imm_r = GetSVEImmRotate();
    624   int lane_size_in_bytes_log2 = GetSVEBitwiseImmLaneSizeInBytesLog2();
    625   switch (lane_size_in_bytes_log2) {
    626     case kDRegSizeInBytesLog2:
    627     case kSRegSizeInBytesLog2:
    628     case kHRegSizeInBytesLog2:
    629     case kBRegSizeInBytesLog2: {
    630       int lane_size_in_bits = 1 << (lane_size_in_bytes_log2 + 3);
    631       return DecodeImmBitMask(n, imm_s, imm_r, lane_size_in_bits);
    632     }
    633     default:
    634       return 0;
    635   }
    636 }
    637 
    638 std::pair<int, int> Instruction::GetSVEImmShiftAndLaneSizeLog2(
    639     bool is_predicated) const {
    640   Instr tsize =
    641       is_predicated ? ExtractBits<0x00C00300>() : ExtractBits<0x00D80000>();
    642   Instr imm_3 =
    643       is_predicated ? ExtractBits<0x000000E0>() : ExtractBits<0x00070000>();
    644   if (tsize == 0) {
    645     // The bit field `tsize` means undefined if it is zero, so return a
    646     // convenience value kWMinInt to indicate a failure case.
    647     return std::make_pair(kWMinInt, kWMinInt);
    648   }
    649 
    650   int lane_size_in_bytes_log_2 = 32 - CountLeadingZeros(tsize, 32) - 1;
    651   int esize = (1 << lane_size_in_bytes_log_2) * kBitsPerByte;
    652   int shift = (2 * esize) - ((tsize << 3) | imm_3);
    653   return std::make_pair(shift, lane_size_in_bytes_log_2);
    654 }
    655 
    656 int Instruction::GetSVEMsizeFromDtype(bool is_signed, int dtype_h_lsb) const {
    657   Instr dtype_h = ExtractBits(dtype_h_lsb + 1, dtype_h_lsb);
    658   if (is_signed) {
    659     dtype_h = dtype_h ^ 0x3;
    660   }
    661   return dtype_h;
    662 }
    663 
    664 int Instruction::GetSVEEsizeFromDtype(bool is_signed, int dtype_l_lsb) const {
    665   Instr dtype_l = ExtractBits(dtype_l_lsb + 1, dtype_l_lsb);
    666   if (is_signed) {
    667     dtype_l = dtype_l ^ 0x3;
    668   }
    669   return dtype_l;
    670 }
    671 
    672 int Instruction::GetSVEBitwiseImmLaneSizeInBytesLog2() const {
    673   int n = GetSVEBitN();
    674   int imm_s = GetSVEImmSetBits();
    675   unsigned type_bitset =
    676       (n << SVEImmSetBits_width) | (~imm_s & GetUintMask(SVEImmSetBits_width));
    677 
    678   // An lane size is constructed from the n and imm_s bits according to
    679   // the following table:
    680   //
    681   // N   imms   size
    682   // 0  0xxxxx   32
    683   // 0  10xxxx   16
    684   // 0  110xxx    8
    685   // 0  1110xx    8
    686   // 0  11110x    8
    687   // 1  xxxxxx   64
    688 
    689   if (type_bitset == 0) {
    690     // Bail out early since `HighestSetBitPosition` doesn't accept zero
    691     // value input.
    692     return -1;
    693   }
    694 
    695   switch (HighestSetBitPosition(type_bitset)) {
    696     case 6:
    697       return kDRegSizeInBytesLog2;
    698     case 5:
    699       return kSRegSizeInBytesLog2;
    700     case 4:
    701       return kHRegSizeInBytesLog2;
    702     case 3:
    703     case 2:
    704     case 1:
    705       return kBRegSizeInBytesLog2;
    706     default:
    707       // RESERVED encoding.
    708       return -1;
    709   }
    710 }
    711 
    712 int Instruction::GetSVEExtractImmediate() const {
    713   const int imm8h_mask = 0x001F0000;
    714   const int imm8l_mask = 0x00001C00;
    715   return ExtractBits<imm8h_mask | imm8l_mask>();
    716 }
    717 
    718 uint64_t Instruction::DecodeImmBitMask(int32_t n,
    719                                        int32_t imm_s,
    720                                        int32_t imm_r,
    721                                        int32_t size) const {
    722   // An integer is constructed from the n, imm_s and imm_r bits according to
    723   // the following table:
    724   //
    725   //  N   imms    immr    size        S             R
    726   //  1  ssssss  rrrrrr    64    UInt(ssssss)  UInt(rrrrrr)
    727   //  0  0sssss  xrrrrr    32    UInt(sssss)   UInt(rrrrr)
    728   //  0  10ssss  xxrrrr    16    UInt(ssss)    UInt(rrrr)
    729   //  0  110sss  xxxrrr     8    UInt(sss)     UInt(rrr)
    730   //  0  1110ss  xxxxrr     4    UInt(ss)      UInt(rr)
    731   //  0  11110s  xxxxxr     2    UInt(s)       UInt(r)
    732   // (s bits must not be all set)
    733   //
    734   // A pattern is constructed of size bits, where the least significant S+1
    735   // bits are set. The pattern is rotated right by R, and repeated across a
    736   // 32 or 64-bit value, depending on destination register width.
    737   //
    738 
    739   if (n == 1) {
    740     if (imm_s == 0x3f) {
    741       return 0;
    742     }
    743     uint64_t bits = (UINT64_C(1) << (imm_s + 1)) - 1;
    744     return RotateRight(bits, imm_r, 64);
    745   } else {
    746     if ((imm_s >> 1) == 0x1f) {
    747       return 0;
    748     }
    749     for (int width = 0x20; width >= 0x2; width >>= 1) {
    750       if ((imm_s & width) == 0) {
    751         int mask = width - 1;
    752         if ((imm_s & mask) == mask) {
    753           return 0;
    754         }
    755         uint64_t bits = (UINT64_C(1) << ((imm_s & mask) + 1)) - 1;
    756         return RepeatBitsAcrossReg(size,
    757                                    RotateRight(bits, imm_r & mask, width),
    758                                    width);
    759       }
    760     }
    761   }
    762   VIXL_UNREACHABLE();
    763   return 0;
    764 }
    765 
    766 
    767 uint32_t Instruction::GetImmNEONabcdefgh() const {
    768   return GetImmNEONabc() << 5 | GetImmNEONdefgh();
    769 }
    770 
    771 
    772 Float16 Instruction::Imm8ToFloat16(uint32_t imm8) {
    773   // Imm8: abcdefgh (8 bits)
    774   // Half: aBbb.cdef.gh00.0000 (16 bits)
    775   // where B is b ^ 1
    776   uint32_t bits = imm8;
    777   uint16_t bit7 = (bits >> 7) & 0x1;
    778   uint16_t bit6 = (bits >> 6) & 0x1;
    779   uint16_t bit5_to_0 = bits & 0x3f;
    780   uint16_t result = (bit7 << 15) | ((4 - bit6) << 12) | (bit5_to_0 << 6);
    781   return RawbitsToFloat16(result);
    782 }
    783 
    784 
    785 float Instruction::Imm8ToFP32(uint32_t imm8) {
    786   // Imm8: abcdefgh (8 bits)
    787   // Single: aBbb.bbbc.defg.h000.0000.0000.0000.0000 (32 bits)
    788   // where B is b ^ 1
    789   uint32_t bits = imm8;
    790   uint32_t bit7 = (bits >> 7) & 0x1;
    791   uint32_t bit6 = (bits >> 6) & 0x1;
    792   uint32_t bit5_to_0 = bits & 0x3f;
    793   uint32_t result = (bit7 << 31) | ((32 - bit6) << 25) | (bit5_to_0 << 19);
    794 
    795   return RawbitsToFloat(result);
    796 }
    797 
    798 
    799 Float16 Instruction::GetImmFP16() const { return Imm8ToFloat16(GetImmFP()); }
    800 
    801 
    802 float Instruction::GetImmFP32() const { return Imm8ToFP32(GetImmFP()); }
    803 
    804 
    805 double Instruction::Imm8ToFP64(uint32_t imm8) {
    806   // Imm8: abcdefgh (8 bits)
    807   // Double: aBbb.bbbb.bbcd.efgh.0000.0000.0000.0000
    808   //         0000.0000.0000.0000.0000.0000.0000.0000 (64 bits)
    809   // where B is b ^ 1
    810   uint32_t bits = imm8;
    811   uint64_t bit7 = (bits >> 7) & 0x1;
    812   uint64_t bit6 = (bits >> 6) & 0x1;
    813   uint64_t bit5_to_0 = bits & 0x3f;
    814   uint64_t result = (bit7 << 63) | ((256 - bit6) << 54) | (bit5_to_0 << 48);
    815 
    816   return RawbitsToDouble(result);
    817 }
    818 
    819 
    820 double Instruction::GetImmFP64() const { return Imm8ToFP64(GetImmFP()); }
    821 
    822 
    823 Float16 Instruction::GetImmNEONFP16() const {
    824   return Imm8ToFloat16(GetImmNEONabcdefgh());
    825 }
    826 
    827 
    828 float Instruction::GetImmNEONFP32() const {
    829   return Imm8ToFP32(GetImmNEONabcdefgh());
    830 }
    831 
    832 
    833 double Instruction::GetImmNEONFP64() const {
    834   return Imm8ToFP64(GetImmNEONabcdefgh());
    835 }
    836 
    837 
    838 unsigned CalcLSDataSize(LoadStoreOp op) {
    839   VIXL_ASSERT((LSSize_offset + LSSize_width) == (kInstructionSize * 8));
    840   unsigned size = static_cast<Instr>(op) >> LSSize_offset;
    841   if ((op & LSVector_mask) != 0) {
    842     // Vector register memory operations encode the access size in the "size"
    843     // and "opc" fields.
    844     if ((size == 0) && ((op & LSOpc_mask) >> LSOpc_offset) >= 2) {
    845       size = kQRegSizeInBytesLog2;
    846     }
    847   }
    848   return size;
    849 }
    850 
    851 
    852 unsigned CalcLSPairDataSize(LoadStorePairOp op) {
    853   VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
    854   VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
    855   switch (op) {
    856     case STP_q:
    857     case LDP_q:
    858       return kQRegSizeInBytesLog2;
    859     case STP_x:
    860     case LDP_x:
    861     case STP_d:
    862     case LDP_d:
    863       return kXRegSizeInBytesLog2;
    864     default:
    865       return kWRegSizeInBytesLog2;
    866   }
    867 }
    868 
    869 
    870 int Instruction::GetImmBranchRangeBitwidth(ImmBranchType branch_type) {
    871   switch (branch_type) {
    872     case UncondBranchType:
    873       return ImmUncondBranch_width;
    874     case CondBranchType:
    875       return ImmCondBranch_width;
    876     case CompareBranchType:
    877       return ImmCmpBranch_width;
    878     case TestBranchType:
    879       return ImmTestBranch_width;
    880     default:
    881       VIXL_UNREACHABLE();
    882       return 0;
    883   }
    884 }
    885 
    886 
    887 int32_t Instruction::GetImmBranchForwardRange(ImmBranchType branch_type) {
    888   int32_t encoded_max = 1 << (GetImmBranchRangeBitwidth(branch_type) - 1);
    889   return encoded_max * kInstructionSize;
    890 }
    891 
    892 
    893 bool Instruction::IsValidImmPCOffset(ImmBranchType branch_type,
    894                                      int64_t offset) {
    895   return IsIntN(GetImmBranchRangeBitwidth(branch_type), offset);
    896 }
    897 
    898 
    899 const Instruction* Instruction::GetImmPCOffsetTarget() const {
    900   const Instruction* base = this;
    901   ptrdiff_t offset;
    902   if (IsPCRelAddressing()) {
    903     // ADR and ADRP.
    904     offset = GetImmPCRel();
    905     if (Mask(PCRelAddressingMask) == ADRP) {
    906       base = AlignDown(base, kPageSize);
    907       offset *= kPageSize;
    908     } else {
    909       VIXL_ASSERT(Mask(PCRelAddressingMask) == ADR);
    910     }
    911   } else {
    912     // All PC-relative branches.
    913     VIXL_ASSERT(GetBranchType() != UnknownBranchType);
    914     // Relative branch offsets are instruction-size-aligned.
    915     offset = GetImmBranch() * static_cast<int>(kInstructionSize);
    916   }
    917   return base + offset;
    918 }
    919 
    920 
    921 int Instruction::GetImmBranch() const {
    922   switch (GetBranchType()) {
    923     case CondBranchType:
    924       return GetImmCondBranch();
    925     case UncondBranchType:
    926       return GetImmUncondBranch();
    927     case CompareBranchType:
    928       return GetImmCmpBranch();
    929     case TestBranchType:
    930       return GetImmTestBranch();
    931     default:
    932       VIXL_UNREACHABLE();
    933   }
    934   return 0;
    935 }
    936 
    937 
    938 void Instruction::SetImmPCOffsetTarget(const Instruction* target) {
    939   if (IsPCRelAddressing()) {
    940     SetPCRelImmTarget(target);
    941   } else {
    942     SetBranchImmTarget(target);
    943   }
    944 }
    945 
    946 
    947 void Instruction::SetPCRelImmTarget(const Instruction* target) {
    948   ptrdiff_t imm21;
    949   if ((Mask(PCRelAddressingMask) == ADR)) {
    950     imm21 = target - this;
    951   } else {
    952     VIXL_ASSERT(Mask(PCRelAddressingMask) == ADRP);
    953     uintptr_t this_page = reinterpret_cast<uintptr_t>(this) / kPageSize;
    954     uintptr_t target_page = reinterpret_cast<uintptr_t>(target) / kPageSize;
    955     imm21 = target_page - this_page;
    956   }
    957   Instr imm = Assembler::ImmPCRelAddress(static_cast<int32_t>(imm21));
    958 
    959   SetInstructionBits(Mask(~ImmPCRel_mask) | imm);
    960 }
    961 
    962 
    963 void Instruction::SetBranchImmTarget(const Instruction* target) {
    964   VIXL_ASSERT(((target - this) & 3) == 0);
    965   Instr branch_imm = 0;
    966   uint32_t imm_mask = 0;
    967   int offset = static_cast<int>((target - this) >> kInstructionSizeLog2);
    968   switch (GetBranchType()) {
    969     case CondBranchType: {
    970       branch_imm = Assembler::ImmCondBranch(offset);
    971       imm_mask = ImmCondBranch_mask;
    972       break;
    973     }
    974     case UncondBranchType: {
    975       branch_imm = Assembler::ImmUncondBranch(offset);
    976       imm_mask = ImmUncondBranch_mask;
    977       break;
    978     }
    979     case CompareBranchType: {
    980       branch_imm = Assembler::ImmCmpBranch(offset);
    981       imm_mask = ImmCmpBranch_mask;
    982       break;
    983     }
    984     case TestBranchType: {
    985       branch_imm = Assembler::ImmTestBranch(offset);
    986       imm_mask = ImmTestBranch_mask;
    987       break;
    988     }
    989     default:
    990       VIXL_UNREACHABLE();
    991   }
    992   SetInstructionBits(Mask(~imm_mask) | branch_imm);
    993 }
    994 
    995 
    996 void Instruction::SetImmLLiteral(const Instruction* source) {
    997   VIXL_ASSERT(IsWordAligned(source));
    998   ptrdiff_t offset = (source - this) >> kLiteralEntrySizeLog2;
    999   Instr imm = Assembler::ImmLLiteral(static_cast<int>(offset));
   1000   Instr mask = ImmLLiteral_mask;
   1001 
   1002   SetInstructionBits(Mask(~mask) | imm);
   1003 }
   1004 
   1005 
   1006 VectorFormat VectorFormatHalfWidth(VectorFormat vform) {
   1007   switch (vform) {
   1008     case kFormat8H:
   1009       return kFormat8B;
   1010     case kFormat4S:
   1011       return kFormat4H;
   1012     case kFormat2D:
   1013       return kFormat2S;
   1014     case kFormat1Q:
   1015       return kFormat1D;
   1016     case kFormatH:
   1017       return kFormatB;
   1018     case kFormatS:
   1019       return kFormatH;
   1020     case kFormatD:
   1021       return kFormatS;
   1022     case kFormatVnH:
   1023       return kFormatVnB;
   1024     case kFormatVnS:
   1025       return kFormatVnH;
   1026     case kFormatVnD:
   1027       return kFormatVnS;
   1028     default:
   1029       VIXL_UNREACHABLE();
   1030       return kFormatUndefined;
   1031   }
   1032 }
   1033 
   1034 
   1035 VectorFormat VectorFormatDoubleWidth(VectorFormat vform) {
   1036   switch (vform) {
   1037     case kFormat8B:
   1038       return kFormat8H;
   1039     case kFormat4H:
   1040       return kFormat4S;
   1041     case kFormat2S:
   1042       return kFormat2D;
   1043     case kFormatB:
   1044       return kFormatH;
   1045     case kFormatH:
   1046       return kFormatS;
   1047     case kFormatS:
   1048       return kFormatD;
   1049     case kFormatVnB:
   1050       return kFormatVnH;
   1051     case kFormatVnH:
   1052       return kFormatVnS;
   1053     case kFormatVnS:
   1054       return kFormatVnD;
   1055     default:
   1056       VIXL_UNREACHABLE();
   1057       return kFormatUndefined;
   1058   }
   1059 }
   1060 
   1061 
   1062 VectorFormat VectorFormatFillQ(VectorFormat vform) {
   1063   switch (vform) {
   1064     case kFormatB:
   1065     case kFormat8B:
   1066     case kFormat16B:
   1067       return kFormat16B;
   1068     case kFormatH:
   1069     case kFormat4H:
   1070     case kFormat8H:
   1071       return kFormat8H;
   1072     case kFormatS:
   1073     case kFormat2S:
   1074     case kFormat4S:
   1075       return kFormat4S;
   1076     case kFormatD:
   1077     case kFormat1D:
   1078     case kFormat2D:
   1079       return kFormat2D;
   1080     default:
   1081       VIXL_UNREACHABLE();
   1082       return kFormatUndefined;
   1083   }
   1084 }
   1085 
   1086 VectorFormat VectorFormatHalfWidthDoubleLanes(VectorFormat vform) {
   1087   switch (vform) {
   1088     case kFormat4H:
   1089       return kFormat8B;
   1090     case kFormat8H:
   1091       return kFormat16B;
   1092     case kFormat2S:
   1093       return kFormat4H;
   1094     case kFormat4S:
   1095       return kFormat8H;
   1096     case kFormat1D:
   1097       return kFormat2S;
   1098     case kFormat2D:
   1099       return kFormat4S;
   1100     case kFormat1Q:
   1101       return kFormat2D;
   1102     case kFormatVnH:
   1103       return kFormatVnB;
   1104     case kFormatVnS:
   1105       return kFormatVnH;
   1106     case kFormatVnD:
   1107       return kFormatVnS;
   1108     default:
   1109       VIXL_UNREACHABLE();
   1110       return kFormatUndefined;
   1111   }
   1112 }
   1113 
   1114 VectorFormat VectorFormatDoubleLanes(VectorFormat vform) {
   1115   VIXL_ASSERT(vform == kFormat8B || vform == kFormat4H || vform == kFormat2S);
   1116   switch (vform) {
   1117     case kFormat8B:
   1118       return kFormat16B;
   1119     case kFormat4H:
   1120       return kFormat8H;
   1121     case kFormat2S:
   1122       return kFormat4S;
   1123     default:
   1124       VIXL_UNREACHABLE();
   1125       return kFormatUndefined;
   1126   }
   1127 }
   1128 
   1129 
   1130 VectorFormat VectorFormatHalfLanes(VectorFormat vform) {
   1131   VIXL_ASSERT(vform == kFormat16B || vform == kFormat8H || vform == kFormat4S);
   1132   switch (vform) {
   1133     case kFormat16B:
   1134       return kFormat8B;
   1135     case kFormat8H:
   1136       return kFormat4H;
   1137     case kFormat4S:
   1138       return kFormat2S;
   1139     default:
   1140       VIXL_UNREACHABLE();
   1141       return kFormatUndefined;
   1142   }
   1143 }
   1144 
   1145 
   1146 VectorFormat ScalarFormatFromLaneSize(int lane_size_in_bits) {
   1147   switch (lane_size_in_bits) {
   1148     case 8:
   1149       return kFormatB;
   1150     case 16:
   1151       return kFormatH;
   1152     case 32:
   1153       return kFormatS;
   1154     case 64:
   1155       return kFormatD;
   1156     default:
   1157       VIXL_UNREACHABLE();
   1158       return kFormatUndefined;
   1159   }
   1160 }
   1161 
   1162 
   1163 bool IsSVEFormat(VectorFormat vform) {
   1164   switch (vform) {
   1165     case kFormatVnB:
   1166     case kFormatVnH:
   1167     case kFormatVnS:
   1168     case kFormatVnD:
   1169     case kFormatVnQ:
   1170     case kFormatVnO:
   1171       return true;
   1172     default:
   1173       return false;
   1174   }
   1175 }
   1176 
   1177 
   1178 VectorFormat SVEFormatFromLaneSizeInBytes(int lane_size_in_bytes) {
   1179   switch (lane_size_in_bytes) {
   1180     case 1:
   1181       return kFormatVnB;
   1182     case 2:
   1183       return kFormatVnH;
   1184     case 4:
   1185       return kFormatVnS;
   1186     case 8:
   1187       return kFormatVnD;
   1188     case 16:
   1189       return kFormatVnQ;
   1190     default:
   1191       VIXL_UNREACHABLE();
   1192       return kFormatUndefined;
   1193   }
   1194 }
   1195 
   1196 
   1197 VectorFormat SVEFormatFromLaneSizeInBits(int lane_size_in_bits) {
   1198   switch (lane_size_in_bits) {
   1199     case 8:
   1200     case 16:
   1201     case 32:
   1202     case 64:
   1203     case 128:
   1204       return SVEFormatFromLaneSizeInBytes(lane_size_in_bits / kBitsPerByte);
   1205     default:
   1206       VIXL_UNREACHABLE();
   1207       return kFormatUndefined;
   1208   }
   1209 }
   1210 
   1211 
   1212 VectorFormat SVEFormatFromLaneSizeInBytesLog2(int lane_size_in_bytes_log2) {
   1213   switch (lane_size_in_bytes_log2) {
   1214     case 0:
   1215     case 1:
   1216     case 2:
   1217     case 3:
   1218     case 4:
   1219       return SVEFormatFromLaneSizeInBytes(1 << lane_size_in_bytes_log2);
   1220     default:
   1221       VIXL_UNREACHABLE();
   1222       return kFormatUndefined;
   1223   }
   1224 }
   1225 
   1226 
   1227 VectorFormat ScalarFormatFromFormat(VectorFormat vform) {
   1228   return ScalarFormatFromLaneSize(LaneSizeInBitsFromFormat(vform));
   1229 }
   1230 
   1231 
   1232 unsigned RegisterSizeInBitsFromFormat(VectorFormat vform) {
   1233   VIXL_ASSERT(vform != kFormatUndefined);
   1234   VIXL_ASSERT(!IsSVEFormat(vform));
   1235   switch (vform) {
   1236     case kFormatB:
   1237       return kBRegSize;
   1238     case kFormatH:
   1239       return kHRegSize;
   1240     case kFormatS:
   1241     case kFormat2H:
   1242       return kSRegSize;
   1243     case kFormatD:
   1244     case kFormat8B:
   1245     case kFormat4H:
   1246     case kFormat2S:
   1247     case kFormat1D:
   1248       return kDRegSize;
   1249     case kFormat16B:
   1250     case kFormat8H:
   1251     case kFormat4S:
   1252     case kFormat2D:
   1253     case kFormat1Q:
   1254       return kQRegSize;
   1255     default:
   1256       VIXL_UNREACHABLE();
   1257       return 0;
   1258   }
   1259 }
   1260 
   1261 
   1262 unsigned RegisterSizeInBytesFromFormat(VectorFormat vform) {
   1263   return RegisterSizeInBitsFromFormat(vform) / 8;
   1264 }
   1265 
   1266 
   1267 unsigned LaneSizeInBitsFromFormat(VectorFormat vform) {
   1268   VIXL_ASSERT(vform != kFormatUndefined);
   1269   switch (vform) {
   1270     case kFormatB:
   1271     case kFormat8B:
   1272     case kFormat16B:
   1273     case kFormatVnB:
   1274       return 8;
   1275     case kFormatH:
   1276     case kFormat2H:
   1277     case kFormat4H:
   1278     case kFormat8H:
   1279     case kFormatVnH:
   1280       return 16;
   1281     case kFormatS:
   1282     case kFormat2S:
   1283     case kFormat4S:
   1284     case kFormatVnS:
   1285       return 32;
   1286     case kFormatD:
   1287     case kFormat1D:
   1288     case kFormat2D:
   1289     case kFormatVnD:
   1290       return 64;
   1291     case kFormat1Q:
   1292     case kFormatVnQ:
   1293       return 128;
   1294     case kFormatVnO:
   1295       return 256;
   1296     default:
   1297       VIXL_UNREACHABLE();
   1298       return 0;
   1299   }
   1300 }
   1301 
   1302 
   1303 int LaneSizeInBytesFromFormat(VectorFormat vform) {
   1304   return LaneSizeInBitsFromFormat(vform) / 8;
   1305 }
   1306 
   1307 
   1308 int LaneSizeInBytesLog2FromFormat(VectorFormat vform) {
   1309   VIXL_ASSERT(vform != kFormatUndefined);
   1310   switch (vform) {
   1311     case kFormatB:
   1312     case kFormat8B:
   1313     case kFormat16B:
   1314     case kFormatVnB:
   1315       return 0;
   1316     case kFormatH:
   1317     case kFormat2H:
   1318     case kFormat4H:
   1319     case kFormat8H:
   1320     case kFormatVnH:
   1321       return 1;
   1322     case kFormatS:
   1323     case kFormat2S:
   1324     case kFormat4S:
   1325     case kFormatVnS:
   1326       return 2;
   1327     case kFormatD:
   1328     case kFormat1D:
   1329     case kFormat2D:
   1330     case kFormatVnD:
   1331       return 3;
   1332     case kFormatVnQ:
   1333       return 4;
   1334     default:
   1335       VIXL_UNREACHABLE();
   1336       return 0;
   1337   }
   1338 }
   1339 
   1340 
   1341 int LaneCountFromFormat(VectorFormat vform) {
   1342   VIXL_ASSERT(vform != kFormatUndefined);
   1343   switch (vform) {
   1344     case kFormat16B:
   1345       return 16;
   1346     case kFormat8B:
   1347     case kFormat8H:
   1348       return 8;
   1349     case kFormat4H:
   1350     case kFormat4S:
   1351       return 4;
   1352     case kFormat2H:
   1353     case kFormat2S:
   1354     case kFormat2D:
   1355       return 2;
   1356     case kFormat1D:
   1357     case kFormat1Q:
   1358     case kFormatB:
   1359     case kFormatH:
   1360     case kFormatS:
   1361     case kFormatD:
   1362       return 1;
   1363     default:
   1364       VIXL_UNREACHABLE();
   1365       return 0;
   1366   }
   1367 }
   1368 
   1369 
   1370 int MaxLaneCountFromFormat(VectorFormat vform) {
   1371   VIXL_ASSERT(vform != kFormatUndefined);
   1372   switch (vform) {
   1373     case kFormatB:
   1374     case kFormat8B:
   1375     case kFormat16B:
   1376       return 16;
   1377     case kFormatH:
   1378     case kFormat4H:
   1379     case kFormat8H:
   1380       return 8;
   1381     case kFormatS:
   1382     case kFormat2S:
   1383     case kFormat4S:
   1384       return 4;
   1385     case kFormatD:
   1386     case kFormat1D:
   1387     case kFormat2D:
   1388       return 2;
   1389     default:
   1390       VIXL_UNREACHABLE();
   1391       return 0;
   1392   }
   1393 }
   1394 
   1395 
   1396 // Does 'vform' indicate a vector format or a scalar format?
   1397 bool IsVectorFormat(VectorFormat vform) {
   1398   VIXL_ASSERT(vform != kFormatUndefined);
   1399   switch (vform) {
   1400     case kFormatB:
   1401     case kFormatH:
   1402     case kFormatS:
   1403     case kFormatD:
   1404       return false;
   1405     default:
   1406       return true;
   1407   }
   1408 }
   1409 
   1410 
   1411 int64_t MaxIntFromFormat(VectorFormat vform) {
   1412   int lane_size = LaneSizeInBitsFromFormat(vform);
   1413   return static_cast<int64_t>(GetUintMask(lane_size) >> 1);
   1414 }
   1415 
   1416 
   1417 int64_t MinIntFromFormat(VectorFormat vform) {
   1418   return -MaxIntFromFormat(vform) - 1;
   1419 }
   1420 
   1421 
   1422 uint64_t MaxUintFromFormat(VectorFormat vform) {
   1423   return GetUintMask(LaneSizeInBitsFromFormat(vform));
   1424 }
   1425 
   1426 }  // namespace aarch64
   1427 }  // namespace vixl