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