Path: blob/master/dep/vixl/src/aarch64/assembler-sve-aarch64.cc
4261 views
// Copyright 2019, 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 "assembler-aarch64.h"2728namespace vixl {29namespace aarch64 {3031void Assembler::ResolveSVEImm8Shift(int* imm8, int* shift) {32if (*shift < 0) {33VIXL_ASSERT(*shift == -1);34// Derive the shift amount from the immediate.35if (IsInt8(*imm8)) {36*shift = 0;37} else if ((*imm8 % 256) == 0) {38*imm8 /= 256;39*shift = 8;40}41}4243VIXL_ASSERT(IsInt8(*imm8));44VIXL_ASSERT((*shift == 0) || (*shift == 8));45}4647// SVEAddressGeneration.4849void Assembler::adr(const ZRegister& zd, const SVEMemOperand& addr) {50VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));51VIXL_ASSERT(addr.IsVectorPlusVector());52VIXL_ASSERT(53AreSameLaneSize(zd, addr.GetVectorBase(), addr.GetVectorOffset()));5455int lane_size = zd.GetLaneSizeInBits();56VIXL_ASSERT((lane_size == kSRegSize) || (lane_size == kDRegSize));5758int shift_amount = addr.GetShiftAmount();59VIXL_ASSERT((shift_amount >= 0) && (shift_amount <= 3));6061Instr op = 0xffffffff;62Instr msz = shift_amount << 10;63SVEOffsetModifier mod = addr.GetOffsetModifier();64switch (mod) {65case SVE_UXTW:66VIXL_ASSERT(lane_size == kDRegSize);67op = ADR_z_az_d_u32_scaled;68break;69case SVE_SXTW:70VIXL_ASSERT(lane_size == kDRegSize);71op = ADR_z_az_d_s32_scaled;72break;73case SVE_LSL:74case NO_SVE_OFFSET_MODIFIER:75op = (lane_size == kSRegSize) ? ADR_z_az_s_same_scaled76: ADR_z_az_d_same_scaled;77break;78default:79VIXL_UNIMPLEMENTED();80}81Emit(op | msz | Rd(zd) | Rn(addr.GetVectorBase()) |82Rm(addr.GetVectorOffset()));83}8485void Assembler::SVELogicalImmediate(const ZRegister& zdn,86uint64_t imm,87Instr op) {88unsigned bit_n, imm_s, imm_r;89unsigned lane_size = zdn.GetLaneSizeInBits();90// Check that the immediate can be encoded in the instruction.91if (IsImmLogical(imm, lane_size, &bit_n, &imm_s, &imm_r)) {92Emit(op | Rd(zdn) | SVEBitN(bit_n) | SVEImmRotate(imm_r, lane_size) |93SVEImmSetBits(imm_s, lane_size));94} else {95VIXL_UNREACHABLE();96}97}9899void Assembler::and_(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {100USE(zn);101VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));102VIXL_ASSERT(zd.Is(zn));103SVELogicalImmediate(zd, imm, AND_z_zi);104}105106void Assembler::dupm(const ZRegister& zd, uint64_t imm) {107VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));108// DUPM_z_i is an SVEBroadcastBitmaskImmOp, but its encoding and constraints109// are similar enough to SVEBitwiseLogicalWithImm_UnpredicatedOp, that we can110// use the logical immediate encoder to get the correct behaviour.111SVELogicalImmediate(zd, imm, DUPM_z_i);112}113114void Assembler::eor(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {115USE(zn);116VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));117VIXL_ASSERT(zd.Is(zn));118SVELogicalImmediate(zd, imm, EOR_z_zi);119}120121void Assembler::orr(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {122USE(zn);123VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));124VIXL_ASSERT(zd.Is(zn));125SVELogicalImmediate(zd, imm, ORR_z_zi);126}127128// SVEBitwiseLogicalUnpredicated.129void Assembler::and_(const ZRegister& zd,130const ZRegister& zn,131const ZRegister& zm) {132VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));133VIXL_ASSERT(zd.IsLaneSizeD());134VIXL_ASSERT(AreSameFormat(zd, zn, zm));135Emit(AND_z_zz | Rd(zd) | Rn(zn) | Rm(zm));136}137138void Assembler::bic(const ZRegister& zd,139const ZRegister& zn,140const ZRegister& zm) {141VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));142VIXL_ASSERT(zd.IsLaneSizeD());143VIXL_ASSERT(AreSameFormat(zd, zn, zm));144Emit(BIC_z_zz | Rd(zd) | Rn(zn) | Rm(zm));145}146147void Assembler::eor(const ZRegister& zd,148const ZRegister& zn,149const ZRegister& zm) {150VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));151VIXL_ASSERT(zd.IsLaneSizeD());152VIXL_ASSERT(AreSameFormat(zd, zn, zm));153Emit(EOR_z_zz | Rd(zd) | Rn(zn) | Rm(zm));154}155156void Assembler::orr(const ZRegister& zd,157const ZRegister& zn,158const ZRegister& zm) {159VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));160VIXL_ASSERT(zd.IsLaneSizeD());161VIXL_ASSERT(AreSameFormat(zd, zn, zm));162Emit(ORR_z_zz | Rd(zd) | Rn(zn) | Rm(zm));163}164165// SVEBitwiseShiftPredicated.166167void Assembler::SVEBitwiseShiftImmediatePred(const ZRegister& zdn,168const PRegisterM& pg,169Instr encoded_imm_and_tsz,170Instr op) {171Instr tszl_and_imm = ExtractUnsignedBitfield32(4, 0, encoded_imm_and_tsz)172<< 5;173Instr tszh = ExtractUnsignedBitfield32(6, 5, encoded_imm_and_tsz) << 22;174Emit(op | tszh | tszl_and_imm | PgLow8(pg) | Rd(zdn));175}176177void Assembler::asr(const ZRegister& zd,178const PRegisterM& pg,179const ZRegister& zn,180int shift) {181// ASR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>182// 0000 0100 ..00 0000 100. .... .... ....183// tszh<23:22> | opc<19:18> = 00 | L<17> = 0 | U<16> = 0 | Pg<12:10> |184// tszl<9:8> | imm3<7:5> | Zdn<4:0>185186USE(zn);187VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));188VIXL_ASSERT(zd.Is(zn));189Instr encoded_imm =190EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());191SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, ASR_z_p_zi);192}193194void Assembler::asr(const ZRegister& zd,195const PRegisterM& pg,196const ZRegister& zn,197const ZRegister& zm) {198// ASR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D199// 0000 0100 ..01 1000 100. .... .... ....200// size<23:22> | R<18> = 0 | L<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> |201// Zdn<4:0>202203USE(zn);204VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));205VIXL_ASSERT(zd.Is(zn));206VIXL_ASSERT(AreSameLaneSize(zd, zn, zm) ||207((zm.GetLaneSizeInBytes() == kDRegSizeInBytes) &&208(zd.GetLaneSizeInBytes() != kDRegSizeInBytes)));209Instr op = ASR_z_p_zw;210if (AreSameLaneSize(zd, zn, zm)) {211op = ASR_z_p_zz;212}213Emit(op | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));214}215216void Assembler::asrd(const ZRegister& zd,217const PRegisterM& pg,218const ZRegister& zn,219int shift) {220// ASRD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>221// 0000 0100 ..00 0100 100. .... .... ....222// tszh<23:22> | opc<19:18> = 01 | L<17> = 0 | U<16> = 0 | Pg<12:10> |223// tszl<9:8> | imm3<7:5> | Zdn<4:0>224225USE(zn);226VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));227VIXL_ASSERT(zd.Is(zn));228229Instr encoded_imm =230EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());231SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, ASRD_z_p_zi);232}233234void Assembler::asrr(const ZRegister& zd,235const PRegisterM& pg,236const ZRegister& zn,237const ZRegister& zm) {238// ASRR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>239// 0000 0100 ..01 0100 100. .... .... ....240// size<23:22> | R<18> = 1 | L<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> |241// Zdn<4:0>242243USE(zn);244VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));245VIXL_ASSERT(zd.Is(zn));246VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));247248Emit(ASRR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));249}250251void Assembler::lsl(const ZRegister& zd,252const PRegisterM& pg,253const ZRegister& zn,254int shift) {255// LSL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>256// 0000 0100 ..00 0011 100. .... .... ....257// tszh<23:22> | opc<19:18> = 00 | L<17> = 1 | U<16> = 1 | Pg<12:10> |258// tszl<9:8> | imm3<7:5> | Zdn<4:0>259260USE(zn);261VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));262VIXL_ASSERT(zd.Is(zn));263264Instr encoded_imm =265EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());266SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, LSL_z_p_zi);267}268269void Assembler::lsl(const ZRegister& zd,270const PRegisterM& pg,271const ZRegister& zn,272const ZRegister& zm) {273// LSL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D274// 0000 0100 ..01 1011 100. .... .... ....275// size<23:22> | R<18> = 0 | L<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> |276// Zdn<4:0>277278USE(zn);279VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));280VIXL_ASSERT(zd.Is(zn));281VIXL_ASSERT(AreSameLaneSize(zd, zn, zm) ||282((zm.GetLaneSizeInBytes() == kDRegSizeInBytes) &&283(zd.GetLaneSizeInBytes() != kDRegSizeInBytes)));284Instr op = LSL_z_p_zw;285if (AreSameLaneSize(zd, zn, zm)) {286op = LSL_z_p_zz;287}288Emit(op | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));289}290291void Assembler::lslr(const ZRegister& zd,292const PRegisterM& pg,293const ZRegister& zn,294const ZRegister& zm) {295// LSLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>296// 0000 0100 ..01 0111 100. .... .... ....297// size<23:22> | R<18> = 1 | L<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> |298// Zdn<4:0>299300USE(zn);301VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));302VIXL_ASSERT(zd.Is(zn));303VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));304305Emit(LSLR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));306}307308void Assembler::lsr(const ZRegister& zd,309const PRegisterM& pg,310const ZRegister& zn,311int shift) {312// LSR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>313// 0000 0100 ..00 0001 100. .... .... ....314// tszh<23:22> | opc<19:18> = 00 | L<17> = 0 | U<16> = 1 | Pg<12:10> |315// tszl<9:8> | imm3<7:5> | Zdn<4:0>316317USE(zn);318VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));319VIXL_ASSERT(zd.Is(zn));320321Instr encoded_imm =322EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());323SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, LSR_z_p_zi);324}325326void Assembler::lsr(const ZRegister& zd,327const PRegisterM& pg,328const ZRegister& zn,329const ZRegister& zm) {330// LSR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.D331// 0000 0100 ..01 1001 100. .... .... ....332// size<23:22> | R<18> = 0 | L<17> = 0 | U<16> = 1 | Pg<12:10> | Zm<9:5> |333// Zdn<4:0>334335USE(zn);336VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));337VIXL_ASSERT(zd.Is(zn));338VIXL_ASSERT(AreSameLaneSize(zd, zn, zm) ||339((zm.GetLaneSizeInBytes() == kDRegSizeInBytes) &&340(zd.GetLaneSizeInBytes() != kDRegSizeInBytes)));341Instr op = LSR_z_p_zw;342if (AreSameLaneSize(zd, zn, zm)) {343op = LSR_z_p_zz;344}345Emit(op | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));346}347348void Assembler::lsrr(const ZRegister& zd,349const PRegisterM& pg,350const ZRegister& zn,351const ZRegister& zm) {352// LSRR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>353// 0000 0100 ..01 0101 100. .... .... ....354// size<23:22> | R<18> = 1 | L<17> = 0 | U<16> = 1 | Pg<12:10> | Zm<9:5> |355// Zdn<4:0>356357USE(zn);358VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));359VIXL_ASSERT(zd.Is(zn));360VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));361362Emit(LSRR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));363}364365// SVEBitwiseShiftUnpredicated.366367Instr Assembler::EncodeSVEShiftLeftImmediate(int shift, int lane_size_in_bits) {368VIXL_ASSERT((shift >= 0) && (shift < lane_size_in_bits));369return lane_size_in_bits + shift;370}371372Instr Assembler::EncodeSVEShiftRightImmediate(int shift,373int lane_size_in_bits) {374VIXL_ASSERT((shift > 0) && (shift <= lane_size_in_bits));375return (2 * lane_size_in_bits) - shift;376}377378void Assembler::SVEBitwiseShiftImmediate(const ZRegister& zd,379const ZRegister& zn,380Instr encoded_imm_and_tsz,381Instr op) {382Instr tszl_and_imm = ExtractUnsignedBitfield32(4, 0, encoded_imm_and_tsz)383<< 16;384Instr tszh = ExtractUnsignedBitfield32(6, 5, encoded_imm_and_tsz) << 22;385Emit(op | tszh | tszl_and_imm | Rd(zd) | Rn(zn));386}387388void Assembler::asr(const ZRegister& zd, const ZRegister& zn, int shift) {389VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));390VIXL_ASSERT(AreSameLaneSize(zd, zn));391Instr encoded_imm =392EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());393SVEBitwiseShiftImmediate(zd, zn, encoded_imm, ASR_z_zi);394}395396void Assembler::asr(const ZRegister& zd,397const ZRegister& zn,398const ZRegister& zm) {399VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));400VIXL_ASSERT(AreSameLaneSize(zd, zn));401VIXL_ASSERT(zd.GetLaneSizeInBytes() != kDRegSizeInBytes);402403Emit(ASR_z_zw | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));404}405406void Assembler::lsl(const ZRegister& zd, const ZRegister& zn, int shift) {407VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));408Instr encoded_imm =409EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());410SVEBitwiseShiftImmediate(zd, zn, encoded_imm, LSL_z_zi);411}412413void Assembler::lsl(const ZRegister& zd,414const ZRegister& zn,415const ZRegister& zm) {416VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));417VIXL_ASSERT(AreSameLaneSize(zd, zn));418VIXL_ASSERT(zd.GetLaneSizeInBytes() != kDRegSizeInBytes);419420Emit(LSL_z_zw | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));421}422423void Assembler::lsr(const ZRegister& zd, const ZRegister& zn, int shift) {424VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));425Instr encoded_imm =426EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());427SVEBitwiseShiftImmediate(zd, zn, encoded_imm, LSR_z_zi);428}429430void Assembler::lsr(const ZRegister& zd,431const ZRegister& zn,432const ZRegister& zm) {433VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));434VIXL_ASSERT(AreSameLaneSize(zd, zn));435VIXL_ASSERT(zd.GetLaneSizeInBytes() != kDRegSizeInBytes);436437Emit(LSR_z_zw | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));438}439440// SVEElementCount.441442#define VIXL_SVE_INC_DEC_LIST(V) \443V(cntb, CNTB_r_s) \444V(cnth, CNTH_r_s) \445V(cntw, CNTW_r_s) \446V(cntd, CNTD_r_s) \447V(decb, DECB_r_rs) \448V(dech, DECH_r_rs) \449V(decw, DECW_r_rs) \450V(decd, DECD_r_rs) \451V(incb, INCB_r_rs) \452V(inch, INCH_r_rs) \453V(incw, INCW_r_rs) \454V(incd, INCD_r_rs) \455V(sqdecb, SQDECB_r_rs_x) \456V(sqdech, SQDECH_r_rs_x) \457V(sqdecw, SQDECW_r_rs_x) \458V(sqdecd, SQDECD_r_rs_x) \459V(sqincb, SQINCB_r_rs_x) \460V(sqinch, SQINCH_r_rs_x) \461V(sqincw, SQINCW_r_rs_x) \462V(sqincd, SQINCD_r_rs_x)463464#define VIXL_DEFINE_ASM_FUNC(FN, OP) \465void Assembler::FN(const Register& rdn, int pattern, int multiplier) { \466VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \467VIXL_ASSERT(rdn.IsX()); \468Emit(OP | Rd(rdn) | ImmSVEPredicateConstraint(pattern) | \469ImmUnsignedField<19, 16>(multiplier - 1)); \470}471VIXL_SVE_INC_DEC_LIST(VIXL_DEFINE_ASM_FUNC)472#undef VIXL_DEFINE_ASM_FUNC473474#define VIXL_SVE_UQINC_UQDEC_LIST(V) \475V(uqdecb, (rdn.IsX() ? UQDECB_r_rs_x : UQDECB_r_rs_uw)) \476V(uqdech, (rdn.IsX() ? UQDECH_r_rs_x : UQDECH_r_rs_uw)) \477V(uqdecw, (rdn.IsX() ? UQDECW_r_rs_x : UQDECW_r_rs_uw)) \478V(uqdecd, (rdn.IsX() ? UQDECD_r_rs_x : UQDECD_r_rs_uw)) \479V(uqincb, (rdn.IsX() ? UQINCB_r_rs_x : UQINCB_r_rs_uw)) \480V(uqinch, (rdn.IsX() ? UQINCH_r_rs_x : UQINCH_r_rs_uw)) \481V(uqincw, (rdn.IsX() ? UQINCW_r_rs_x : UQINCW_r_rs_uw)) \482V(uqincd, (rdn.IsX() ? UQINCD_r_rs_x : UQINCD_r_rs_uw))483484#define VIXL_DEFINE_ASM_FUNC(FN, OP) \485void Assembler::FN(const Register& rdn, int pattern, int multiplier) { \486VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \487Emit(OP | Rd(rdn) | ImmSVEPredicateConstraint(pattern) | \488ImmUnsignedField<19, 16>(multiplier - 1)); \489}490VIXL_SVE_UQINC_UQDEC_LIST(VIXL_DEFINE_ASM_FUNC)491#undef VIXL_DEFINE_ASM_FUNC492493#define VIXL_SVE_SQX_INC_DEC_LIST(V) \494V(sqdecb, SQDECB) \495V(sqdech, SQDECH) \496V(sqdecw, SQDECW) \497V(sqdecd, SQDECD) \498V(sqincb, SQINCB) \499V(sqinch, SQINCH) \500V(sqincw, SQINCW) \501V(sqincd, SQINCD)502503#define VIXL_DEFINE_ASM_FUNC(FN, OP) \504void Assembler::FN(const Register& xd, \505const Register& wn, \506int pattern, \507int multiplier) { \508USE(wn); \509VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \510VIXL_ASSERT(wn.IsW() && xd.Is(wn.X())); \511Emit(OP##_r_rs_sx | Rd(xd) | ImmSVEPredicateConstraint(pattern) | \512ImmUnsignedField<19, 16>(multiplier - 1)); \513}514VIXL_SVE_SQX_INC_DEC_LIST(VIXL_DEFINE_ASM_FUNC)515#undef VIXL_DEFINE_ASM_FUNC516517#define VIXL_SVE_INC_DEC_VEC_LIST(V) \518V(dech, DEC, H) \519V(decw, DEC, W) \520V(decd, DEC, D) \521V(inch, INC, H) \522V(incw, INC, W) \523V(incd, INC, D) \524V(sqdech, SQDEC, H) \525V(sqdecw, SQDEC, W) \526V(sqdecd, SQDEC, D) \527V(sqinch, SQINC, H) \528V(sqincw, SQINC, W) \529V(sqincd, SQINC, D) \530V(uqdech, UQDEC, H) \531V(uqdecw, UQDEC, W) \532V(uqdecd, UQDEC, D) \533V(uqinch, UQINC, H) \534V(uqincw, UQINC, W) \535V(uqincd, UQINC, D)536537#define VIXL_DEFINE_ASM_FUNC(FN, OP, T) \538void Assembler::FN(const ZRegister& zdn, int pattern, int multiplier) { \539VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \540VIXL_ASSERT(zdn.GetLaneSizeInBytes() == k##T##RegSizeInBytes); \541Emit(OP##T##_z_zs | Rd(zdn) | ImmSVEPredicateConstraint(pattern) | \542ImmUnsignedField<19, 16>(multiplier - 1)); \543}544VIXL_SVE_INC_DEC_VEC_LIST(VIXL_DEFINE_ASM_FUNC)545#undef VIXL_DEFINE_ASM_FUNC546547// SVEFPAccumulatingReduction.548549void Assembler::fadda(const VRegister& vd,550const PRegister& pg,551const VRegister& vn,552const ZRegister& zm) {553// FADDA <V><dn>, <Pg>, <V><dn>, <Zm>.<T>554// 0110 0101 ..01 1000 001. .... .... ....555// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zm<9:5> | Vdn<4:0>556557USE(vn);558VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));559VIXL_ASSERT(vd.Is(vn));560VIXL_ASSERT(vd.IsScalar());561VIXL_ASSERT(zm.GetLaneSizeInBytes() != kBRegSizeInBytes);562VIXL_ASSERT(AreSameLaneSize(zm, vd));563564Emit(FADDA_v_p_z | SVESize(zm) | Rd(vd) | PgLow8(pg) | Rn(zm));565}566567// SVEFPArithmetic_Predicated.568569void Assembler::fabd(const ZRegister& zd,570const PRegisterM& pg,571const ZRegister& zn,572const ZRegister& zm) {573// FABD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>574// 0110 0101 ..00 1000 100. .... .... ....575// size<23:22> | opc<19:16> = 1000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>576577USE(zn);578VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));579VIXL_ASSERT(zd.Is(zn));580VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));581VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);582583Emit(FABD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));584}585586void Assembler::fadd(const ZRegister& zd,587const PRegisterM& pg,588const ZRegister& zn,589double imm) {590// FADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>591// 0110 0101 ..01 1000 100. ..00 00.. ....592// size<23:22> | opc<18:16> = 000 | Pg<12:10> | i1<5> | Zdn<4:0>593594USE(zn);595VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));596VIXL_ASSERT(zd.Is(zn));597VIXL_ASSERT(AreSameLaneSize(zd, zn));598VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);599VIXL_ASSERT((imm == 0.5) || (imm == 1.0));600601Instr i1 = (imm == 1.0) ? (1 << 5) : 0;602Emit(FADD_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);603}604605void Assembler::fadd(const ZRegister& zd,606const PRegisterM& pg,607const ZRegister& zn,608const ZRegister& zm) {609// FADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>610// 0110 0101 ..00 0000 100. .... .... ....611// size<23:22> | opc<19:16> = 0000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>612613USE(zn);614VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));615VIXL_ASSERT(zd.Is(zn));616VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));617VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);618619Emit(FADD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));620}621622void Assembler::fdiv(const ZRegister& zd,623const PRegisterM& pg,624const ZRegister& zn,625const ZRegister& zm) {626// FDIV <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>627// 0110 0101 ..00 1101 100. .... .... ....628// size<23:22> | opc<19:16> = 1101 | Pg<12:10> | Zm<9:5> | Zdn<4:0>629630USE(zn);631VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));632VIXL_ASSERT(zd.Is(zn));633VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));634VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);635636Emit(FDIV_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));637}638639void Assembler::fdivr(const ZRegister& zd,640const PRegisterM& pg,641const ZRegister& zn,642const ZRegister& zm) {643// FDIVR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>644// 0110 0101 ..00 1100 100. .... .... ....645// size<23:22> | opc<19:16> = 1100 | Pg<12:10> | Zm<9:5> | Zdn<4:0>646647USE(zn);648VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));649VIXL_ASSERT(zd.Is(zn));650VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));651VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);652653Emit(FDIVR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));654}655656void Assembler::fmax(const ZRegister& zd,657const PRegisterM& pg,658const ZRegister& zn,659double imm) {660// FMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>661// 0110 0101 ..01 1110 100. ..00 00.. ....662// size<23:22> | opc<18:16> = 110 | Pg<12:10> | i1<5> | Zdn<4:0>663664USE(zn);665VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));666VIXL_ASSERT(zd.Is(zn));667VIXL_ASSERT(AreSameLaneSize(zd, zn));668VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);669VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));670671Instr i1 = (imm == 1.0) ? (1 << 5) : 0;672Emit(FMAX_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);673}674675void Assembler::fmax(const ZRegister& zd,676const PRegisterM& pg,677const ZRegister& zn,678const ZRegister& zm) {679// FMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>680// 0110 0101 ..00 0110 100. .... .... ....681// size<23:22> | opc<19:16> = 0110 | Pg<12:10> | Zm<9:5> | Zdn<4:0>682683USE(zn);684VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));685VIXL_ASSERT(zd.Is(zn));686VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));687VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);688689Emit(FMAX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));690}691692void Assembler::fmaxnm(const ZRegister& zd,693const PRegisterM& pg,694const ZRegister& zn,695double imm) {696// FMAXNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>697// 0110 0101 ..01 1100 100. ..00 00.. ....698// size<23:22> | opc<18:16> = 100 | Pg<12:10> | i1<5> | Zdn<4:0>699700USE(zn);701VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));702VIXL_ASSERT(zd.Is(zn));703VIXL_ASSERT(AreSameLaneSize(zd, zn));704VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);705VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));706707Instr i1 = (imm == 1.0) ? (1 << 5) : 0;708Emit(FMAXNM_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);709}710711void Assembler::fmaxnm(const ZRegister& zd,712const PRegisterM& pg,713const ZRegister& zn,714const ZRegister& zm) {715// FMAXNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>716// 0110 0101 ..00 0100 100. .... .... ....717// size<23:22> | opc<19:16> = 0100 | Pg<12:10> | Zm<9:5> | Zdn<4:0>718719USE(zn);720VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));721VIXL_ASSERT(zd.Is(zn));722VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));723VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);724725Emit(FMAXNM_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));726}727728void Assembler::fmin(const ZRegister& zd,729const PRegisterM& pg,730const ZRegister& zn,731double imm) {732// FMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>733// 0110 0101 ..01 1111 100. ..00 00.. ....734// size<23:22> | opc<18:16> = 111 | Pg<12:10> | i1<5> | Zdn<4:0>735736USE(zn);737VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));738VIXL_ASSERT(zd.Is(zn));739VIXL_ASSERT(AreSameLaneSize(zd, zn));740VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);741VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));742743Instr i1 = (imm == 1.0) ? (1 << 5) : 0;744Emit(FMIN_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);745}746747void Assembler::fmin(const ZRegister& zd,748const PRegisterM& pg,749const ZRegister& zn,750const ZRegister& zm) {751// FMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>752// 0110 0101 ..00 0111 100. .... .... ....753// size<23:22> | opc<19:16> = 0111 | Pg<12:10> | Zm<9:5> | Zdn<4:0>754755USE(zn);756VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));757VIXL_ASSERT(zd.Is(zn));758VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));759VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);760761Emit(FMIN_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));762}763764void Assembler::fminnm(const ZRegister& zd,765const PRegisterM& pg,766const ZRegister& zn,767double imm) {768// FMINNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>769// 0110 0101 ..01 1101 100. ..00 00.. ....770// size<23:22> | opc<18:16> = 101 | Pg<12:10> | i1<5> | Zdn<4:0>771772USE(zn);773VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));774VIXL_ASSERT(zd.Is(zn));775VIXL_ASSERT(AreSameLaneSize(zd, zn));776VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);777VIXL_ASSERT(((imm == 0.0) && (copysign(1.0, imm) == 1.0)) || (imm == 1.0));778779Instr i1 = (imm == 1.0) ? (1 << 5) : 0;780Emit(FMINNM_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);781}782783void Assembler::fminnm(const ZRegister& zd,784const PRegisterM& pg,785const ZRegister& zn,786const ZRegister& zm) {787// FMINNM <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>788// 0110 0101 ..00 0101 100. .... .... ....789// size<23:22> | opc<19:16> = 0101 | Pg<12:10> | Zm<9:5> | Zdn<4:0>790791USE(zn);792VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));793VIXL_ASSERT(zd.Is(zn));794VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));795VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);796797Emit(FMINNM_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));798}799800void Assembler::fmul(const ZRegister& zd,801const PRegisterM& pg,802const ZRegister& zn,803double imm) {804// FMUL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>805// 0110 0101 ..01 1010 100. ..00 00.. ....806// size<23:22> | opc<18:16> = 010 | Pg<12:10> | i1<5> | Zdn<4:0>807808USE(zn);809VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));810VIXL_ASSERT(zd.Is(zn));811VIXL_ASSERT(AreSameLaneSize(zd, zn));812VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);813VIXL_ASSERT((imm == 0.5) || (imm == 2.0));814815Instr i1 = (imm == 2.0) ? (1 << 5) : 0;816Emit(FMUL_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);817}818819void Assembler::fmul(const ZRegister& zd,820const PRegisterM& pg,821const ZRegister& zn,822const ZRegister& zm) {823// FMUL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>824// 0110 0101 ..00 0010 100. .... .... ....825// size<23:22> | opc<19:16> = 0010 | Pg<12:10> | Zm<9:5> | Zdn<4:0>826827USE(zn);828VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));829VIXL_ASSERT(zd.Is(zn));830VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));831VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);832833Emit(FMUL_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));834}835836void Assembler::fmulx(const ZRegister& zd,837const PRegisterM& pg,838const ZRegister& zn,839const ZRegister& zm) {840// FMULX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>841// 0110 0101 ..00 1010 100. .... .... ....842// size<23:22> | opc<19:16> = 1010 | Pg<12:10> | Zm<9:5> | Zdn<4:0>843844USE(zn);845VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));846VIXL_ASSERT(zd.Is(zn));847VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));848VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);849850Emit(FMULX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));851}852853void Assembler::fscale(const ZRegister& zd,854const PRegisterM& pg,855const ZRegister& zn,856const ZRegister& zm) {857// FSCALE <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>858// 0110 0101 ..00 1001 100. .... .... ....859// size<23:22> | opc<19:16> = 1001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>860861USE(zn);862VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));863VIXL_ASSERT(zd.Is(zn));864VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));865VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);866867Emit(FSCALE_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));868}869870void Assembler::fsub(const ZRegister& zd,871const PRegisterM& pg,872const ZRegister& zn,873double imm) {874// FSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>875// 0110 0101 ..01 1001 100. ..00 00.. ....876// size<23:22> | opc<18:16> = 001 | Pg<12:10> | i1<5> | Zdn<4:0>877878USE(zn);879VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));880VIXL_ASSERT(zd.Is(zn));881VIXL_ASSERT(AreSameLaneSize(zd, zn));882VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);883VIXL_ASSERT((imm == 0.5) || (imm == 1.0));884885Instr i1 = (imm == 1.0) ? (1 << 5) : 0;886Emit(FSUB_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);887}888889void Assembler::fsub(const ZRegister& zd,890const PRegisterM& pg,891const ZRegister& zn,892const ZRegister& zm) {893// FSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>894// 0110 0101 ..00 0001 100. .... .... ....895// size<23:22> | opc<19:16> = 0001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>896897USE(zn);898VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));899VIXL_ASSERT(zd.Is(zn));900VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));901VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);902903Emit(FSUB_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));904}905906void Assembler::fsubr(const ZRegister& zd,907const PRegisterM& pg,908const ZRegister& zn,909double imm) {910// FSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <const>911// 0110 0101 ..01 1011 100. ..00 00.. ....912// size<23:22> | opc<18:16> = 011 | Pg<12:10> | i1<5> | Zdn<4:0>913914USE(zn);915VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));916VIXL_ASSERT(zd.Is(zn));917VIXL_ASSERT(AreSameLaneSize(zd, zn));918VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);919VIXL_ASSERT((imm == 0.5) || (imm == 1.0));920921Instr i1 = (imm == 1.0) ? (1 << 5) : 0;922Emit(FSUBR_z_p_zs | SVESize(zd) | Rd(zd) | PgLow8(pg) | i1);923}924925void Assembler::fsubr(const ZRegister& zd,926const PRegisterM& pg,927const ZRegister& zn,928const ZRegister& zm) {929// FSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>930// 0110 0101 ..00 0011 100. .... .... ....931// size<23:22> | opc<19:16> = 0011 | Pg<12:10> | Zm<9:5> | Zdn<4:0>932933USE(zn);934VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));935VIXL_ASSERT(zd.Is(zn));936VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));937VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);938939Emit(FSUBR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));940}941942void Assembler::ftmad(const ZRegister& zd,943const ZRegister& zn,944const ZRegister& zm,945int imm3) {946// FTMAD <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, #<imm>947// 0110 0101 ..01 0... 1000 00.. .... ....948// size<23:22> | imm3<18:16> | Zm<9:5> | Zdn<4:0>949950USE(zn);951VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));952VIXL_ASSERT(zd.Is(zn));953VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));954VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);955956Emit(FTMAD_z_zzi | SVESize(zd) | Rd(zd) | Rn(zm) |957ImmUnsignedField<18, 16>(imm3));958}959960// SVEFPArithmeticUnpredicated.961962void Assembler::fadd(const ZRegister& zd,963const ZRegister& zn,964const ZRegister& zm) {965// FADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>966// 0110 0101 ..0. .... 0000 00.. .... ....967// size<23:22> | Zm<20:16> | opc<12:10> = 000 | Zn<9:5> | Zd<4:0>968969VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));970VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));971VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);972973Emit(FADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));974}975976void Assembler::fmul(const ZRegister& zd,977const ZRegister& zn,978const ZRegister& zm) {979// FMUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>980// 0110 0101 ..0. .... 0000 10.. .... ....981// size<23:22> | Zm<20:16> | opc<12:10> = 010 | Zn<9:5> | Zd<4:0>982983VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));984VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));985VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);986987Emit(FMUL_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));988}989990void Assembler::frecps(const ZRegister& zd,991const ZRegister& zn,992const ZRegister& zm) {993// FRECPS <Zd>.<T>, <Zn>.<T>, <Zm>.<T>994// 0110 0101 ..0. .... 0001 10.. .... ....995// size<23:22> | Zm<20:16> | opc<12:10> = 110 | Zn<9:5> | Zd<4:0>996997VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));998VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));999VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);10001001Emit(FRECPS_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));1002}10031004void Assembler::frsqrts(const ZRegister& zd,1005const ZRegister& zn,1006const ZRegister& zm) {1007// FRSQRTS <Zd>.<T>, <Zn>.<T>, <Zm>.<T>1008// 0110 0101 ..0. .... 0001 11.. .... ....1009// size<23:22> | Zm<20:16> | opc<12:10> = 111 | Zn<9:5> | Zd<4:0>10101011VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1012VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));1013VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);10141015Emit(FRSQRTS_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));1016}10171018void Assembler::fsub(const ZRegister& zd,1019const ZRegister& zn,1020const ZRegister& zm) {1021// FSUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>1022// 0110 0101 ..0. .... 0000 01.. .... ....1023// size<23:22> | Zm<20:16> | opc<12:10> = 001 | Zn<9:5> | Zd<4:0>10241025VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1026VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));1027VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);10281029Emit(FSUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));1030}10311032void Assembler::ftsmul(const ZRegister& zd,1033const ZRegister& zn,1034const ZRegister& zm) {1035// FTSMUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>1036// 0110 0101 ..0. .... 0000 11.. .... ....1037// size<23:22> | Zm<20:16> | opc<12:10> = 011 | Zn<9:5> | Zd<4:0>10381039VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1040VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));1041VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);10421043Emit(FTSMUL_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));1044}10451046// SVEFPCompareVectors.10471048void Assembler::facge(const PRegisterWithLaneSize& pd,1049const PRegisterZ& pg,1050const ZRegister& zn,1051const ZRegister& zm) {1052// FACGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>1053// 0110 0101 ..0. .... 110. .... ...1 ....1054// size<23:22> | Zm<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |1055// o3<4> = 1 | Pd<3:0>10561057VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1058VIXL_ASSERT(AreSameLaneSize(zn, zm));1059VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);10601061Emit(FACGE_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));1062}10631064void Assembler::facgt(const PRegisterWithLaneSize& pd,1065const PRegisterZ& pg,1066const ZRegister& zn,1067const ZRegister& zm) {1068// FACGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>1069// 0110 0101 ..0. .... 111. .... ...1 ....1070// size<23:22> | Zm<20:16> | op<15> = 1 | o2<13> = 1 | Pg<12:10> | Zn<9:5> |1071// o3<4> = 1 | Pd<3:0>10721073VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1074VIXL_ASSERT(AreSameLaneSize(zn, zm));1075VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);10761077Emit(FACGT_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));1078}10791080void Assembler::fcmeq(const PRegisterWithLaneSize& pd,1081const PRegisterZ& pg,1082const ZRegister& zn,1083const ZRegister& zm) {1084// FCMEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>1085// 0110 0101 ..0. .... 011. .... ...0 ....1086// size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5> |1087// o3<4> = 0 | Pd<3:0>10881089VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1090VIXL_ASSERT(AreSameLaneSize(zn, zm));1091VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);10921093Emit(FCMEQ_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));1094}10951096void Assembler::fcmge(const PRegisterWithLaneSize& pd,1097const PRegisterZ& pg,1098const ZRegister& zn,1099const ZRegister& zm) {1100// FCMGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>1101// 0110 0101 ..0. .... 010. .... ...0 ....1102// size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |1103// o3<4> = 0 | Pd<3:0>11041105VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1106VIXL_ASSERT(AreSameLaneSize(zn, zm));1107VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);11081109Emit(FCMGE_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));1110}11111112void Assembler::fcmgt(const PRegisterWithLaneSize& pd,1113const PRegisterZ& pg,1114const ZRegister& zn,1115const ZRegister& zm) {1116// FCMGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>1117// 0110 0101 ..0. .... 010. .... ...1 ....1118// size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |1119// o3<4> = 1 | Pd<3:0>11201121VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1122VIXL_ASSERT(AreSameLaneSize(zn, zm));1123VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);11241125Emit(FCMGT_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));1126}11271128void Assembler::fcmne(const PRegisterWithLaneSize& pd,1129const PRegisterZ& pg,1130const ZRegister& zn,1131const ZRegister& zm) {1132// FCMNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>1133// 0110 0101 ..0. .... 011. .... ...1 ....1134// size<23:22> | Zm<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5> |1135// o3<4> = 1 | Pd<3:0>11361137VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1138VIXL_ASSERT(AreSameLaneSize(zn, zm));1139VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);11401141Emit(FCMNE_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));1142}11431144void Assembler::fcmuo(const PRegisterWithLaneSize& pd,1145const PRegisterZ& pg,1146const ZRegister& zn,1147const ZRegister& zm) {1148// FCMUO <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>1149// 0110 0101 ..0. .... 110. .... ...0 ....1150// size<23:22> | Zm<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5> |1151// o3<4> = 0 | Pd<3:0>11521153VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1154VIXL_ASSERT(AreSameLaneSize(zn, zm));1155VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);11561157Emit(FCMUO_p_p_zz | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));1158}11591160// SVEFPCompareWithZero.11611162void Assembler::fcmeq(const PRegisterWithLaneSize& pd,1163const PRegisterZ& pg,1164const ZRegister& zn,1165double zero) {1166// FCMEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.01167// 0110 0101 ..01 0010 001. .... ...0 ....1168// size<23:22> | eq<17> = 1 | lt<16> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |1169// Pd<3:0>11701171VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1172VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1173VIXL_ASSERT(zero == 0.0);1174USE(zero);11751176Emit(FCMEQ_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));1177}11781179void Assembler::fcmge(const PRegisterWithLaneSize& pd,1180const PRegisterZ& pg,1181const ZRegister& zn,1182double zero) {1183// FCMGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.01184// 0110 0101 ..01 0000 001. .... ...0 ....1185// size<23:22> | eq<17> = 0 | lt<16> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |1186// Pd<3:0>11871188VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1189VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1190VIXL_ASSERT(zero == 0.0);1191USE(zero);11921193Emit(FCMGE_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));1194}11951196void Assembler::fcmgt(const PRegisterWithLaneSize& pd,1197const PRegisterZ& pg,1198const ZRegister& zn,1199double zero) {1200// FCMGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.01201// 0110 0101 ..01 0000 001. .... ...1 ....1202// size<23:22> | eq<17> = 0 | lt<16> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |1203// Pd<3:0>12041205VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1206VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1207VIXL_ASSERT(zero == 0.0);1208USE(zero);12091210Emit(FCMGT_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));1211}12121213void Assembler::fcmle(const PRegisterWithLaneSize& pd,1214const PRegisterZ& pg,1215const ZRegister& zn,1216double zero) {1217// FCMLE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.01218// 0110 0101 ..01 0001 001. .... ...1 ....1219// size<23:22> | eq<17> = 0 | lt<16> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |1220// Pd<3:0>12211222VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1223VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1224VIXL_ASSERT(zero == 0.0);1225USE(zero);12261227Emit(FCMLE_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));1228}12291230void Assembler::fcmlt(const PRegisterWithLaneSize& pd,1231const PRegisterZ& pg,1232const ZRegister& zn,1233double zero) {1234// FCMLT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.01235// 0110 0101 ..01 0001 001. .... ...0 ....1236// size<23:22> | eq<17> = 0 | lt<16> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |1237// Pd<3:0>12381239VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1240VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1241VIXL_ASSERT(zero == 0.0);1242USE(zero);12431244Emit(FCMLT_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));1245}12461247void Assembler::fcmne(const PRegisterWithLaneSize& pd,1248const PRegisterZ& pg,1249const ZRegister& zn,1250double zero) {1251// FCMNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #0.01252// 0110 0101 ..01 0011 001. .... ...0 ....1253// size<23:22> | eq<17> = 1 | lt<16> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |1254// Pd<3:0>12551256VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1257VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1258VIXL_ASSERT(zero == 0.0);1259USE(zero);12601261Emit(FCMNE_p_p_z0 | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn));1262}12631264// SVEFPComplexAddition.12651266void Assembler::fcadd(const ZRegister& zd,1267const PRegisterM& pg,1268const ZRegister& zn,1269const ZRegister& zm,1270int rot) {1271// FCADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>, <const>1272// 0110 0100 ..00 000. 100. .... .... ....1273// size<23:22> | rot<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>12741275USE(zn);1276VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1277VIXL_ASSERT(zd.Is(zn));1278VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));1279VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);1280VIXL_ASSERT((rot == 90) || (rot == 270));12811282Instr rotate_bit = (rot == 90) ? 0 : (1 << 16);1283Emit(FCADD_z_p_zz | rotate_bit | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));1284}12851286// SVEFPComplexMulAdd.12871288void Assembler::fcmla(const ZRegister& zda,1289const PRegisterM& pg,1290const ZRegister& zn,1291const ZRegister& zm,1292int rot) {1293// FCMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>, <const>1294// 0110 0100 ..0. .... 0... .... .... ....1295// size<23:22> | Zm<20:16> | rot<14:13> | Pg<12:10> | Zn<9:5> | Zda<4:0>12961297VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1298VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));1299VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);1300VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));13011302Instr rotate_bit = (rot / 90) << 13;1303Emit(FCMLA_z_p_zzz | rotate_bit | SVESize(zda) | Rd(zda) | PgLow8(pg) |1304Rn(zn) | Rm(zm));1305}13061307// SVEFPComplexMulAddIndex.13081309void Assembler::fcmla(const ZRegister& zda,1310const ZRegister& zn,1311const ZRegister& zm,1312int index,1313int rot) {1314VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1315VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));1316VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));13171318Instr rotate_bit = (rot / 90) << 10;1319Emit(FCMLA_z_zzzi_h | SVEMulComplexIndexHelper(zm, index) | rotate_bit |1320Rd(zda) | Rn(zn));1321}13221323// SVEFPFastReduction.13241325void Assembler::faddv(const VRegister& vd,1326const PRegister& pg,1327const ZRegister& zn) {1328// FADDV <V><d>, <Pg>, <Zn>.<T>1329// 0110 0101 ..00 0000 001. .... .... ....1330// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zn<9:5> | Vd<4:0>13311332VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1333VIXL_ASSERT(vd.IsScalar());1334VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1335VIXL_ASSERT(AreSameLaneSize(zn, vd));13361337Emit(FADDV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));1338}13391340void Assembler::fmaxnmv(const VRegister& vd,1341const PRegister& pg,1342const ZRegister& zn) {1343// FMAXNMV <V><d>, <Pg>, <Zn>.<T>1344// 0110 0101 ..00 0100 001. .... .... ....1345// size<23:22> | opc<18:16> = 100 | Pg<12:10> | Zn<9:5> | Vd<4:0>13461347VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1348VIXL_ASSERT(vd.IsScalar());1349VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1350VIXL_ASSERT(AreSameLaneSize(zn, vd));13511352Emit(FMAXNMV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));1353}13541355void Assembler::fmaxv(const VRegister& vd,1356const PRegister& pg,1357const ZRegister& zn) {1358// FMAXV <V><d>, <Pg>, <Zn>.<T>1359// 0110 0101 ..00 0110 001. .... .... ....1360// size<23:22> | opc<18:16> = 110 | Pg<12:10> | Zn<9:5> | Vd<4:0>13611362VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1363VIXL_ASSERT(vd.IsScalar());1364VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1365VIXL_ASSERT(AreSameLaneSize(zn, vd));13661367Emit(FMAXV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));1368}13691370void Assembler::fminnmv(const VRegister& vd,1371const PRegister& pg,1372const ZRegister& zn) {1373// FMINNMV <V><d>, <Pg>, <Zn>.<T>1374// 0110 0101 ..00 0101 001. .... .... ....1375// size<23:22> | opc<18:16> = 101 | Pg<12:10> | Zn<9:5> | Vd<4:0>13761377VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1378VIXL_ASSERT(vd.IsScalar());1379VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1380VIXL_ASSERT(AreSameLaneSize(zn, vd));13811382Emit(FMINNMV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));1383}13841385void Assembler::fminv(const VRegister& vd,1386const PRegister& pg,1387const ZRegister& zn) {1388// FMINV <V><d>, <Pg>, <Zn>.<T>1389// 0110 0101 ..00 0111 001. .... .... ....1390// size<23:22> | opc<18:16> = 111 | Pg<12:10> | Zn<9:5> | Vd<4:0>13911392VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1393VIXL_ASSERT(vd.IsScalar());1394VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);1395VIXL_ASSERT(AreSameLaneSize(zn, vd));13961397Emit(FMINV_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));1398}13991400// SVEFPMulAdd.14011402void Assembler::fmad(const ZRegister& zdn,1403const PRegisterM& pg,1404const ZRegister& zm,1405const ZRegister& za) {1406// FMAD <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>1407// 0110 0101 ..1. .... 100. .... .... ....1408// size<23:22> | Za<20:16> | opc<14:13> = 00 | Pg<12:10> | Zm<9:5> | Zdn<4:0>14091410VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1411VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));1412VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);14131414Emit(FMAD_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));1415}14161417void Assembler::fmla(const ZRegister& zda,1418const PRegisterM& pg,1419const ZRegister& zn,1420const ZRegister& zm) {1421// FMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>1422// 0110 0101 ..1. .... 000. .... .... ....1423// size<23:22> | Zm<20:16> | opc<14:13> = 00 | Pg<12:10> | Zn<9:5> | Zda<4:0>14241425VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1426VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));1427VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);14281429Emit(FMLA_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));1430}14311432void Assembler::fmls(const ZRegister& zda,1433const PRegisterM& pg,1434const ZRegister& zn,1435const ZRegister& zm) {1436// FMLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>1437// 0110 0101 ..1. .... 001. .... .... ....1438// size<23:22> | Zm<20:16> | opc<14:13> = 01 | Pg<12:10> | Zn<9:5> | Zda<4:0>14391440VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1441VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));1442VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);14431444Emit(FMLS_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));1445}14461447void Assembler::fmsb(const ZRegister& zdn,1448const PRegisterM& pg,1449const ZRegister& zm,1450const ZRegister& za) {1451// FMSB <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>1452// 0110 0101 ..1. .... 101. .... .... ....1453// size<23:22> | Za<20:16> | opc<14:13> = 01 | Pg<12:10> | Zm<9:5> | Zdn<4:0>14541455VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1456VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));1457VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);14581459Emit(FMSB_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));1460}14611462void Assembler::fnmad(const ZRegister& zdn,1463const PRegisterM& pg,1464const ZRegister& zm,1465const ZRegister& za) {1466// FNMAD <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>1467// 0110 0101 ..1. .... 110. .... .... ....1468// size<23:22> | Za<20:16> | opc<14:13> = 10 | Pg<12:10> | Zm<9:5> | Zdn<4:0>14691470VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1471VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));1472VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);14731474Emit(FNMAD_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));1475}14761477void Assembler::fnmla(const ZRegister& zda,1478const PRegisterM& pg,1479const ZRegister& zn,1480const ZRegister& zm) {1481// FNMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>1482// 0110 0101 ..1. .... 010. .... .... ....1483// size<23:22> | Zm<20:16> | opc<14:13> = 10 | Pg<12:10> | Zn<9:5> | Zda<4:0>14841485VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1486VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));1487VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);14881489Emit(FNMLA_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));1490}14911492void Assembler::fnmls(const ZRegister& zda,1493const PRegisterM& pg,1494const ZRegister& zn,1495const ZRegister& zm) {1496// FNMLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>1497// 0110 0101 ..1. .... 011. .... .... ....1498// size<23:22> | Zm<20:16> | opc<14:13> = 11 | Pg<12:10> | Zn<9:5> | Zda<4:0>14991500VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1501VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));1502VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);15031504Emit(FNMLS_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));1505}15061507void Assembler::fnmsb(const ZRegister& zdn,1508const PRegisterM& pg,1509const ZRegister& zm,1510const ZRegister& za) {1511// FNMSB <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>1512// 0110 0101 ..1. .... 111. .... .... ....1513// size<23:22> | Za<20:16> | opc<14:13> = 11 | Pg<12:10> | Zm<9:5> | Zdn<4:0>15141515VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1516VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));1517VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);15181519Emit(FNMSB_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rn(zm) | Rm(za));1520}15211522Instr Assembler::SVEMulIndexHelper(unsigned lane_size_in_bytes_log2,1523const ZRegister& zm,1524int index,1525Instr op_h,1526Instr op_s,1527Instr op_d) {1528Instr size = lane_size_in_bytes_log2 << SVESize_offset;1529Instr zm_with_index = Rm(zm);1530Instr op = 0xffffffff;1531// Allowable register number and lane index depends on the lane size.1532switch (lane_size_in_bytes_log2) {1533case kHRegSizeInBytesLog2:1534VIXL_ASSERT(zm.GetCode() <= 7);1535VIXL_ASSERT(IsUint3(index));1536// For H-sized lanes, size is encoded as 0b0x, where x is used as the top1537// bit of the index. So, if index is less than four, the top bit of index1538// is zero, and therefore size is 0b00. Otherwise, it's 0b01, the usual1539// encoding for H-sized lanes.1540if (index < 4) size = 0;1541// Top two bits of "zm" encode the index.1542zm_with_index |= (index & 3) << (Rm_offset + 3);1543op = op_h;1544break;1545case kSRegSizeInBytesLog2:1546VIXL_CHECK(zm.GetCode() <= 7);1547VIXL_CHECK(IsUint2(index));1548// Top two bits of "zm" encode the index.1549zm_with_index |= (index & 3) << (Rm_offset + 3);1550op = op_s;1551break;1552case kDRegSizeInBytesLog2:1553VIXL_CHECK(zm.GetCode() <= 15);1554VIXL_CHECK(IsUint1(index));1555// Top bit of "zm" encodes the index.1556zm_with_index |= (index & 1) << (Rm_offset + 4);1557op = op_d;1558break;1559default:1560VIXL_UNIMPLEMENTED();1561}1562return op | zm_with_index | size;1563}15641565Instr Assembler::SVEMulLongIndexHelper(const ZRegister& zm, int index) {1566Instr imm_field;1567Instr zm_id;1568if (zm.IsLaneSizeH()) {1569VIXL_CHECK(zm.GetCode() <= 7);1570VIXL_CHECK(IsUint3(index));1571imm_field = ExtractUnsignedBitfield32(2, 1, index) << 19;1572zm_id = Rx<18, 16>(zm);1573} else {1574VIXL_ASSERT(zm.IsLaneSizeS());1575VIXL_CHECK(zm.GetCode() <= 15);1576VIXL_CHECK(IsUint2(index));1577imm_field = ExtractBit(index, 1) << 20;1578zm_id = Rx<19, 16>(zm);1579}15801581// Synthesize the low part of immediate encoding.1582imm_field |= ExtractBit(index, 0) << 11;15831584return zm_id | imm_field;1585}15861587Instr Assembler::SVEMulComplexIndexHelper(const ZRegister& zm, int index) {1588Instr zm_idx_size;1589if (zm.IsLaneSizeH()) {1590// Zm<18:16> | i2<20:19>1591VIXL_CHECK(zm.GetCode() <= 7);1592VIXL_CHECK(IsUint2(index));1593zm_idx_size = (index << 19) | Rx<18, 16>(zm) | 0;1594} else {1595VIXL_ASSERT(zm.IsLaneSizeS());1596// Zm<19:16> | i1<20>1597VIXL_CHECK(zm.GetCode() <= 15);1598VIXL_CHECK(IsUint1(index));1599zm_idx_size = (index << 20) | Rx<19, 16>(zm) | (1 << 22);1600}1601return zm_idx_size;1602}16031604// SVEFPMulAddIndex.16051606void Assembler::fmla(const ZRegister& zda,1607const ZRegister& zn,1608const ZRegister& zm,1609int index) {1610VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1611VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));16121613// The encoding of opcode, index, Zm, and size are synthesized in this1614// variable.1615Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),1616zm,1617index,1618FMLA_z_zzzi_h,1619FMLA_z_zzzi_s,1620FMLA_z_zzzi_d);16211622Emit(synthesized_op | Rd(zda) | Rn(zn));1623}16241625void Assembler::fmls(const ZRegister& zda,1626const ZRegister& zn,1627const ZRegister& zm,1628int index) {1629VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1630VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));16311632// The encoding of opcode, index, Zm, and size are synthesized in this1633// variable.1634Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),1635zm,1636index,1637FMLS_z_zzzi_h,1638FMLS_z_zzzi_s,1639FMLS_z_zzzi_d);16401641Emit(synthesized_op | Rd(zda) | Rn(zn));1642}16431644// SVEFPMulIndex.16451646// This prototype maps to 3 instruction encodings:1647void Assembler::fmul(const ZRegister& zd,1648const ZRegister& zn,1649const ZRegister& zm,1650unsigned index) {1651// FMUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>[<imm>]1652// 0110 0100 ..1. .... 0010 00.. .... ....1653// size<23:22> | opc<20:16> | Zn<9:5> | Zd<4:0>16541655VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1656VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));16571658// The encoding of opcode, index, Zm, and size are synthesized in this1659// variable.1660Instr synthesized_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),1661zm,1662index,1663FMUL_z_zzi_h,1664FMUL_z_zzi_s,1665FMUL_z_zzi_d);16661667Emit(synthesized_op | Rd(zd) | Rn(zn));1668}16691670// SVEFPUnaryOpPredicated.16711672void Assembler::fcvt(const ZRegister& zd,1673const PRegisterM& pg,1674const ZRegister& zn) {1675VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));16761677Instr op = 0xffffffff;1678switch (zn.GetLaneSizeInBytes()) {1679case kHRegSizeInBytes:1680switch (zd.GetLaneSizeInBytes()) {1681case kSRegSizeInBytes:1682op = FCVT_z_p_z_h2s;1683break;1684case kDRegSizeInBytes:1685op = FCVT_z_p_z_h2d;1686break;1687}1688break;1689case kSRegSizeInBytes:1690switch (zd.GetLaneSizeInBytes()) {1691case kHRegSizeInBytes:1692op = FCVT_z_p_z_s2h;1693break;1694case kDRegSizeInBytes:1695op = FCVT_z_p_z_s2d;1696break;1697}1698break;1699case kDRegSizeInBytes:1700switch (zd.GetLaneSizeInBytes()) {1701case kHRegSizeInBytes:1702op = FCVT_z_p_z_d2h;1703break;1704case kSRegSizeInBytes:1705op = FCVT_z_p_z_d2s;1706break;1707}1708break;1709}1710VIXL_ASSERT(op != 0xffffffff);17111712Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));1713}17141715void Assembler::fcvtzs(const ZRegister& zd,1716const PRegisterM& pg,1717const ZRegister& zn) {1718VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1719Instr op = 0xffffffff;1720switch (zn.GetLaneSizeInBytes()) {1721case kHRegSizeInBytes:1722switch (zd.GetLaneSizeInBytes()) {1723case kHRegSizeInBytes:1724op = FCVTZS_z_p_z_fp162h;1725break;1726case kSRegSizeInBytes:1727op = FCVTZS_z_p_z_fp162w;1728break;1729case kDRegSizeInBytes:1730op = FCVTZS_z_p_z_fp162x;1731break;1732}1733break;1734case kSRegSizeInBytes:1735switch (zd.GetLaneSizeInBytes()) {1736case kSRegSizeInBytes:1737op = FCVTZS_z_p_z_s2w;1738break;1739case kDRegSizeInBytes:1740op = FCVTZS_z_p_z_s2x;1741break;1742}1743break;1744case kDRegSizeInBytes:1745switch (zd.GetLaneSizeInBytes()) {1746case kSRegSizeInBytes:1747op = FCVTZS_z_p_z_d2w;1748break;1749case kDRegSizeInBytes:1750op = FCVTZS_z_p_z_d2x;1751break;1752}1753break;1754}1755VIXL_ASSERT(op != 0xffffffff);17561757Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));1758}17591760void Assembler::fcvtzu(const ZRegister& zd,1761const PRegisterM& pg,1762const ZRegister& zn) {1763VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1764Instr op = 0xffffffff;1765switch (zn.GetLaneSizeInBytes()) {1766case kHRegSizeInBytes:1767switch (zd.GetLaneSizeInBytes()) {1768case kHRegSizeInBytes:1769op = FCVTZU_z_p_z_fp162h;1770break;1771case kSRegSizeInBytes:1772op = FCVTZU_z_p_z_fp162w;1773break;1774case kDRegSizeInBytes:1775op = FCVTZU_z_p_z_fp162x;1776break;1777}1778break;1779case kSRegSizeInBytes:1780switch (zd.GetLaneSizeInBytes()) {1781case kSRegSizeInBytes:1782op = FCVTZU_z_p_z_s2w;1783break;1784case kDRegSizeInBytes:1785op = FCVTZU_z_p_z_s2x;1786break;1787}1788break;1789case kDRegSizeInBytes:1790switch (zd.GetLaneSizeInBytes()) {1791case kSRegSizeInBytes:1792op = FCVTZU_z_p_z_d2w;1793break;1794case kDRegSizeInBytes:1795op = FCVTZU_z_p_z_d2x;1796break;1797}1798break;1799}1800VIXL_ASSERT(op != 0xffffffff);18011802Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));1803}18041805void Assembler::frecpx(const ZRegister& zd,1806const PRegisterM& pg,1807const ZRegister& zn) {1808// FRECPX <Zd>.<T>, <Pg>/M, <Zn>.<T>1809// 0110 0101 ..00 1100 101. .... .... ....1810// size<23:22> | opc<17:16> = 00 | Pg<12:10> | Zn<9:5> | Zd<4:0>18111812VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1813VIXL_ASSERT(AreSameLaneSize(zd, zn));1814VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);18151816Emit(FRECPX_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));1817}18181819void Assembler::frinta(const ZRegister& zd,1820const PRegisterM& pg,1821const ZRegister& zn) {1822VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1823VIXL_ASSERT(AreSameLaneSize(zd, zn));1824VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);18251826Emit(FRINTA_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));1827}18281829void Assembler::frinti(const ZRegister& zd,1830const PRegisterM& pg,1831const ZRegister& zn) {1832VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1833VIXL_ASSERT(AreSameLaneSize(zd, zn));1834VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);18351836Emit(FRINTI_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));1837}18381839void Assembler::frintm(const ZRegister& zd,1840const PRegisterM& pg,1841const ZRegister& zn) {1842VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1843VIXL_ASSERT(AreSameLaneSize(zd, zn));1844VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);18451846Emit(FRINTM_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));1847}18481849void Assembler::frintn(const ZRegister& zd,1850const PRegisterM& pg,1851const ZRegister& zn) {1852VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1853VIXL_ASSERT(AreSameLaneSize(zd, zn));1854VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);18551856Emit(FRINTN_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));1857}18581859void Assembler::frintp(const ZRegister& zd,1860const PRegisterM& pg,1861const ZRegister& zn) {1862VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1863VIXL_ASSERT(AreSameLaneSize(zd, zn));1864VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);18651866Emit(FRINTP_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));1867}18681869void Assembler::frintx(const ZRegister& zd,1870const PRegisterM& pg,1871const ZRegister& zn) {1872VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1873VIXL_ASSERT(AreSameLaneSize(zd, zn));1874VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);18751876Emit(FRINTX_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));1877}18781879void Assembler::frintz(const ZRegister& zd,1880const PRegisterM& pg,1881const ZRegister& zn) {1882VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1883VIXL_ASSERT(AreSameLaneSize(zd, zn));1884VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);18851886Emit(FRINTZ_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));1887}18881889void Assembler::fsqrt(const ZRegister& zd,1890const PRegisterM& pg,1891const ZRegister& zn) {1892// FSQRT <Zd>.<T>, <Pg>/M, <Zn>.<T>1893// 0110 0101 ..00 1101 101. .... .... ....1894// size<23:22> | opc<17:16> = 01 | Pg<12:10> | Zn<9:5> | Zd<4:0>18951896VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1897VIXL_ASSERT(AreSameLaneSize(zd, zn));1898VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);18991900Emit(FSQRT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));1901}19021903void Assembler::scvtf(const ZRegister& zd,1904const PRegisterM& pg,1905const ZRegister& zn) {1906VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1907Instr op = 0xffffffff;1908switch (zn.GetLaneSizeInBytes()) {1909case kHRegSizeInBytes:1910switch (zd.GetLaneSizeInBytes()) {1911case kHRegSizeInBytes:1912op = SCVTF_z_p_z_h2fp16;1913break;1914}1915break;1916case kSRegSizeInBytes:1917switch (zd.GetLaneSizeInBytes()) {1918case kHRegSizeInBytes:1919op = SCVTF_z_p_z_w2fp16;1920break;1921case kSRegSizeInBytes:1922op = SCVTF_z_p_z_w2s;1923break;1924case kDRegSizeInBytes:1925op = SCVTF_z_p_z_w2d;1926break;1927}1928break;1929case kDRegSizeInBytes:1930switch (zd.GetLaneSizeInBytes()) {1931case kHRegSizeInBytes:1932op = SCVTF_z_p_z_x2fp16;1933break;1934case kSRegSizeInBytes:1935op = SCVTF_z_p_z_x2s;1936break;1937case kDRegSizeInBytes:1938op = SCVTF_z_p_z_x2d;1939break;1940}1941break;1942}1943VIXL_ASSERT(op != 0xffffffff);19441945Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));1946}19471948void Assembler::ucvtf(const ZRegister& zd,1949const PRegisterM& pg,1950const ZRegister& zn) {1951VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));1952Instr op = 0xffffffff;1953switch (zn.GetLaneSizeInBytes()) {1954case kHRegSizeInBytes:1955switch (zd.GetLaneSizeInBytes()) {1956case kHRegSizeInBytes:1957op = UCVTF_z_p_z_h2fp16;1958break;1959}1960break;1961case kSRegSizeInBytes:1962switch (zd.GetLaneSizeInBytes()) {1963case kHRegSizeInBytes:1964op = UCVTF_z_p_z_w2fp16;1965break;1966case kSRegSizeInBytes:1967op = UCVTF_z_p_z_w2s;1968break;1969case kDRegSizeInBytes:1970op = UCVTF_z_p_z_w2d;1971break;1972}1973break;1974case kDRegSizeInBytes:1975switch (zd.GetLaneSizeInBytes()) {1976case kHRegSizeInBytes:1977op = UCVTF_z_p_z_x2fp16;1978break;1979case kSRegSizeInBytes:1980op = UCVTF_z_p_z_x2s;1981break;1982case kDRegSizeInBytes:1983op = UCVTF_z_p_z_x2d;1984break;1985}1986break;1987}1988VIXL_ASSERT(op != 0xffffffff);19891990Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));1991}19921993// SVEFPUnaryOpUnpredicated.19941995void Assembler::frecpe(const ZRegister& zd, const ZRegister& zn) {1996// FRECPE <Zd>.<T>, <Zn>.<T>1997// 0110 0101 ..00 1110 0011 00.. .... ....1998// size<23:22> | opc<18:16> = 110 | Zn<9:5> | Zd<4:0>19992000VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2001VIXL_ASSERT(AreSameLaneSize(zd, zn));2002VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);20032004Emit(FRECPE_z_z | SVESize(zd) | Rd(zd) | Rn(zn));2005}20062007void Assembler::frsqrte(const ZRegister& zd, const ZRegister& zn) {2008// FRSQRTE <Zd>.<T>, <Zn>.<T>2009// 0110 0101 ..00 1111 0011 00.. .... ....2010// size<23:22> | opc<18:16> = 111 | Zn<9:5> | Zd<4:0>20112012VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2013VIXL_ASSERT(AreSameLaneSize(zd, zn));2014VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);20152016Emit(FRSQRTE_z_z | SVESize(zd) | Rd(zd) | Rn(zn));2017}20182019// SVEIncDecByPredicateCount.20202021void Assembler::decp(const Register& rdn, const PRegisterWithLaneSize& pg) {2022// DECP <Xdn>, <Pg>.<T>2023// 0010 0101 ..10 1101 1000 100. .... ....2024// size<23:22> | op<17> = 0 | D<16> = 1 | opc2<10:9> = 00 | Pg<8:5> |2025// Rdn<4:0>20262027VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2028VIXL_ASSERT(rdn.IsX());20292030Emit(DECP_r_p_r | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));2031}20322033void Assembler::decp(const ZRegister& zdn, const PRegister& pg) {2034// DECP <Zdn>.<T>, <Pg>2035// 0010 0101 ..10 1101 1000 000. .... ....2036// size<23:22> | op<17> = 0 | D<16> = 1 | opc2<10:9> = 00 | Pg<8:5> |2037// Zdn<4:0>20382039VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2040VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);2041VIXL_ASSERT(pg.IsUnqualified());20422043Emit(DECP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));2044}20452046void Assembler::incp(const Register& rdn, const PRegisterWithLaneSize& pg) {2047// INCP <Xdn>, <Pg>.<T>2048// 0010 0101 ..10 1100 1000 100. .... ....2049// size<23:22> | op<17> = 0 | D<16> = 0 | opc2<10:9> = 00 | Pg<8:5> |2050// Rdn<4:0>20512052VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2053VIXL_ASSERT(rdn.IsX());20542055Emit(INCP_r_p_r | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));2056}20572058void Assembler::incp(const ZRegister& zdn, const PRegister& pg) {2059// INCP <Zdn>.<T>, <Pg>2060// 0010 0101 ..10 1100 1000 000. .... ....2061// size<23:22> | op<17> = 0 | D<16> = 0 | opc2<10:9> = 00 | Pg<8:5> |2062// Zdn<4:0>20632064VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2065VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);2066VIXL_ASSERT(pg.IsUnqualified());20672068Emit(INCP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));2069}20702071void Assembler::sqdecp(const Register& xd,2072const PRegisterWithLaneSize& pg,2073const Register& wn) {2074// SQDECP <Xdn>, <Pg>.<T>, <Wdn>2075// 0010 0101 ..10 1010 1000 100. .... ....2076// size<23:22> | D<17> = 1 | U<16> = 0 | sf<10> = 0 | op<9> = 0 | Pg<8:5> |2077// Rdn<4:0>20782079USE(wn);2080VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2081VIXL_ASSERT(xd.IsX() && wn.IsW() && xd.Aliases(wn));20822083Emit(SQDECP_r_p_r_sx | SVESize(pg) | Rd(xd) | Rx<8, 5>(pg));2084}20852086void Assembler::sqdecp(const Register& xdn, const PRegisterWithLaneSize& pg) {2087// SQDECP <Xdn>, <Pg>.<T>2088// 0010 0101 ..10 1010 1000 110. .... ....2089// size<23:22> | D<17> = 1 | U<16> = 0 | sf<10> = 1 | op<9> = 0 | Pg<8:5> |2090// Rdn<4:0>20912092VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2093VIXL_ASSERT(xdn.IsX());20942095Emit(SQDECP_r_p_r_x | SVESize(pg) | Rd(xdn) | Rx<8, 5>(pg));2096}20972098void Assembler::sqdecp(const ZRegister& zdn, const PRegister& pg) {2099// SQDECP <Zdn>.<T>, <Pg>2100// 0010 0101 ..10 1010 1000 000. .... ....2101// size<23:22> | D<17> = 1 | U<16> = 0 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>21022103VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2104VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);2105VIXL_ASSERT(pg.IsUnqualified());21062107Emit(SQDECP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));2108}21092110void Assembler::sqincp(const Register& xd,2111const PRegisterWithLaneSize& pg,2112const Register& wn) {2113// SQINCP <Xdn>, <Pg>.<T>, <Wdn>2114// 0010 0101 ..10 1000 1000 100. .... ....2115// size<23:22> | D<17> = 0 | U<16> = 0 | sf<10> = 0 | op<9> = 0 | Pg<8:5> |2116// Rdn<4:0>21172118USE(wn);2119VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2120VIXL_ASSERT(xd.IsX() && wn.IsW() && xd.Aliases(wn));21212122Emit(SQINCP_r_p_r_sx | SVESize(pg) | Rd(xd) | Rx<8, 5>(pg));2123}21242125void Assembler::sqincp(const Register& xdn, const PRegisterWithLaneSize& pg) {2126// SQINCP <Xdn>, <Pg>.<T>2127// 0010 0101 ..10 1000 1000 110. .... ....2128// size<23:22> | D<17> = 0 | U<16> = 0 | sf<10> = 1 | op<9> = 0 | Pg<8:5> |2129// Rdn<4:0>21302131VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2132VIXL_ASSERT(xdn.IsX());21332134Emit(SQINCP_r_p_r_x | SVESize(pg) | Rd(xdn) | Rx<8, 5>(pg));2135}21362137void Assembler::sqincp(const ZRegister& zdn, const PRegister& pg) {2138// SQINCP <Zdn>.<T>, <Pg>2139// 0010 0101 ..10 1000 1000 000. .... ....2140// size<23:22> | D<17> = 0 | U<16> = 0 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>21412142VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2143VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);2144VIXL_ASSERT(pg.IsUnqualified());21452146Emit(SQINCP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));2147}21482149void Assembler::uqdecp(const Register& rdn, const PRegisterWithLaneSize& pg) {2150// UQDECP <Wdn>, <Pg>.<T>2151// UQDECP <Xdn>, <Pg>.<T>2152// 0010 0101 ..10 1011 1000 10.. .... ....2153// size<23:22> | D<17> = 1 | U<16> = 1 | sf<10> | op<9> = 0 | Pg<8:5> |2154// Rdn<4:0>21552156VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));21572158Instr op = rdn.IsX() ? UQDECP_r_p_r_x : UQDECP_r_p_r_uw;2159Emit(op | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));2160}21612162void Assembler::uqdecp(const ZRegister& zdn, const PRegister& pg) {2163// UQDECP <Zdn>.<T>, <Pg>2164// 0010 0101 ..10 1011 1000 000. .... ....2165// size<23:22> | D<17> = 1 | U<16> = 1 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>21662167VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2168VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);2169VIXL_ASSERT(pg.IsUnqualified());21702171Emit(UQDECP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));2172}21732174void Assembler::uqincp(const Register& rdn, const PRegisterWithLaneSize& pg) {2175// UQINCP <Wdn>, <Pg>.<T>2176// 0010 0101 ..10 1001 1000 100. .... ....2177// size<23:22> | D<17> = 0 | U<16> = 1 | sf<10> = 0 | op<9> = 0 | Pg<8:5> |2178// Rdn<4:0>21792180VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));21812182Instr op = rdn.IsX() ? UQINCP_r_p_r_x : UQINCP_r_p_r_uw;2183Emit(op | SVESize(pg) | Rd(rdn) | Rx<8, 5>(pg));2184}21852186void Assembler::uqincp(const ZRegister& zdn, const PRegister& pg) {2187// UQINCP <Zdn>.<T>, <Pg>2188// 0010 0101 ..10 1001 1000 000. .... ....2189// size<23:22> | D<17> = 0 | U<16> = 1 | opc<10:9> = 00 | Pg<8:5> | Zdn<4:0>21902191VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2192VIXL_ASSERT(zdn.GetLaneSizeInBytes() != kBRegSizeInBytes);2193VIXL_ASSERT(pg.IsUnqualified());21942195Emit(UQINCP_z_p_z | SVESize(zdn) | Rd(zdn) | Pg<8, 5>(pg));2196}21972198// SVEIndexGeneration.21992200void Assembler::index(const ZRegister& zd, int start, int step) {2201// INDEX <Zd>.<T>, #<imm1>, #<imm2>2202// 0000 0100 ..1. .... 0100 00.. .... ....2203// size<23:22> | step<20:16> | start<9:5> | Zd<4:0>22042205VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));22062207Emit(INDEX_z_ii | SVESize(zd) | ImmField<20, 16>(step) |2208ImmField<9, 5>(start) | Rd(zd));2209}22102211void Assembler::index(const ZRegister& zd,2212const Register& rn,2213const Register& rm) {2214// INDEX <Zd>.<T>, <R><n>, <R><m>2215// 0000 0100 ..1. .... 0100 11.. .... ....2216// size<23:22> | Rm<20:16> | Rn<9:5> | Zd<4:0>22172218VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2219VIXL_ASSERT(static_cast<unsigned>(rn.GetSizeInBits()) >=2220zd.GetLaneSizeInBits());2221VIXL_ASSERT(static_cast<unsigned>(rm.GetSizeInBits()) >=2222zd.GetLaneSizeInBits());22232224Emit(INDEX_z_rr | SVESize(zd) | Rd(zd) | Rn(rn) | Rm(rm));2225}22262227void Assembler::index(const ZRegister& zd, const Register& rn, int imm5) {2228// INDEX <Zd>.<T>, <R><n>, #<imm>2229// 0000 0100 ..1. .... 0100 01.. .... ....2230// size<23:22> | imm5<20:16> | Rn<9:5> | Zd<4:0>22312232VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2233VIXL_ASSERT(static_cast<unsigned>(rn.GetSizeInBits()) >=2234zd.GetLaneSizeInBits());22352236Emit(INDEX_z_ri | SVESize(zd) | Rd(zd) | Rn(rn) | ImmField<20, 16>(imm5));2237}22382239void Assembler::index(const ZRegister& zd, int imm5, const Register& rm) {2240// INDEX <Zd>.<T>, #<imm>, <R><m>2241// 0000 0100 ..1. .... 0100 10.. .... ....2242// size<23:22> | Rm<20:16> | imm5<9:5> | Zd<4:0>22432244VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2245VIXL_ASSERT(static_cast<unsigned>(rm.GetSizeInBits()) >=2246zd.GetLaneSizeInBits());22472248Emit(INDEX_z_ir | SVESize(zd) | Rd(zd) | ImmField<9, 5>(imm5) | Rm(rm));2249}22502251// SVEIntArithmeticUnpredicated.22522253void Assembler::add(const ZRegister& zd,2254const ZRegister& zn,2255const ZRegister& zm) {2256// ADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>2257// 0000 0100 ..1. .... 0000 00.. .... ....2258// size<23:22> | Zm<20:16> | opc<12:10> = 000 | Zn<9:5> | Zd<4:0>22592260VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2261VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));22622263Emit(ADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));2264}22652266void Assembler::sqadd(const ZRegister& zd,2267const ZRegister& zn,2268const ZRegister& zm) {2269// SQADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>2270// 0000 0100 ..1. .... 0001 00.. .... ....2271// size<23:22> | Zm<20:16> | opc<12:10> = 100 | Zn<9:5> | Zd<4:0>22722273VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2274VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));22752276Emit(SQADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));2277}22782279void Assembler::sqsub(const ZRegister& zd,2280const ZRegister& zn,2281const ZRegister& zm) {2282// SQSUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>2283// 0000 0100 ..1. .... 0001 10.. .... ....2284// size<23:22> | Zm<20:16> | opc<12:10> = 110 | Zn<9:5> | Zd<4:0>22852286VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2287VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));22882289Emit(SQSUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));2290}22912292void Assembler::sub(const ZRegister& zd,2293const ZRegister& zn,2294const ZRegister& zm) {2295// SUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>2296// 0000 0100 ..1. .... 0000 01.. .... ....2297// size<23:22> | Zm<20:16> | opc<12:10> = 001 | Zn<9:5> | Zd<4:0>22982299VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2300VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));23012302Emit(SUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));2303}23042305void Assembler::uqadd(const ZRegister& zd,2306const ZRegister& zn,2307const ZRegister& zm) {2308// UQADD <Zd>.<T>, <Zn>.<T>, <Zm>.<T>2309// 0000 0100 ..1. .... 0001 01.. .... ....2310// size<23:22> | Zm<20:16> | opc<12:10> = 101 | Zn<9:5> | Zd<4:0>23112312VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2313VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));23142315Emit(UQADD_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));2316}23172318void Assembler::uqsub(const ZRegister& zd,2319const ZRegister& zn,2320const ZRegister& zm) {2321// UQSUB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>2322// 0000 0100 ..1. .... 0001 11.. .... ....2323// size<23:22> | Zm<20:16> | opc<12:10> = 111 | Zn<9:5> | Zd<4:0>23242325VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2326VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));23272328Emit(UQSUB_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));2329}23302331// SVEIntBinaryArithmeticPredicated.23322333void Assembler::add(const ZRegister& zd,2334const PRegisterM& pg,2335const ZRegister& zn,2336const ZRegister& zm) {2337// ADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2338// 0000 0100 ..00 0000 000. .... .... ....2339// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>23402341USE(zn);2342VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2343VIXL_ASSERT(zd.Is(zn));2344VIXL_ASSERT(AreSameFormat(zd, zn, zm));23452346Emit(ADD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2347}23482349void Assembler::and_(const ZRegister& zd,2350const PRegisterM& pg,2351const ZRegister& zn,2352const ZRegister& zm) {2353// AND <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2354// 0000 0100 ..01 1010 000. .... .... ....2355// size<23:22> | opc<18:16> = 010 | Pg<12:10> | Zm<9:5> | Zdn<4:0>23562357USE(zn);2358VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2359VIXL_ASSERT(zd.Is(zn));2360VIXL_ASSERT(AreSameFormat(zd, zn, zm));23612362Emit(AND_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2363}23642365void Assembler::bic(const ZRegister& zd,2366const PRegisterM& pg,2367const ZRegister& zn,2368const ZRegister& zm) {2369// BIC <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2370// 0000 0100 ..01 1011 000. .... .... ....2371// size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zm<9:5> | Zdn<4:0>23722373USE(zn);2374VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2375VIXL_ASSERT(zd.Is(zn));2376VIXL_ASSERT(AreSameFormat(zd, zn, zm));23772378Emit(BIC_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2379}23802381void Assembler::eor(const ZRegister& zd,2382const PRegisterM& pg,2383const ZRegister& zn,2384const ZRegister& zm) {2385// EOR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2386// 0000 0100 ..01 1001 000. .... .... ....2387// size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>23882389USE(zn);2390VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2391VIXL_ASSERT(zd.Is(zn));2392VIXL_ASSERT(AreSameFormat(zd, zn, zm));23932394Emit(EOR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2395}23962397void Assembler::mul(const ZRegister& zd,2398const PRegisterM& pg,2399const ZRegister& zn,2400const ZRegister& zm) {2401// MUL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2402// 0000 0100 ..01 0000 000. .... .... ....2403// size<23:22> | H<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>24042405USE(zn);2406VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2407VIXL_ASSERT(zd.Is(zn));2408VIXL_ASSERT(AreSameFormat(zd, zn, zm));24092410Emit(MUL_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2411}24122413void Assembler::orr(const ZRegister& zd,2414const PRegisterM& pg,2415const ZRegister& zn,2416const ZRegister& zm) {2417// ORR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2418// 0000 0100 ..01 1000 000. .... .... ....2419// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zm<9:5> | Zdn<4:0>24202421USE(zn);2422VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2423VIXL_ASSERT(zd.Is(zn));2424VIXL_ASSERT(AreSameFormat(zd, zn, zm));24252426Emit(ORR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2427}24282429void Assembler::sabd(const ZRegister& zd,2430const PRegisterM& pg,2431const ZRegister& zn,2432const ZRegister& zm) {2433// SABD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2434// 0000 0100 ..00 1100 000. .... .... ....2435// size<23:22> | opc<18:17> = 10 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>24362437USE(zn);2438VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2439VIXL_ASSERT(zd.Is(zn));2440VIXL_ASSERT(AreSameFormat(zd, zn, zm));24412442Emit(SABD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2443}24442445void Assembler::sdiv(const ZRegister& zd,2446const PRegisterM& pg,2447const ZRegister& zn,2448const ZRegister& zm) {2449// SDIV <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2450// 0000 0100 ..01 0100 000. .... .... ....2451// size<23:22> | R<17> = 0 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>24522453USE(zn);2454VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2455VIXL_ASSERT(zd.Is(zn));2456VIXL_ASSERT(AreSameFormat(zd, zn, zm));2457VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());24582459Emit(SDIV_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2460}24612462void Assembler::sdivr(const ZRegister& zd,2463const PRegisterM& pg,2464const ZRegister& zn,2465const ZRegister& zm) {2466// SDIVR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2467// 0000 0100 ..01 0110 000. .... .... ....2468// size<23:22> | R<17> = 1 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>24692470USE(zn);2471VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2472VIXL_ASSERT(zd.Is(zn));2473VIXL_ASSERT(AreSameFormat(zd, zn, zm));2474VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());24752476Emit(SDIVR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2477}24782479void Assembler::smax(const ZRegister& zd,2480const PRegisterM& pg,2481const ZRegister& zn,2482const ZRegister& zm) {2483// SMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2484// 0000 0100 ..00 1000 000. .... .... ....2485// size<23:22> | opc<18:17> = 00 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>24862487USE(zn);2488VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2489VIXL_ASSERT(zd.Is(zn));2490VIXL_ASSERT(AreSameFormat(zd, zn, zm));24912492Emit(SMAX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2493}24942495void Assembler::smin(const ZRegister& zd,2496const PRegisterM& pg,2497const ZRegister& zn,2498const ZRegister& zm) {2499// SMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2500// 0000 0100 ..00 1010 000. .... .... ....2501// size<23:22> | opc<18:17> = 01 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>25022503USE(zn);2504VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2505VIXL_ASSERT(zd.Is(zn));2506VIXL_ASSERT(AreSameFormat(zd, zn, zm));25072508Emit(SMIN_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2509}25102511void Assembler::smulh(const ZRegister& zd,2512const PRegisterM& pg,2513const ZRegister& zn,2514const ZRegister& zm) {2515// SMULH <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2516// 0000 0100 ..01 0010 000. .... .... ....2517// size<23:22> | H<17> = 1 | U<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>25182519USE(zn);2520VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2521VIXL_ASSERT(zd.Is(zn));2522VIXL_ASSERT(AreSameFormat(zd, zn, zm));25232524Emit(SMULH_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2525}25262527void Assembler::sub(const ZRegister& zd,2528const PRegisterM& pg,2529const ZRegister& zn,2530const ZRegister& zm) {2531// SUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2532// 0000 0100 ..00 0001 000. .... .... ....2533// size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zm<9:5> | Zdn<4:0>25342535USE(zn);2536VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2537VIXL_ASSERT(zd.Is(zn));2538VIXL_ASSERT(AreSameFormat(zd, zn, zm));25392540Emit(SUB_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2541}25422543void Assembler::subr(const ZRegister& zd,2544const PRegisterM& pg,2545const ZRegister& zn,2546const ZRegister& zm) {2547// SUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2548// 0000 0100 ..00 0011 000. .... .... ....2549// size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zm<9:5> | Zdn<4:0>25502551USE(zn);2552VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2553VIXL_ASSERT(zd.Is(zn));2554VIXL_ASSERT(AreSameFormat(zd, zn, zm));25552556Emit(SUBR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2557}25582559void Assembler::uabd(const ZRegister& zd,2560const PRegisterM& pg,2561const ZRegister& zn,2562const ZRegister& zm) {2563// UABD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2564// 0000 0100 ..00 1101 000. .... .... ....2565// size<23:22> | opc<18:17> = 10 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>25662567USE(zn);2568VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2569VIXL_ASSERT(zd.Is(zn));2570VIXL_ASSERT(AreSameFormat(zd, zn, zm));25712572Emit(UABD_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2573}25742575void Assembler::udiv(const ZRegister& zd,2576const PRegisterM& pg,2577const ZRegister& zn,2578const ZRegister& zm) {2579// UDIV <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2580// 0000 0100 ..01 0101 000. .... .... ....2581// size<23:22> | R<17> = 0 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>25822583USE(zn);2584VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2585VIXL_ASSERT(zd.Is(zn));2586VIXL_ASSERT(AreSameFormat(zd, zn, zm));2587VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());25882589Emit(UDIV_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2590}25912592void Assembler::udivr(const ZRegister& zd,2593const PRegisterM& pg,2594const ZRegister& zn,2595const ZRegister& zm) {2596// UDIVR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2597// 0000 0100 ..01 0111 000. .... .... ....2598// size<23:22> | R<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>25992600USE(zn);2601VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2602VIXL_ASSERT(zd.Is(zn));2603VIXL_ASSERT(AreSameFormat(zd, zn, zm));2604VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());26052606Emit(UDIVR_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2607}26082609void Assembler::umax(const ZRegister& zd,2610const PRegisterM& pg,2611const ZRegister& zn,2612const ZRegister& zm) {2613// UMAX <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2614// 0000 0100 ..00 1001 000. .... .... ....2615// size<23:22> | opc<18:17> = 00 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>26162617USE(zn);2618VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2619VIXL_ASSERT(zd.Is(zn));2620VIXL_ASSERT(AreSameFormat(zd, zn, zm));26212622Emit(UMAX_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2623}26242625void Assembler::umin(const ZRegister& zd,2626const PRegisterM& pg,2627const ZRegister& zn,2628const ZRegister& zm) {2629// UMIN <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2630// 0000 0100 ..00 1011 000. .... .... ....2631// size<23:22> | opc<18:17> = 01 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>26322633USE(zn);2634VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2635VIXL_ASSERT(zd.Is(zn));2636VIXL_ASSERT(AreSameFormat(zd, zn, zm));26372638Emit(UMIN_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2639}26402641void Assembler::umulh(const ZRegister& zd,2642const PRegisterM& pg,2643const ZRegister& zn,2644const ZRegister& zm) {2645// UMULH <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>2646// 0000 0100 ..01 0011 000. .... .... ....2647// size<23:22> | H<17> = 1 | U<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>26482649USE(zn);2650VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2651VIXL_ASSERT(zd.Is(zn));2652VIXL_ASSERT(AreSameFormat(zd, zn, zm));26532654Emit(UMULH_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));2655}26562657// SVEIntCompareScalars.26582659void Assembler::ctermeq(const Register& rn, const Register& rm) {2660// CTERMEQ <R><n>, <R><m>2661// 0010 0101 1.1. .... 0010 00.. ...0 00002662// op<23> = 1 | sz<22> | Rm<20:16> | Rn<9:5> | ne<4> = 026632664VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2665VIXL_ASSERT(AreSameSizeAndType(rn, rm));2666const Instr sz = rn.Is64Bits() ? 0x00400000 : 0x00000000;26672668Emit(CTERMEQ_rr | sz | Rn(rn) | Rm(rm));2669}26702671void Assembler::ctermne(const Register& rn, const Register& rm) {2672// CTERMNE <R><n>, <R><m>2673// 0010 0101 1.1. .... 0010 00.. ...1 00002674// op<23> = 1 | sz<22> | Rm<20:16> | Rn<9:5> | ne<4> = 126752676VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2677VIXL_ASSERT(AreSameSizeAndType(rn, rm));2678const Instr sz = rn.Is64Bits() ? 0x00400000 : 0x00000000;26792680Emit(CTERMNE_rr | sz | Rn(rn) | Rm(rm));2681}26822683void Assembler::whilele(const PRegisterWithLaneSize& pd,2684const Register& rn,2685const Register& rm) {2686// WHILELE <Pd>.<T>, <R><n>, <R><m>2687// 0010 0101 ..1. .... 000. 01.. ...1 ....2688// size<23:22> | Rm<20:16> | sf<12> | U<11> = 0 | lt<10> = 1 | Rn<9:5> |2689// eq<4> = 1 | Pd<3:0>26902691VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2692VIXL_ASSERT(AreSameSizeAndType(rn, rm));2693const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;26942695Emit(WHILELE_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));2696}26972698void Assembler::whilelo(const PRegisterWithLaneSize& pd,2699const Register& rn,2700const Register& rm) {2701// WHILELO <Pd>.<T>, <R><n>, <R><m>2702// 0010 0101 ..1. .... 000. 11.. ...0 ....2703// size<23:22> | Rm<20:16> | sf<12> | U<11> = 1 | lt<10> = 1 | Rn<9:5> |2704// eq<4> = 0 | Pd<3:0>27052706VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2707VIXL_ASSERT(AreSameSizeAndType(rn, rm));2708const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;27092710Emit(WHILELO_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));2711}27122713void Assembler::whilels(const PRegisterWithLaneSize& pd,2714const Register& rn,2715const Register& rm) {2716// WHILELS <Pd>.<T>, <R><n>, <R><m>2717// 0010 0101 ..1. .... 000. 11.. ...1 ....2718// size<23:22> | Rm<20:16> | sf<12> | U<11> = 1 | lt<10> = 1 | Rn<9:5> |2719// eq<4> = 1 | Pd<3:0>27202721VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2722VIXL_ASSERT(AreSameSizeAndType(rn, rm));2723const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;27242725Emit(WHILELS_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));2726}27272728void Assembler::whilelt(const PRegisterWithLaneSize& pd,2729const Register& rn,2730const Register& rm) {2731// WHILELT <Pd>.<T>, <R><n>, <R><m>2732// 0010 0101 ..1. .... 000. 01.. ...0 ....2733// size<23:22> | Rm<20:16> | sf<12> | U<11> = 0 | lt<10> = 1 | Rn<9:5> |2734// eq<4> = 0 | Pd<3:0>27352736VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2737VIXL_ASSERT(AreSameSizeAndType(rn, rm));2738const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;27392740Emit(WHILELT_p_p_rr | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));2741}27422743void Assembler::CompareVectors(const PRegisterWithLaneSize& pd,2744const PRegisterZ& pg,2745const ZRegister& zn,2746const ZRegister& zm,2747SVEIntCompareVectorsOp op) {2748Emit(op | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));2749}27502751void Assembler::CompareVectors(const PRegisterWithLaneSize& pd,2752const PRegisterZ& pg,2753const ZRegister& zn,2754int imm,2755SVEIntCompareSignedImmOp op) {2756Emit(op | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm));2757}27582759void Assembler::CompareVectors(const PRegisterWithLaneSize& pd,2760const PRegisterZ& pg,2761const ZRegister& zn,2762unsigned imm,2763SVEIntCompareUnsignedImmOp op) {2764Emit(op | SVESize(zn) | Pd(pd) | PgLow8(pg) | Rn(zn) |2765ImmUnsignedField<20, 14>(imm));2766}27672768void Assembler::cmp(Condition cond,2769const PRegisterWithLaneSize& pd,2770const PRegisterZ& pg,2771const ZRegister& zn,2772const ZRegister& zm) {2773switch (cond) {2774case eq:2775cmpeq(pd, pg, zn, zm);2776break;2777case ge:2778cmpge(pd, pg, zn, zm);2779break;2780case gt:2781cmpgt(pd, pg, zn, zm);2782break;2783case le:2784cmple(pd, pg, zn, zm);2785break;2786case lt:2787cmplt(pd, pg, zn, zm);2788break;2789case ne:2790cmpne(pd, pg, zn, zm);2791break;2792case hi:2793cmphi(pd, pg, zn, zm);2794break;2795case hs:2796cmphs(pd, pg, zn, zm);2797break;2798case lo:2799cmplo(pd, pg, zn, zm);2800break;2801case ls:2802cmpls(pd, pg, zn, zm);2803break;2804default:2805VIXL_UNREACHABLE();2806}2807}28082809// SVEIntCompareSignedImm.28102811void Assembler::cmpeq(const PRegisterWithLaneSize& pd,2812const PRegisterZ& pg,2813const ZRegister& zn,2814int imm5) {2815// CMPEQ <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2816// 0010 0101 ..0. .... 100. .... ...0 ....2817// size<23:22> | imm5<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5>2818// | ne<4> = 0 | Pd<3:0>28192820VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2821VIXL_ASSERT(AreSameLaneSize(pd, zn));28222823CompareVectors(pd, pg, zn, imm5, CMPEQ_p_p_zi);2824}28252826void Assembler::cmpge(const PRegisterWithLaneSize& pd,2827const PRegisterZ& pg,2828const ZRegister& zn,2829int imm5) {2830// CMPGE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2831// 0010 0101 ..0. .... 000. .... ...0 ....2832// size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5>2833// | ne<4> = 0 | Pd<3:0>28342835VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2836VIXL_ASSERT(AreSameLaneSize(pd, zn));28372838CompareVectors(pd, pg, zn, imm5, CMPGE_p_p_zi);2839}28402841void Assembler::cmpgt(const PRegisterWithLaneSize& pd,2842const PRegisterZ& pg,2843const ZRegister& zn,2844int imm5) {2845// CMPGT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2846// 0010 0101 ..0. .... 000. .... ...1 ....2847// size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 0 | Pg<12:10> | Zn<9:5>2848// | ne<4> = 1 | Pd<3:0>28492850VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2851VIXL_ASSERT(AreSameLaneSize(pd, zn));28522853CompareVectors(pd, pg, zn, imm5, CMPGT_p_p_zi);2854}28552856void Assembler::cmple(const PRegisterWithLaneSize& pd,2857const PRegisterZ& pg,2858const ZRegister& zn,2859int imm5) {2860// CMPLE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2861// 0010 0101 ..0. .... 001. .... ...1 ....2862// size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5>2863// | ne<4> = 1 | Pd<3:0>28642865VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2866VIXL_ASSERT(AreSameLaneSize(pd, zn));28672868CompareVectors(pd, pg, zn, imm5, CMPLE_p_p_zi);2869}28702871void Assembler::cmplt(const PRegisterWithLaneSize& pd,2872const PRegisterZ& pg,2873const ZRegister& zn,2874int imm5) {2875// CMPLT <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2876// 0010 0101 ..0. .... 001. .... ...0 ....2877// size<23:22> | imm5<20:16> | op<15> = 0 | o2<13> = 1 | Pg<12:10> | Zn<9:5>2878// | ne<4> = 0 | Pd<3:0>28792880VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2881VIXL_ASSERT(AreSameLaneSize(pd, zn));28822883CompareVectors(pd, pg, zn, imm5, CMPLT_p_p_zi);2884}28852886void Assembler::cmpne(const PRegisterWithLaneSize& pd,2887const PRegisterZ& pg,2888const ZRegister& zn,2889int imm5) {2890// CMPNE <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2891// 0010 0101 ..0. .... 100. .... ...1 ....2892// size<23:22> | imm5<20:16> | op<15> = 1 | o2<13> = 0 | Pg<12:10> | Zn<9:5>2893// | ne<4> = 1 | Pd<3:0>28942895VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2896VIXL_ASSERT(AreSameLaneSize(pd, zn));28972898CompareVectors(pd, pg, zn, imm5, CMPNE_p_p_zi);2899}29002901// SVEIntCompareUnsignedImm.29022903void Assembler::cmphi(const PRegisterWithLaneSize& pd,2904const PRegisterZ& pg,2905const ZRegister& zn,2906unsigned imm7) {2907// CMPHI <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2908// 0010 0100 ..1. .... ..0. .... ...1 ....2909// size<23:22> | imm7<20:14> | lt<13> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |2910// Pd<3:0>29112912VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2913VIXL_ASSERT(AreSameLaneSize(pd, zn));29142915CompareVectors(pd, pg, zn, imm7, CMPHI_p_p_zi);2916}29172918void Assembler::cmphs(const PRegisterWithLaneSize& pd,2919const PRegisterZ& pg,2920const ZRegister& zn,2921unsigned imm7) {2922// CMPHS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2923// 0010 0100 ..1. .... ..0. .... ...0 ....2924// size<23:22> | imm7<20:14> | lt<13> = 0 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |2925// Pd<3:0>29262927VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2928VIXL_ASSERT(AreSameLaneSize(pd, zn));29292930CompareVectors(pd, pg, zn, imm7, CMPHS_p_p_zi);2931}29322933void Assembler::cmplo(const PRegisterWithLaneSize& pd,2934const PRegisterZ& pg,2935const ZRegister& zn,2936unsigned imm7) {2937// CMPLO <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2938// 0010 0100 ..1. .... ..1. .... ...0 ....2939// size<23:22> | imm7<20:14> | lt<13> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 0 |2940// Pd<3:0>29412942VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2943VIXL_ASSERT(AreSameLaneSize(pd, zn));29442945CompareVectors(pd, pg, zn, imm7, CMPLO_p_p_zi);2946}29472948void Assembler::cmpls(const PRegisterWithLaneSize& pd,2949const PRegisterZ& pg,2950const ZRegister& zn,2951unsigned imm7) {2952// CMPLS <Pd>.<T>, <Pg>/Z, <Zn>.<T>, #<imm>2953// 0010 0100 ..1. .... ..1. .... ...1 ....2954// size<23:22> | imm7<20:14> | lt<13> = 1 | Pg<12:10> | Zn<9:5> | ne<4> = 1 |2955// Pd<3:0>29562957VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2958VIXL_ASSERT(AreSameLaneSize(pd, zn));29592960CompareVectors(pd, pg, zn, imm7, CMPLS_p_p_zi);2961}29622963// SVEIntCompareVectors.29642965// This prototype maps to 2 instruction encodings:2966// CMPEQ_p_p_zw2967// CMPEQ_p_p_zz2968void Assembler::cmpeq(const PRegisterWithLaneSize& pd,2969const PRegisterZ& pg,2970const ZRegister& zn,2971const ZRegister& zm) {2972VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2973VIXL_ASSERT(AreSameLaneSize(pd, zn));2974SVEIntCompareVectorsOp op = CMPEQ_p_p_zz;2975if (!AreSameLaneSize(zn, zm)) {2976VIXL_ASSERT(zm.IsLaneSizeD());2977op = CMPEQ_p_p_zw;2978}2979CompareVectors(pd, pg, zn, zm, op);2980}29812982// This prototype maps to 2 instruction encodings:2983// CMPGE_p_p_zw2984// CMPGE_p_p_zz2985void Assembler::cmpge(const PRegisterWithLaneSize& pd,2986const PRegisterZ& pg,2987const ZRegister& zn,2988const ZRegister& zm) {2989VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));2990VIXL_ASSERT(AreSameLaneSize(pd, zn));2991SVEIntCompareVectorsOp op = CMPGE_p_p_zz;2992if (!AreSameLaneSize(zn, zm)) {2993VIXL_ASSERT(zm.IsLaneSizeD());2994op = CMPGE_p_p_zw;2995}2996CompareVectors(pd, pg, zn, zm, op);2997}29982999// This prototype maps to 2 instruction encodings:3000// CMPGT_p_p_zw3001// CMPGT_p_p_zz3002void Assembler::cmpgt(const PRegisterWithLaneSize& pd,3003const PRegisterZ& pg,3004const ZRegister& zn,3005const ZRegister& zm) {3006VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3007VIXL_ASSERT(AreSameLaneSize(pd, zn));3008SVEIntCompareVectorsOp op = CMPGT_p_p_zz;3009if (!AreSameLaneSize(zn, zm)) {3010VIXL_ASSERT(zm.IsLaneSizeD());3011op = CMPGT_p_p_zw;3012}3013CompareVectors(pd, pg, zn, zm, op);3014}30153016// This prototype maps to 2 instruction encodings:3017// CMPHI_p_p_zw3018// CMPHI_p_p_zz3019void Assembler::cmphi(const PRegisterWithLaneSize& pd,3020const PRegisterZ& pg,3021const ZRegister& zn,3022const ZRegister& zm) {3023VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3024VIXL_ASSERT(AreSameLaneSize(pd, zn));3025SVEIntCompareVectorsOp op = CMPHI_p_p_zz;3026if (!AreSameLaneSize(zn, zm)) {3027VIXL_ASSERT(zm.IsLaneSizeD());3028op = CMPHI_p_p_zw;3029}3030CompareVectors(pd, pg, zn, zm, op);3031}30323033// This prototype maps to 2 instruction encodings:3034// CMPHS_p_p_zw3035// CMPHS_p_p_zz3036void Assembler::cmphs(const PRegisterWithLaneSize& pd,3037const PRegisterZ& pg,3038const ZRegister& zn,3039const ZRegister& zm) {3040VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3041VIXL_ASSERT(AreSameLaneSize(pd, zn));3042SVEIntCompareVectorsOp op = CMPHS_p_p_zz;3043if (!AreSameLaneSize(zn, zm)) {3044VIXL_ASSERT(zm.IsLaneSizeD());3045op = CMPHS_p_p_zw;3046}3047CompareVectors(pd, pg, zn, zm, op);3048}30493050void Assembler::cmple(const PRegisterWithLaneSize& pd,3051const PRegisterZ& pg,3052const ZRegister& zn,3053const ZRegister& zm) {3054VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3055VIXL_ASSERT(AreSameLaneSize(pd, zn));3056if (AreSameLaneSize(zn, zm)) {3057cmpge(pd, pg, zm, zn);3058return;3059}3060VIXL_ASSERT(zm.IsLaneSizeD());3061VIXL_ASSERT(!zn.IsLaneSizeD());30623063CompareVectors(pd, pg, zn, zm, CMPLE_p_p_zw);3064}30653066void Assembler::cmplo(const PRegisterWithLaneSize& pd,3067const PRegisterZ& pg,3068const ZRegister& zn,3069const ZRegister& zm) {3070VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3071VIXL_ASSERT(AreSameLaneSize(pd, zn));3072if (AreSameLaneSize(zn, zm)) {3073cmphi(pd, pg, zm, zn);3074return;3075}3076VIXL_ASSERT(zm.IsLaneSizeD());3077VIXL_ASSERT(!zn.IsLaneSizeD());30783079CompareVectors(pd, pg, zn, zm, CMPLO_p_p_zw);3080}30813082void Assembler::cmpls(const PRegisterWithLaneSize& pd,3083const PRegisterZ& pg,3084const ZRegister& zn,3085const ZRegister& zm) {3086VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3087VIXL_ASSERT(AreSameLaneSize(pd, zn));3088if (AreSameLaneSize(zn, zm)) {3089cmphs(pd, pg, zm, zn);3090return;3091}3092VIXL_ASSERT(zm.IsLaneSizeD());3093VIXL_ASSERT(!zn.IsLaneSizeD());30943095CompareVectors(pd, pg, zn, zm, CMPLS_p_p_zw);3096}30973098void Assembler::cmplt(const PRegisterWithLaneSize& pd,3099const PRegisterZ& pg,3100const ZRegister& zn,3101const ZRegister& zm) {3102VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3103VIXL_ASSERT(AreSameLaneSize(pd, zn));3104if (AreSameLaneSize(zn, zm)) {3105cmpgt(pd, pg, zm, zn);3106return;3107}3108VIXL_ASSERT(zm.IsLaneSizeD());3109VIXL_ASSERT(!zn.IsLaneSizeD());31103111CompareVectors(pd, pg, zn, zm, CMPLT_p_p_zw);3112}31133114// This prototype maps to 2 instruction encodings:3115// CMPNE_p_p_zw3116// CMPNE_p_p_zz3117void Assembler::cmpne(const PRegisterWithLaneSize& pd,3118const PRegisterZ& pg,3119const ZRegister& zn,3120const ZRegister& zm) {3121VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3122VIXL_ASSERT(AreSameLaneSize(pd, zn));3123SVEIntCompareVectorsOp op = CMPNE_p_p_zz;3124if (!AreSameLaneSize(zn, zm)) {3125VIXL_ASSERT(zm.IsLaneSizeD());3126op = CMPNE_p_p_zw;3127}3128CompareVectors(pd, pg, zn, zm, op);3129}31303131// SVEIntMiscUnpredicated.31323133void Assembler::fexpa(const ZRegister& zd, const ZRegister& zn) {3134// FEXPA <Zd>.<T>, <Zn>.<T>3135// 0000 0100 ..10 0000 1011 10.. .... ....3136// size<23:22> | opc<20:16> = 00000 | Zn<9:5> | Zd<4:0>31373138VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3139VIXL_ASSERT(AreSameLaneSize(zd, zn));3140VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);31413142Emit(FEXPA_z_z | SVESize(zd) | Rd(zd) | Rn(zn));3143}31443145void Assembler::ftssel(const ZRegister& zd,3146const ZRegister& zn,3147const ZRegister& zm) {3148// FTSSEL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>3149// 0000 0100 ..1. .... 1011 00.. .... ....3150// size<23:22> | Zm<20:16> | op<10> = 0 | Zn<9:5> | Zd<4:0>31513152VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3153VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));3154VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);31553156Emit(FTSSEL_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));3157}31583159void Assembler::movprfx(const ZRegister& zd, const ZRegister& zn) {3160// MOVPRFX <Zd>, <Zn>3161// 0000 0100 0010 0000 1011 11.. .... ....3162// opc<23:22> = 00 | opc2<20:16> = 00000 | Zn<9:5> | Zd<4:0>31633164VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3165VIXL_ASSERT(AreSameLaneSize(zd, zn));31663167Emit(MOVPRFX_z_z | Rd(zd) | Rn(zn));3168}31693170// SVEIntMulAddPredicated.31713172void Assembler::mad(const ZRegister& zdn,3173const PRegisterM& pg,3174const ZRegister& zm,3175const ZRegister& za) {3176// MAD <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>3177// 0000 0100 ..0. .... 110. .... .... ....3178// size<23:22> | Zm<20:16> | op<13> = 0 | Pg<12:10> | Za<9:5> | Zdn<4:0>31793180VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3181VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));31823183Emit(MAD_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rm(zm) | Rn(za));3184}31853186void Assembler::mla(const ZRegister& zda,3187const PRegisterM& pg,3188const ZRegister& zn,3189const ZRegister& zm) {3190// MLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>3191// 0000 0100 ..0. .... 010. .... .... ....3192// size<23:22> | Zm<20:16> | op<13> = 0 | Pg<12:10> | Zn<9:5> | Zda<4:0>31933194VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3195VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));31963197Emit(MLA_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));3198}31993200void Assembler::mls(const ZRegister& zda,3201const PRegisterM& pg,3202const ZRegister& zn,3203const ZRegister& zm) {3204// MLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>3205// 0000 0100 ..0. .... 011. .... .... ....3206// size<23:22> | Zm<20:16> | op<13> = 1 | Pg<12:10> | Zn<9:5> | Zda<4:0>32073208VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3209VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));32103211Emit(MLS_z_p_zzz | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn) | Rm(zm));3212}32133214void Assembler::msb(const ZRegister& zdn,3215const PRegisterM& pg,3216const ZRegister& zm,3217const ZRegister& za) {3218// MSB <Zdn>.<T>, <Pg>/M, <Zm>.<T>, <Za>.<T>3219// 0000 0100 ..0. .... 111. .... .... ....3220// size<23:22> | Zm<20:16> | op<13> = 1 | Pg<12:10> | Za<9:5> | Zdn<4:0>32213222VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3223VIXL_ASSERT(AreSameLaneSize(zdn, zm, za));32243225Emit(MSB_z_p_zzz | SVESize(zdn) | Rd(zdn) | PgLow8(pg) | Rm(zm) | Rn(za));3226}32273228// SVEIntMulAddUnpredicated.32293230void Assembler::sdot(const ZRegister& zda,3231const ZRegister& zn,3232const ZRegister& zm) {3233VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3234VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());3235VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));3236VIXL_ASSERT(AreSameLaneSize(zm, zn));32373238Emit(SDOT_z_zzz | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));3239}32403241void Assembler::udot(const ZRegister& zda,3242const ZRegister& zn,3243const ZRegister& zm) {3244VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3245VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());3246VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));3247VIXL_ASSERT(AreSameLaneSize(zm, zn));32483249Emit(UDOT_z_zzz | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));3250}32513252// SVEIntReduction.32533254void Assembler::andv(const VRegister& vd,3255const PRegister& pg,3256const ZRegister& zn) {3257VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3258VIXL_ASSERT(vd.IsScalar());32593260Emit(ANDV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));3261}32623263void Assembler::eorv(const VRegister& vd,3264const PRegister& pg,3265const ZRegister& zn) {3266VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3267VIXL_ASSERT(vd.IsScalar());32683269Emit(EORV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));3270}32713272void Assembler::movprfx(const ZRegister& zd,3273const PRegister& pg,3274const ZRegister& zn) {3275// MOVPRFX <Zd>.<T>, <Pg>/<ZM>, <Zn>.<T>3276// 0000 0100 ..01 000. 001. .... .... ....3277// size<23:22> | opc<18:17> = 00 | M<16> | Pg<12:10> | Zn<9:5> | Zd<4:0>32783279VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3280VIXL_ASSERT(AreSameLaneSize(zd, zn));3281VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());3282VIXL_ASSERT(!pg.HasLaneSize());32833284Instr m = pg.IsMerging() ? 0x00010000 : 0x00000000;3285Emit(MOVPRFX_z_p_z | SVESize(zd) | m | Rd(zd) | PgLow8(pg) | Rn(zn));3286}32873288void Assembler::orv(const VRegister& vd,3289const PRegister& pg,3290const ZRegister& zn) {3291VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3292VIXL_ASSERT(vd.IsScalar());32933294Emit(ORV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));3295}32963297void Assembler::saddv(const VRegister& dd,3298const PRegister& pg,3299const ZRegister& zn) {3300VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3301VIXL_ASSERT(zn.GetLaneSizeInBytes() != kDRegSizeInBytes);33023303Emit(SADDV_r_p_z | SVESize(zn) | Rd(dd) | PgLow8(pg) | Rn(zn));3304}33053306void Assembler::smaxv(const VRegister& vd,3307const PRegister& pg,3308const ZRegister& zn) {3309VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3310VIXL_ASSERT(vd.IsScalar());33113312Emit(SMAXV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));3313}33143315void Assembler::sminv(const VRegister& vd,3316const PRegister& pg,3317const ZRegister& zn) {3318VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3319VIXL_ASSERT(vd.IsScalar());33203321Emit(SMINV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));3322}33233324void Assembler::uaddv(const VRegister& dd,3325const PRegister& pg,3326const ZRegister& zn) {3327VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));33283329Emit(UADDV_r_p_z | SVESize(zn) | Rd(dd) | PgLow8(pg) | Rn(zn));3330}33313332void Assembler::umaxv(const VRegister& vd,3333const PRegister& pg,3334const ZRegister& zn) {3335VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3336VIXL_ASSERT(vd.IsScalar());33373338Emit(UMAXV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));3339}33403341void Assembler::uminv(const VRegister& vd,3342const PRegister& pg,3343const ZRegister& zn) {3344VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3345VIXL_ASSERT(vd.IsScalar());33463347Emit(UMINV_r_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));3348}33493350// SVEIntUnaryArithmeticPredicated.33513352void Assembler::abs(const ZRegister& zd,3353const PRegisterM& pg,3354const ZRegister& zn) {3355// ABS <Zd>.<T>, <Pg>/M, <Zn>.<T>3356// 0000 0100 ..01 0110 101. .... .... ....3357// size<23:22> | opc<18:16> = 110 | Pg<12:10> | Zn<9:5> | Zd<4:0>33583359VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3360VIXL_ASSERT(AreSameLaneSize(zd, zn));33613362Emit(ABS_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3363}33643365void Assembler::cls(const ZRegister& zd,3366const PRegisterM& pg,3367const ZRegister& zn) {3368// CLS <Zd>.<T>, <Pg>/M, <Zn>.<T>3369// 0000 0100 ..01 1000 101. .... .... ....3370// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zn<9:5> | Zd<4:0>33713372VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3373VIXL_ASSERT(AreSameLaneSize(zd, zn));33743375Emit(CLS_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3376}33773378void Assembler::clz(const ZRegister& zd,3379const PRegisterM& pg,3380const ZRegister& zn) {3381// CLZ <Zd>.<T>, <Pg>/M, <Zn>.<T>3382// 0000 0100 ..01 1001 101. .... .... ....3383// size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zn<9:5> | Zd<4:0>33843385VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3386VIXL_ASSERT(AreSameLaneSize(zd, zn));33873388Emit(CLZ_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3389}33903391void Assembler::cnot(const ZRegister& zd,3392const PRegisterM& pg,3393const ZRegister& zn) {3394// CNOT <Zd>.<T>, <Pg>/M, <Zn>.<T>3395// 0000 0100 ..01 1011 101. .... .... ....3396// size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zn<9:5> | Zd<4:0>33973398VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3399VIXL_ASSERT(AreSameLaneSize(zd, zn));34003401Emit(CNOT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3402}34033404void Assembler::cnt(const ZRegister& zd,3405const PRegisterM& pg,3406const ZRegister& zn) {3407// CNT <Zd>.<T>, <Pg>/M, <Zn>.<T>3408// 0000 0100 ..01 1010 101. .... .... ....3409// size<23:22> | opc<18:16> = 010 | Pg<12:10> | Zn<9:5> | Zd<4:0>34103411VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3412VIXL_ASSERT(AreSameLaneSize(zd, zn));34133414Emit(CNT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3415}34163417void Assembler::fabs(const ZRegister& zd,3418const PRegisterM& pg,3419const ZRegister& zn) {3420// FABS <Zd>.<T>, <Pg>/M, <Zn>.<T>3421// 0000 0100 ..01 1100 101. .... .... ....3422// size<23:22> | opc<18:16> = 100 | Pg<12:10> | Zn<9:5> | Zd<4:0>34233424VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3425VIXL_ASSERT(AreSameLaneSize(zd, zn));3426VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);34273428Emit(FABS_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3429}34303431void Assembler::fneg(const ZRegister& zd,3432const PRegisterM& pg,3433const ZRegister& zn) {3434// FNEG <Zd>.<T>, <Pg>/M, <Zn>.<T>3435// 0000 0100 ..01 1101 101. .... .... ....3436// size<23:22> | opc<18:16> = 101 | Pg<12:10> | Zn<9:5> | Zd<4:0>34373438VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3439VIXL_ASSERT(AreSameLaneSize(zd, zn));3440VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);34413442Emit(FNEG_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3443}34443445void Assembler::neg(const ZRegister& zd,3446const PRegisterM& pg,3447const ZRegister& zn) {3448// NEG <Zd>.<T>, <Pg>/M, <Zn>.<T>3449// 0000 0100 ..01 0111 101. .... .... ....3450// size<23:22> | opc<18:16> = 111 | Pg<12:10> | Zn<9:5> | Zd<4:0>34513452VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3453VIXL_ASSERT(AreSameLaneSize(zd, zn));34543455Emit(NEG_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3456}34573458void Assembler::not_(const ZRegister& zd,3459const PRegisterM& pg,3460const ZRegister& zn) {3461// NOT <Zd>.<T>, <Pg>/M, <Zn>.<T>3462// 0000 0100 ..01 1110 101. .... .... ....3463// size<23:22> | opc<18:16> = 110 | Pg<12:10> | Zn<9:5> | Zd<4:0>34643465VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3466VIXL_ASSERT(AreSameLaneSize(zd, zn));34673468Emit(NOT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3469}34703471void Assembler::sxtb(const ZRegister& zd,3472const PRegisterM& pg,3473const ZRegister& zn) {3474// SXTB <Zd>.<T>, <Pg>/M, <Zn>.<T>3475// 0000 0100 ..01 0000 101. .... .... ....3476// size<23:22> | opc<18:16> = 000 | Pg<12:10> | Zn<9:5> | Zd<4:0>34773478VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3479VIXL_ASSERT(AreSameLaneSize(zd, zn));3480VIXL_ASSERT(zd.GetLaneSizeInBytes() > kBRegSizeInBytes);34813482Emit(SXTB_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3483}34843485void Assembler::sxth(const ZRegister& zd,3486const PRegisterM& pg,3487const ZRegister& zn) {3488// SXTH <Zd>.<T>, <Pg>/M, <Zn>.<T>3489// 0000 0100 ..01 0010 101. .... .... ....3490// size<23:22> | opc<18:16> = 010 | Pg<12:10> | Zn<9:5> | Zd<4:0>34913492VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3493VIXL_ASSERT(AreSameLaneSize(zd, zn));3494VIXL_ASSERT(zd.GetLaneSizeInBytes() > kHRegSizeInBytes);34953496Emit(SXTH_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3497}34983499void Assembler::sxtw(const ZRegister& zd,3500const PRegisterM& pg,3501const ZRegister& zn) {3502// SXTW <Zd>.D, <Pg>/M, <Zn>.D3503// 0000 0100 ..01 0100 101. .... .... ....3504// size<23:22> | opc<18:16> = 100 | Pg<12:10> | Zn<9:5> | Zd<4:0>35053506VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3507VIXL_ASSERT(AreSameLaneSize(zd, zn));3508VIXL_ASSERT(zd.GetLaneSizeInBytes() > kSRegSizeInBytes);35093510Emit(SXTW_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3511}35123513void Assembler::uxtb(const ZRegister& zd,3514const PRegisterM& pg,3515const ZRegister& zn) {3516// UXTB <Zd>.<T>, <Pg>/M, <Zn>.<T>3517// 0000 0100 ..01 0001 101. .... .... ....3518// size<23:22> | opc<18:16> = 001 | Pg<12:10> | Zn<9:5> | Zd<4:0>35193520VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3521VIXL_ASSERT(AreSameLaneSize(zd, zn));3522VIXL_ASSERT(zd.GetLaneSizeInBytes() > kBRegSizeInBytes);35233524Emit(UXTB_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3525}35263527void Assembler::uxth(const ZRegister& zd,3528const PRegisterM& pg,3529const ZRegister& zn) {3530// UXTH <Zd>.<T>, <Pg>/M, <Zn>.<T>3531// 0000 0100 ..01 0011 101. .... .... ....3532// size<23:22> | opc<18:16> = 011 | Pg<12:10> | Zn<9:5> | Zd<4:0>35333534VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3535VIXL_ASSERT(AreSameLaneSize(zd, zn));3536VIXL_ASSERT(zd.GetLaneSizeInBytes() > kHRegSizeInBytes);35373538Emit(UXTH_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3539}35403541void Assembler::uxtw(const ZRegister& zd,3542const PRegisterM& pg,3543const ZRegister& zn) {3544// UXTW <Zd>.D, <Pg>/M, <Zn>.D3545// 0000 0100 ..01 0101 101. .... .... ....3546// size<23:22> | opc<18:16> = 101 | Pg<12:10> | Zn<9:5> | Zd<4:0>35473548VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3549VIXL_ASSERT(AreSameLaneSize(zd, zn));3550VIXL_ASSERT(zd.GetLaneSizeInBytes() > kSRegSizeInBytes);35513552Emit(UXTW_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));3553}35543555// SVEIntWideImmPredicated.35563557void Assembler::cpy(const ZRegister& zd,3558const PRegister& pg,3559int imm8,3560int shift) {3561// CPY <Zd>.<T>, <Pg>/<ZM>, #<imm>{, <shift>}3562// 0000 0101 ..01 .... 0... .... .... ....3563// size<23:22> | Pg<19:16> | M<14> | sh<13> | imm8<12:5> | Zd<4:0>35643565VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3566VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());35673568ResolveSVEImm8Shift(&imm8, &shift);35693570Instr sh = (shift > 0) ? (1 << 13) : 0;3571Instr m = pg.IsMerging() ? (1 << 14) : 0;3572Emit(CPY_z_p_i | m | sh | SVESize(zd) | Rd(zd) | Pg<19, 16>(pg) |3573ImmField<12, 5>(imm8));3574}35753576void Assembler::fcpy(const ZRegister& zd, const PRegisterM& pg, double imm) {3577// FCPY <Zd>.<T>, <Pg>/M, #<const>3578// 0000 0101 ..01 .... 110. .... .... ....3579// size<23:22> | Pg<19:16> | imm8<12:5> | Zd<4:0>35803581VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3582VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);35833584Instr imm_field = ImmUnsignedField<12, 5>(FP64ToImm8(imm));3585Emit(FCPY_z_p_i | SVESize(zd) | Rd(zd) | Pg<19, 16>(pg) | imm_field);3586}35873588// SVEIntAddSubtractImmUnpredicated.35893590void Assembler::SVEIntAddSubtractImmUnpredicatedHelper(3591SVEIntAddSubtractImm_UnpredicatedOp op,3592const ZRegister& zd,3593int imm8,3594int shift) {3595if (shift < 0) {3596VIXL_ASSERT(shift == -1);3597// Derive the shift amount from the immediate.3598if (IsUint8(imm8)) {3599shift = 0;3600} else if (IsUint16(imm8) && ((imm8 % 256) == 0)) {3601imm8 /= 256;3602shift = 8;3603}3604}36053606VIXL_ASSERT(IsUint8(imm8));3607VIXL_ASSERT((shift == 0) || (shift == 8));36083609Instr shift_bit = (shift > 0) ? (1 << 13) : 0;3610Emit(op | SVESize(zd) | Rd(zd) | shift_bit | ImmUnsignedField<12, 5>(imm8));3611}36123613void Assembler::add(const ZRegister& zd,3614const ZRegister& zn,3615int imm8,3616int shift) {3617// ADD <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}3618// 0010 0101 ..10 0000 11.. .... .... ....3619// size<23:22> | opc<18:16> = 000 | sh<13> | imm8<12:5> | Zdn<4:0>36203621USE(zn);3622VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3623VIXL_ASSERT(zd.Is(zn));3624VIXL_ASSERT(AreSameLaneSize(zd, zn));36253626SVEIntAddSubtractImmUnpredicatedHelper(ADD_z_zi, zd, imm8, shift);3627}36283629void Assembler::dup(const ZRegister& zd, int imm8, int shift) {3630// DUP <Zd>.<T>, #<imm>{, <shift>}3631// 0010 0101 ..11 1000 11.. .... .... ....3632// size<23:22> | opc<18:17> = 00 | sh<13> | imm8<12:5> | Zd<4:0>36333634VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));36353636ResolveSVEImm8Shift(&imm8, &shift);3637VIXL_ASSERT((shift < 8) || !zd.IsLaneSizeB());36383639Instr shift_bit = (shift > 0) ? (1 << 13) : 0;3640Emit(DUP_z_i | SVESize(zd) | Rd(zd) | shift_bit | ImmField<12, 5>(imm8));3641}36423643void Assembler::fdup(const ZRegister& zd, double imm) {3644// FDUP <Zd>.<T>, #<const>3645// 0010 0101 ..11 1001 110. .... .... ....3646// size<23:22> | opc<18:17> = 00 | o2<13> = 0 | imm8<12:5> | Zd<4:0>36473648VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3649VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);36503651Instr encoded_imm = FP64ToImm8(imm) << 5;3652Emit(FDUP_z_i | SVESize(zd) | encoded_imm | Rd(zd));3653}36543655void Assembler::mul(const ZRegister& zd, const ZRegister& zn, int imm8) {3656// MUL <Zdn>.<T>, <Zdn>.<T>, #<imm>3657// 0010 0101 ..11 0000 110. .... .... ....3658// size<23:22> | opc<18:16> = 000 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>36593660USE(zn);3661VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3662VIXL_ASSERT(zd.Is(zn));3663VIXL_ASSERT(AreSameLaneSize(zd, zn));36643665Emit(MUL_z_zi | SVESize(zd) | Rd(zd) | ImmField<12, 5>(imm8));3666}36673668void Assembler::smax(const ZRegister& zd, const ZRegister& zn, int imm8) {3669// SMAX <Zdn>.<T>, <Zdn>.<T>, #<imm>3670// 0010 0101 ..10 1000 110. .... .... ....3671// size<23:22> | opc<18:16> = 000 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>36723673USE(zn);3674VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3675VIXL_ASSERT(zd.Is(zn));3676VIXL_ASSERT(AreSameLaneSize(zd, zn));36773678Emit(SMAX_z_zi | SVESize(zd) | Rd(zd) | ImmField<12, 5>(imm8));3679}36803681void Assembler::smin(const ZRegister& zd, const ZRegister& zn, int imm8) {3682// SMIN <Zdn>.<T>, <Zdn>.<T>, #<imm>3683// 0010 0101 ..10 1010 110. .... .... ....3684// size<23:22> | opc<18:16> = 010 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>36853686USE(zn);3687VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3688VIXL_ASSERT(zd.Is(zn));3689VIXL_ASSERT(AreSameLaneSize(zd, zn));36903691Emit(SMIN_z_zi | SVESize(zd) | Rd(zd) | ImmField<12, 5>(imm8));3692}36933694void Assembler::sqadd(const ZRegister& zd,3695const ZRegister& zn,3696int imm8,3697int shift) {3698// SQADD <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}3699// 0010 0101 ..10 0100 11.. .... .... ....3700// size<23:22> | opc<18:16> = 100 | sh<13> | imm8<12:5> | Zdn<4:0>37013702USE(zn);3703VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3704VIXL_ASSERT(zd.Is(zn));3705VIXL_ASSERT(AreSameLaneSize(zd, zn));37063707SVEIntAddSubtractImmUnpredicatedHelper(SQADD_z_zi, zd, imm8, shift);3708}37093710void Assembler::sqsub(const ZRegister& zd,3711const ZRegister& zn,3712int imm8,3713int shift) {3714// SQSUB <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}3715// 0010 0101 ..10 0110 11.. .... .... ....3716// size<23:22> | opc<18:16> = 110 | sh<13> | imm8<12:5> | Zdn<4:0>37173718USE(zn);3719VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3720VIXL_ASSERT(zd.Is(zn));3721VIXL_ASSERT(AreSameLaneSize(zd, zn));37223723SVEIntAddSubtractImmUnpredicatedHelper(SQSUB_z_zi, zd, imm8, shift);3724}37253726void Assembler::sub(const ZRegister& zd,3727const ZRegister& zn,3728int imm8,3729int shift) {3730// SUB <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}3731// 0010 0101 ..10 0001 11.. .... .... ....3732// size<23:22> | opc<18:16> = 001 | sh<13> | imm8<12:5> | Zdn<4:0>37333734USE(zn);3735VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3736VIXL_ASSERT(zd.Is(zn));3737VIXL_ASSERT(AreSameLaneSize(zd, zn));37383739SVEIntAddSubtractImmUnpredicatedHelper(SUB_z_zi, zd, imm8, shift);3740}37413742void Assembler::subr(const ZRegister& zd,3743const ZRegister& zn,3744int imm8,3745int shift) {3746// SUBR <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}3747// 0010 0101 ..10 0011 11.. .... .... ....3748// size<23:22> | opc<18:16> = 011 | sh<13> | imm8<12:5> | Zdn<4:0>37493750USE(zn);3751VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3752VIXL_ASSERT(zd.Is(zn));3753VIXL_ASSERT(AreSameLaneSize(zd, zn));37543755SVEIntAddSubtractImmUnpredicatedHelper(SUBR_z_zi, zd, imm8, shift);3756}37573758void Assembler::umax(const ZRegister& zd, const ZRegister& zn, int imm8) {3759// UMAX <Zdn>.<T>, <Zdn>.<T>, #<imm>3760// 0010 0101 ..10 1001 110. .... .... ....3761// size<23:22> | opc<18:16> = 001 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>37623763USE(zn);3764VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3765VIXL_ASSERT(zd.Is(zn));3766VIXL_ASSERT(AreSameLaneSize(zd, zn));37673768Emit(UMAX_z_zi | SVESize(zd) | Rd(zd) | ImmUnsignedField<12, 5>(imm8));3769}37703771void Assembler::umin(const ZRegister& zd, const ZRegister& zn, int imm8) {3772// UMIN <Zdn>.<T>, <Zdn>.<T>, #<imm>3773// 0010 0101 ..10 1011 110. .... .... ....3774// size<23:22> | opc<18:16> = 011 | o2<13> = 0 | imm8<12:5> | Zdn<4:0>37753776USE(zn);3777VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3778VIXL_ASSERT(zd.Is(zn));3779VIXL_ASSERT(AreSameLaneSize(zd, zn));37803781Emit(UMIN_z_zi | SVESize(zd) | Rd(zd) | ImmUnsignedField<12, 5>(imm8));3782}37833784void Assembler::uqadd(const ZRegister& zd,3785const ZRegister& zn,3786int imm8,3787int shift) {3788// UQADD <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}3789// 0010 0101 ..10 0101 11.. .... .... ....3790// size<23:22> | opc<18:16> = 101 | sh<13> | imm8<12:5> | Zdn<4:0>37913792USE(zn);3793VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3794VIXL_ASSERT(zd.Is(zn));3795VIXL_ASSERT(AreSameLaneSize(zd, zn));37963797SVEIntAddSubtractImmUnpredicatedHelper(UQADD_z_zi, zd, imm8, shift);3798}37993800void Assembler::uqsub(const ZRegister& zd,3801const ZRegister& zn,3802int imm8,3803int shift) {3804// UQSUB <Zdn>.<T>, <Zdn>.<T>, #<imm>{, <shift>}3805// 0010 0101 ..10 0111 11.. .... .... ....3806// size<23:22> | opc<18:16> = 111 | sh<13> | imm8<12:5> | Zdn<4:0>38073808USE(zn);3809VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));3810VIXL_ASSERT(zd.Is(zn));3811VIXL_ASSERT(AreSameLaneSize(zd, zn));38123813SVEIntAddSubtractImmUnpredicatedHelper(UQSUB_z_zi, zd, imm8, shift);3814}38153816// SVEMemLoad.38173818void Assembler::SVELdSt1Helper(unsigned msize_in_bytes_log2,3819const ZRegister& zt,3820const PRegister& pg,3821const SVEMemOperand& addr,3822bool is_signed,3823Instr op) {3824VIXL_ASSERT(addr.IsContiguous());38253826Instr mem_op = SVEMemOperandHelper(msize_in_bytes_log2, 1, addr);3827Instr dtype =3828SVEDtype(msize_in_bytes_log2, zt.GetLaneSizeInBytesLog2(), is_signed);3829Emit(op | mem_op | dtype | Rt(zt) | PgLow8(pg));3830}38313832void Assembler::SVELdSt234Helper(int num_regs,3833const ZRegister& zt1,3834const PRegister& pg,3835const SVEMemOperand& addr,3836Instr op) {3837VIXL_ASSERT((num_regs >= 2) && (num_regs <= 4));38383839unsigned msize_in_bytes_log2 = zt1.GetLaneSizeInBytesLog2();3840Instr num = (num_regs - 1) << 21;3841Instr msz = msize_in_bytes_log2 << 23;3842Instr mem_op = SVEMemOperandHelper(msize_in_bytes_log2, num_regs, addr);3843Emit(op | mem_op | msz | num | Rt(zt1) | PgLow8(pg));3844}38453846void Assembler::SVELd1Helper(unsigned msize_in_bytes_log2,3847const ZRegister& zt,3848const PRegisterZ& pg,3849const SVEMemOperand& addr,3850bool is_signed) {3851VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() >= msize_in_bytes_log2);3852if (is_signed) {3853// Sign-extension is only possible when the vector elements are larger than3854// the elements in memory.3855VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() != msize_in_bytes_log2);3856}38573858if (addr.IsScatterGather()) {3859bool is_load = true;3860bool is_ff = false;3861SVEScatterGatherHelper(msize_in_bytes_log2,3862zt,3863pg,3864addr,3865is_load,3866is_signed,3867is_ff);3868return;3869}38703871Instr op = 0xffffffff;3872if (addr.IsScalarPlusImmediate()) {3873op = SVEContiguousLoad_ScalarPlusImmFixed;3874} else if (addr.IsScalarPlusScalar()) {3875// Rm must not be xzr.3876VIXL_ASSERT(!addr.GetScalarOffset().IsZero());3877op = SVEContiguousLoad_ScalarPlusScalarFixed;3878} else {3879VIXL_UNIMPLEMENTED();3880}3881SVELdSt1Helper(msize_in_bytes_log2, zt, pg, addr, is_signed, op);3882}38833884void Assembler::SVELdff1Helper(unsigned msize_in_bytes_log2,3885const ZRegister& zt,3886const PRegisterZ& pg,3887const SVEMemOperand& addr,3888bool is_signed) {3889VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() >= msize_in_bytes_log2);3890if (is_signed) {3891// Sign-extension is only possible when the vector elements are larger than3892// the elements in memory.3893VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() != msize_in_bytes_log2);3894}38953896if (addr.IsScatterGather()) {3897bool is_load = true;3898bool is_ff = true;3899SVEScatterGatherHelper(msize_in_bytes_log2,3900zt,3901pg,3902addr,3903is_load,3904is_signed,3905is_ff);3906return;3907}39083909if (addr.IsPlainScalar()) {3910// SVEMemOperand(x0) is treated as a scalar-plus-immediate form ([x0, #0]).3911// In these instructions, we want to treat it as [x0, xzr].3912SVEMemOperand addr_scalar_plus_scalar(addr.GetScalarBase(), xzr);3913// Guard against infinite recursion.3914VIXL_ASSERT(!addr_scalar_plus_scalar.IsPlainScalar());3915SVELdff1Helper(msize_in_bytes_log2,3916zt,3917pg,3918addr_scalar_plus_scalar,3919is_signed);3920return;3921}39223923Instr op = 0xffffffff;3924if (addr.IsScalarPlusScalar()) {3925op = SVEContiguousFirstFaultLoad_ScalarPlusScalarFixed;3926} else {3927VIXL_UNIMPLEMENTED();3928}3929SVELdSt1Helper(msize_in_bytes_log2, zt, pg, addr, is_signed, op);3930}39313932void Assembler::SVEScatterGatherHelper(unsigned msize_in_bytes_log2,3933const ZRegister& zt,3934const PRegister& pg,3935const SVEMemOperand& addr,3936bool is_load,3937bool is_signed,3938bool is_first_fault) {3939VIXL_ASSERT(addr.IsScatterGather());3940VIXL_ASSERT(zt.IsLaneSizeS() || zt.IsLaneSizeD());3941VIXL_ASSERT(is_load || !is_first_fault);3942VIXL_ASSERT(is_load || !is_signed);39433944Instr op = 0xffffffff;3945if (addr.IsVectorPlusImmediate()) {3946VIXL_ASSERT(AreSameLaneSize(zt, addr.GetVectorBase()));3947if (is_load) {3948if (zt.IsLaneSizeS()) {3949op = SVE32BitGatherLoad_VectorPlusImmFixed;3950} else {3951op = SVE64BitGatherLoad_VectorPlusImmFixed;3952}3953} else {3954if (zt.IsLaneSizeS()) {3955op = SVE32BitScatterStore_VectorPlusImmFixed;3956} else {3957op = SVE64BitScatterStore_VectorPlusImmFixed;3958}3959}3960} else {3961VIXL_ASSERT(addr.IsScalarPlusVector());3962VIXL_ASSERT(AreSameLaneSize(zt, addr.GetVectorOffset()));3963SVEOffsetModifier mod = addr.GetOffsetModifier();3964if (zt.IsLaneSizeS()) {3965VIXL_ASSERT((mod == SVE_UXTW) || (mod == SVE_SXTW));3966unsigned shift_amount = addr.GetShiftAmount();3967if (shift_amount == 0) {3968if (is_load) {3969op = SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsFixed;3970} else {3971op = SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsFixed;3972}3973} else if (shift_amount == 1) {3974VIXL_ASSERT(msize_in_bytes_log2 == kHRegSizeInBytesLog2);3975if (is_load) {3976op = SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsFixed;3977} else {3978op = SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsFixed;3979}3980} else {3981VIXL_ASSERT(shift_amount == 2);3982VIXL_ASSERT(msize_in_bytes_log2 == kSRegSizeInBytesLog2);3983if (is_load) {3984op = SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsFixed;3985} else {3986op = SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsFixed;3987}3988}3989} else if (zt.IsLaneSizeD()) {3990switch (mod) {3991case NO_SVE_OFFSET_MODIFIER:3992if (is_load) {3993op = SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsFixed;3994} else {3995op = SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsFixed;3996}3997break;3998case SVE_LSL:3999if (is_load) {4000op = SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsFixed;4001} else {4002op = SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsFixed;4003}4004break;4005case SVE_UXTW:4006case SVE_SXTW: {4007unsigned shift_amount = addr.GetShiftAmount();4008if (shift_amount == 0) {4009if (is_load) {4010op =4011SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsFixed;4012} else {4013op =4014SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsFixed;4015}4016} else {4017VIXL_ASSERT(shift_amount == msize_in_bytes_log2);4018if (is_load) {4019op = SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsFixed;4020} else {4021op =4022SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsFixed;4023}4024}4025break;4026}4027default:4028VIXL_UNIMPLEMENTED();4029}4030}4031}40324033Instr mem_op = SVEMemOperandHelper(msize_in_bytes_log2, 1, addr, is_load);4034Instr msz = ImmUnsignedField<24, 23>(msize_in_bytes_log2);4035Instr u = (!is_load || is_signed) ? 0 : (1 << 14);4036Instr ff = is_first_fault ? (1 << 13) : 0;4037Emit(op | mem_op | msz | u | ff | Rt(zt) | PgLow8(pg));4038}40394040void Assembler::SVELd234Helper(int num_regs,4041const ZRegister& zt1,4042const PRegisterZ& pg,4043const SVEMemOperand& addr) {4044if (addr.IsScalarPlusScalar()) {4045// Rm must not be xzr.4046VIXL_ASSERT(!addr.GetScalarOffset().IsZero());4047}40484049Instr op;4050if (addr.IsScalarPlusImmediate()) {4051op = SVELoadMultipleStructures_ScalarPlusImmFixed;4052} else if (addr.IsScalarPlusScalar()) {4053op = SVELoadMultipleStructures_ScalarPlusScalarFixed;4054} else {4055// These instructions don't support any other addressing modes.4056VIXL_ABORT();4057}4058SVELdSt234Helper(num_regs, zt1, pg, addr, op);4059}40604061// SVEMemContiguousLoad.40624063#define VIXL_DEFINE_LD1(MSZ, LANE_SIZE) \4064void Assembler::ld1##MSZ(const ZRegister& zt, \4065const PRegisterZ& pg, \4066const SVEMemOperand& addr) { \4067VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \4068SVELd1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, false); \4069}4070#define VIXL_DEFINE_LD2(MSZ, LANE_SIZE) \4071void Assembler::ld2##MSZ(const ZRegister& zt1, \4072const ZRegister& zt2, \4073const PRegisterZ& pg, \4074const SVEMemOperand& addr) { \4075USE(zt2); \4076VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \4077VIXL_ASSERT(AreConsecutive(zt1, zt2)); \4078VIXL_ASSERT(AreSameFormat(zt1, zt2)); \4079VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \4080SVELd234Helper(2, zt1, pg, addr); \4081}4082#define VIXL_DEFINE_LD3(MSZ, LANE_SIZE) \4083void Assembler::ld3##MSZ(const ZRegister& zt1, \4084const ZRegister& zt2, \4085const ZRegister& zt3, \4086const PRegisterZ& pg, \4087const SVEMemOperand& addr) { \4088USE(zt2, zt3); \4089VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \4090VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3)); \4091VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3)); \4092VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \4093SVELd234Helper(3, zt1, pg, addr); \4094}4095#define VIXL_DEFINE_LD4(MSZ, LANE_SIZE) \4096void Assembler::ld4##MSZ(const ZRegister& zt1, \4097const ZRegister& zt2, \4098const ZRegister& zt3, \4099const ZRegister& zt4, \4100const PRegisterZ& pg, \4101const SVEMemOperand& addr) { \4102USE(zt2, zt3, zt4); \4103VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \4104VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3, zt4)); \4105VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3, zt4)); \4106VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \4107SVELd234Helper(4, zt1, pg, addr); \4108}41094110VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD1)4111VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD2)4112VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD3)4113VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LD4)41144115#define VIXL_DEFINE_LD1S(MSZ, LANE_SIZE) \4116void Assembler::ld1s##MSZ(const ZRegister& zt, \4117const PRegisterZ& pg, \4118const SVEMemOperand& addr) { \4119VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \4120SVELd1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, true); \4121}4122VIXL_SVE_LOAD_STORE_SIGNED_VARIANT_LIST(VIXL_DEFINE_LD1S)41234124// SVEMem32BitGatherAndUnsizedContiguous.41254126void Assembler::SVELd1BroadcastHelper(unsigned msize_in_bytes_log2,4127const ZRegister& zt,4128const PRegisterZ& pg,4129const SVEMemOperand& addr,4130bool is_signed) {4131VIXL_ASSERT(addr.IsScalarPlusImmediate());4132VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() >= msize_in_bytes_log2);4133if (is_signed) {4134// Sign-extension is only possible when the vector elements are larger than4135// the elements in memory.4136VIXL_ASSERT(zt.GetLaneSizeInBytesLog2() != msize_in_bytes_log2);4137}41384139int64_t imm = addr.GetImmediateOffset();4140int divisor = 1 << msize_in_bytes_log2;4141VIXL_ASSERT(imm % divisor == 0);4142Instr dtype = SVEDtypeSplit(msize_in_bytes_log2,4143zt.GetLaneSizeInBytesLog2(),4144is_signed);41454146Emit(SVELoadAndBroadcastElementFixed | dtype | RnSP(addr.GetScalarBase()) |4147ImmUnsignedField<21, 16>(imm / divisor) | Rt(zt) | PgLow8(pg));4148}41494150// This prototype maps to 4 instruction encodings:4151// LD1RB_z_p_bi_u164152// LD1RB_z_p_bi_u324153// LD1RB_z_p_bi_u644154// LD1RB_z_p_bi_u84155void Assembler::ld1rb(const ZRegister& zt,4156const PRegisterZ& pg,4157const SVEMemOperand& addr) {4158VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));41594160SVELd1BroadcastHelper(kBRegSizeInBytesLog2, zt, pg, addr, false);4161}41624163// This prototype maps to 3 instruction encodings:4164// LD1RH_z_p_bi_u164165// LD1RH_z_p_bi_u324166// LD1RH_z_p_bi_u644167void Assembler::ld1rh(const ZRegister& zt,4168const PRegisterZ& pg,4169const SVEMemOperand& addr) {4170VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));41714172SVELd1BroadcastHelper(kHRegSizeInBytesLog2, zt, pg, addr, false);4173}41744175// This prototype maps to 2 instruction encodings:4176// LD1RW_z_p_bi_u324177// LD1RW_z_p_bi_u644178void Assembler::ld1rw(const ZRegister& zt,4179const PRegisterZ& pg,4180const SVEMemOperand& addr) {4181VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));41824183SVELd1BroadcastHelper(kSRegSizeInBytesLog2, zt, pg, addr, false);4184}41854186void Assembler::ld1rd(const ZRegister& zt,4187const PRegisterZ& pg,4188const SVEMemOperand& addr) {4189VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));41904191SVELd1BroadcastHelper(kDRegSizeInBytesLog2, zt, pg, addr, false);4192}41934194// This prototype maps to 3 instruction encodings:4195// LD1RSB_z_p_bi_s164196// LD1RSB_z_p_bi_s324197// LD1RSB_z_p_bi_s644198void Assembler::ld1rsb(const ZRegister& zt,4199const PRegisterZ& pg,4200const SVEMemOperand& addr) {4201VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));42024203SVELd1BroadcastHelper(kBRegSizeInBytesLog2, zt, pg, addr, true);4204}42054206// This prototype maps to 2 instruction encodings:4207// LD1RSH_z_p_bi_s324208// LD1RSH_z_p_bi_s644209void Assembler::ld1rsh(const ZRegister& zt,4210const PRegisterZ& pg,4211const SVEMemOperand& addr) {4212VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));42134214SVELd1BroadcastHelper(kHRegSizeInBytesLog2, zt, pg, addr, true);4215}42164217void Assembler::ld1rsw(const ZRegister& zt,4218const PRegisterZ& pg,4219const SVEMemOperand& addr) {4220VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));42214222SVELd1BroadcastHelper(kWRegSizeInBytesLog2, zt, pg, addr, true);4223}42244225void Assembler::ldr(const CPURegister& rt, const SVEMemOperand& addr) {4226// LDR <Pt/Zt>, [<Xn|SP>{, #<imm>, MUL VL}]42274228VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4229VIXL_ASSERT(rt.IsPRegister() || rt.IsZRegister());4230VIXL_ASSERT(addr.IsPlainScalar() ||4231(addr.IsScalarPlusImmediate() &&4232(addr.GetOffsetModifier() == SVE_MUL_VL)));4233int64_t imm9 = addr.GetImmediateOffset();4234VIXL_ASSERT(IsInt9(imm9));4235Instr imm9l = ExtractUnsignedBitfield32(2, 0, imm9) << 10;4236Instr imm9h = ExtractUnsignedBitfield32(8, 3, imm9) << 16;42374238Instr op = LDR_z_bi;4239if (rt.IsPRegister()) {4240op = LDR_p_bi;4241}4242Emit(op | Rt(rt) | RnSP(addr.GetScalarBase()) | imm9h | imm9l);4243}42444245// SVEMem64BitGather.42464247// This prototype maps to 3 instruction encodings:4248// LDFF1B_z_p_bz_d_64_unscaled4249// LDFF1B_z_p_bz_d_x32_unscaled4250void Assembler::ldff1b(const ZRegister& zt,4251const PRegisterZ& pg,4252const Register& xn,4253const ZRegister& zm) {4254// LDFF1B { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D]4255// 1100 0100 010. .... 111. .... .... ....4256// msz<24:23> = 00 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>4257// | Zt<4:0>42584259VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));42604261Emit(LDFF1B_z_p_bz_d_64_unscaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));4262}42634264// This prototype maps to 2 instruction encodings:4265// LDFF1B_z_p_ai_d4266// LDFF1B_z_p_ai_s4267void Assembler::ldff1b(const ZRegister& zt,4268const PRegisterZ& pg,4269const ZRegister& zn,4270int imm5) {4271// LDFF1B { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]4272// 1100 0100 001. .... 111. .... .... ....4273// msz<24:23> = 00 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |4274// Zn<9:5> | Zt<4:0>42754276VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));42774278Emit(LDFF1B_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));4279}42804281// This prototype maps to 4 instruction encodings:4282// LDFF1D_z_p_bz_d_64_scaled4283// LDFF1D_z_p_bz_d_64_unscaled4284// LDFF1D_z_p_bz_d_x32_scaled4285// LDFF1D_z_p_bz_d_x32_unscaled4286void Assembler::ldff1d(const ZRegister& zt,4287const PRegisterZ& pg,4288const Register& xn,4289const ZRegister& zm) {4290// LDFF1D { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #3]4291// 1100 0101 111. .... 111. .... .... ....4292// msz<24:23> = 11 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>4293// | Zt<4:0>42944295VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));42964297Emit(LDFF1D_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));4298}42994300void Assembler::ldff1d(const ZRegister& zt,4301const PRegisterZ& pg,4302const ZRegister& zn,4303int imm5) {4304// LDFF1D { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]4305// 1100 0101 101. .... 111. .... .... ....4306// msz<24:23> = 11 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |4307// Zn<9:5> | Zt<4:0>43084309VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));43104311Emit(LDFF1D_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));4312}43134314// This prototype maps to 6 instruction encodings:4315// LDFF1H_z_p_bz_d_64_scaled4316// LDFF1H_z_p_bz_d_64_unscaled4317// LDFF1H_z_p_bz_d_x32_scaled4318// LDFF1H_z_p_bz_d_x32_unscaled4319void Assembler::ldff1h(const ZRegister& zt,4320const PRegisterZ& pg,4321const Register& xn,4322const ZRegister& zm) {4323// LDFF1H { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #1]4324// 1100 0100 111. .... 111. .... .... ....4325// msz<24:23> = 01 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>4326// | Zt<4:0>43274328VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));43294330Emit(LDFF1H_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));4331}43324333// This prototype maps to 2 instruction encodings:4334// LDFF1H_z_p_ai_d4335// LDFF1H_z_p_ai_s4336void Assembler::ldff1h(const ZRegister& zt,4337const PRegisterZ& pg,4338const ZRegister& zn,4339int imm5) {4340// LDFF1H { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]4341// 1100 0100 101. .... 111. .... .... ....4342// msz<24:23> = 01 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |4343// Zn<9:5> | Zt<4:0>43444345VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));43464347Emit(LDFF1H_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));4348}43494350// This prototype maps to 3 instruction encodings:4351// LDFF1SB_z_p_bz_d_64_unscaled4352// LDFF1SB_z_p_bz_d_x32_unscaled4353void Assembler::ldff1sb(const ZRegister& zt,4354const PRegisterZ& pg,4355const Register& xn,4356const ZRegister& zm) {4357// LDFF1SB { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D]4358// 1100 0100 010. .... 101. .... .... ....4359// msz<24:23> = 00 | Zm<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> | Rn<9:5>4360// | Zt<4:0>43614362VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));43634364Emit(LDFF1SB_z_p_bz_d_64_unscaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));4365}43664367// This prototype maps to 2 instruction encodings:4368// LDFF1SB_z_p_ai_d4369// LDFF1SB_z_p_ai_s4370void Assembler::ldff1sb(const ZRegister& zt,4371const PRegisterZ& pg,4372const ZRegister& zn,4373int imm5) {4374// LDFF1SB { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]4375// 1100 0100 001. .... 101. .... .... ....4376// msz<24:23> = 00 | imm5<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> |4377// Zn<9:5> | Zt<4:0>43784379VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));43804381Emit(LDFF1SB_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) |4382ImmField<20, 16>(imm5));4383}43844385// This prototype maps to 6 instruction encodings:4386// LDFF1SH_z_p_bz_d_64_scaled4387// LDFF1SH_z_p_bz_d_64_unscaled4388// LDFF1SH_z_p_bz_d_x32_scaled4389// LDFF1SH_z_p_bz_d_x32_unscaled4390void Assembler::ldff1sh(const ZRegister& zt,4391const PRegisterZ& pg,4392const Register& xn,4393const ZRegister& zm) {4394// LDFF1SH { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #1]4395// 1100 0100 111. .... 101. .... .... ....4396// msz<24:23> = 01 | Zm<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> | Rn<9:5>4397// | Zt<4:0>43984399VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));44004401Emit(LDFF1SH_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));4402}44034404// This prototype maps to 2 instruction encodings:4405// LDFF1SH_z_p_ai_d4406// LDFF1SH_z_p_ai_s4407void Assembler::ldff1sh(const ZRegister& zt,4408const PRegisterZ& pg,4409const ZRegister& zn,4410int imm5) {4411// LDFF1SH { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]4412// 1100 0100 101. .... 101. .... .... ....4413// msz<24:23> = 01 | imm5<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> |4414// Zn<9:5> | Zt<4:0>44154416VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));44174418Emit(LDFF1SH_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) |4419ImmField<20, 16>(imm5));4420}44214422// This prototype maps to 4 instruction encodings:4423// LDFF1SW_z_p_bz_d_64_scaled4424// LDFF1SW_z_p_bz_d_64_unscaled4425// LDFF1SW_z_p_bz_d_x32_scaled4426// LDFF1SW_z_p_bz_d_x32_unscaled4427void Assembler::ldff1sw(const ZRegister& zt,4428const PRegisterZ& pg,4429const Register& xn,4430const ZRegister& zm) {4431// LDFF1SW { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #2]4432// 1100 0101 011. .... 101. .... .... ....4433// msz<24:23> = 10 | Zm<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> | Rn<9:5>4434// | Zt<4:0>44354436VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));44374438Emit(LDFF1SW_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));4439}44404441void Assembler::ldff1sw(const ZRegister& zt,4442const PRegisterZ& pg,4443const ZRegister& zn,4444int imm5) {4445// LDFF1SW { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]4446// 1100 0101 001. .... 101. .... .... ....4447// msz<24:23> = 10 | imm5<20:16> | U<14> = 0 | ff<13> = 1 | Pg<12:10> |4448// Zn<9:5> | Zt<4:0>44494450VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));44514452Emit(LDFF1SW_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) |4453ImmField<20, 16>(imm5));4454}44554456// This prototype maps to 6 instruction encodings:4457// LDFF1W_z_p_bz_d_64_scaled4458// LDFF1W_z_p_bz_d_64_unscaled4459// LDFF1W_z_p_bz_d_x32_scaled4460// LDFF1W_z_p_bz_d_x32_unscaled4461void Assembler::ldff1w(const ZRegister& zt,4462const PRegisterZ& pg,4463const Register& xn,4464const ZRegister& zm) {4465// LDFF1W { <Zt>.D }, <Pg>/Z, [<Xn|SP>, <Zm>.D, LSL #2]4466// 1100 0101 011. .... 111. .... .... ....4467// msz<24:23> = 10 | Zm<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> | Rn<9:5>4468// | Zt<4:0>44694470VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));44714472Emit(LDFF1W_z_p_bz_d_64_scaled | Rt(zt) | PgLow8(pg) | RnSP(xn) | Rm(zm));4473}44744475// This prototype maps to 2 instruction encodings:4476// LDFF1W_z_p_ai_d4477// LDFF1W_z_p_ai_s4478void Assembler::ldff1w(const ZRegister& zt,4479const PRegisterZ& pg,4480const ZRegister& zn,4481int imm5) {4482// LDFF1W { <Zt>.D }, <Pg>/Z, [<Zn>.D{, #<imm>}]4483// 1100 0101 001. .... 111. .... .... ....4484// msz<24:23> = 10 | imm5<20:16> | U<14> = 1 | ff<13> = 1 | Pg<12:10> |4485// Zn<9:5> | Zt<4:0>44864487VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));44884489Emit(LDFF1W_z_p_ai_d | Rt(zt) | PgLow8(pg) | Rn(zn) | ImmField<20, 16>(imm5));4490}44914492void Assembler::SVEGatherPrefetchVectorPlusImmediateHelper(4493PrefetchOperation prfop,4494const PRegister& pg,4495const SVEMemOperand& addr,4496int prefetch_size) {4497VIXL_ASSERT(addr.IsVectorPlusImmediate());4498ZRegister zn = addr.GetVectorBase();4499VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());45004501Instr op = 0xffffffff;4502switch (prefetch_size) {4503case kBRegSize:4504op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFB_i_p_ai_s)4505: static_cast<Instr>(PRFB_i_p_ai_d);4506break;4507case kHRegSize:4508op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFH_i_p_ai_s)4509: static_cast<Instr>(PRFH_i_p_ai_d);4510break;4511case kSRegSize:4512op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFW_i_p_ai_s)4513: static_cast<Instr>(PRFW_i_p_ai_d);4514break;4515case kDRegSize:4516op = zn.IsLaneSizeS() ? static_cast<Instr>(PRFD_i_p_ai_s)4517: static_cast<Instr>(PRFD_i_p_ai_d);4518break;4519default:4520VIXL_UNIMPLEMENTED();4521break;4522}45234524int64_t imm5 = addr.GetImmediateOffset();4525Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) | Rn(zn) |4526ImmUnsignedField<20, 16>(imm5));4527}45284529void Assembler::SVEGatherPrefetchScalarPlusImmediateHelper(4530PrefetchOperation prfop,4531const PRegister& pg,4532const SVEMemOperand& addr,4533int prefetch_size) {4534VIXL_ASSERT(addr.IsScalarPlusImmediate());4535int64_t imm6 = addr.GetImmediateOffset();45364537Instr op = 0xffffffff;4538switch (prefetch_size) {4539case kBRegSize:4540op = PRFB_i_p_bi_s;4541break;4542case kHRegSize:4543op = PRFH_i_p_bi_s;4544break;4545case kSRegSize:4546op = PRFW_i_p_bi_s;4547break;4548case kDRegSize:4549op = PRFD_i_p_bi_s;4550break;4551default:4552VIXL_UNIMPLEMENTED();4553break;4554}45554556Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) |4557RnSP(addr.GetScalarBase()) | ImmField<21, 16>(imm6));4558}45594560void Assembler::SVEContiguousPrefetchScalarPlusScalarHelper(4561PrefetchOperation prfop,4562const PRegister& pg,4563const SVEMemOperand& addr,4564int prefetch_size) {4565VIXL_ASSERT(addr.IsScalarPlusScalar());4566Instr op = 0xffffffff;45674568switch (prefetch_size) {4569case kBRegSize:4570VIXL_ASSERT(addr.GetOffsetModifier() == NO_SVE_OFFSET_MODIFIER);4571op = PRFB_i_p_br_s;4572break;4573case kHRegSize:4574VIXL_ASSERT(addr.GetOffsetModifier() == SVE_LSL);4575VIXL_ASSERT(addr.GetShiftAmount() == kHRegSizeInBytesLog2);4576op = PRFH_i_p_br_s;4577break;4578case kSRegSize:4579VIXL_ASSERT(addr.GetOffsetModifier() == SVE_LSL);4580VIXL_ASSERT(addr.GetShiftAmount() == kSRegSizeInBytesLog2);4581op = PRFW_i_p_br_s;4582break;4583case kDRegSize:4584VIXL_ASSERT(addr.GetOffsetModifier() == SVE_LSL);4585VIXL_ASSERT(addr.GetShiftAmount() == kDRegSizeInBytesLog2);4586op = PRFD_i_p_br_s;4587break;4588default:4589VIXL_UNIMPLEMENTED();4590break;4591}45924593VIXL_ASSERT(!addr.GetScalarOffset().IsZero());4594Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) |4595RnSP(addr.GetScalarBase()) | Rm(addr.GetScalarOffset()));4596}45974598void Assembler::SVEContiguousPrefetchScalarPlusVectorHelper(4599PrefetchOperation prfop,4600const PRegister& pg,4601const SVEMemOperand& addr,4602int prefetch_size) {4603VIXL_ASSERT(addr.IsScalarPlusVector());4604ZRegister zm = addr.GetVectorOffset();4605SVEOffsetModifier mod = addr.GetOffsetModifier();46064607// All prefetch scalar-plus-vector addressing modes use a shift corresponding4608// to the element size.4609switch (prefetch_size) {4610case kBRegSize:4611VIXL_ASSERT(addr.GetShiftAmount() == kBRegSizeInBytesLog2);4612break;4613case kHRegSize:4614VIXL_ASSERT(addr.GetShiftAmount() == kHRegSizeInBytesLog2);4615break;4616case kSRegSize:4617VIXL_ASSERT(addr.GetShiftAmount() == kSRegSizeInBytesLog2);4618break;4619case kDRegSize:4620VIXL_ASSERT(addr.GetShiftAmount() == kDRegSizeInBytesLog2);4621break;4622default:4623VIXL_UNIMPLEMENTED();4624break;4625}46264627Instr sx = 0;4628Instr op = 0xffffffff;4629if ((mod == NO_SVE_OFFSET_MODIFIER) || (mod == SVE_LSL)) {4630VIXL_ASSERT(zm.IsLaneSizeD());46314632switch (prefetch_size) {4633case kBRegSize:4634VIXL_ASSERT(mod == NO_SVE_OFFSET_MODIFIER);4635op = PRFB_i_p_bz_d_64_scaled;4636break;4637case kHRegSize:4638VIXL_ASSERT(mod == SVE_LSL);4639op = PRFH_i_p_bz_d_64_scaled;4640break;4641case kSRegSize:4642VIXL_ASSERT(mod == SVE_LSL);4643op = PRFW_i_p_bz_d_64_scaled;4644break;4645case kDRegSize:4646VIXL_ASSERT(mod == SVE_LSL);4647op = PRFD_i_p_bz_d_64_scaled;4648break;4649default:4650VIXL_UNIMPLEMENTED();4651break;4652}4653} else {4654VIXL_ASSERT((mod == SVE_SXTW) || (mod == SVE_UXTW));4655VIXL_ASSERT(zm.IsLaneSizeS() || zm.IsLaneSizeD());46564657switch (prefetch_size) {4658case kBRegSize:4659op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFB_i_p_bz_s_x32_scaled)4660: static_cast<Instr>(PRFB_i_p_bz_d_x32_scaled);4661break;4662case kHRegSize:4663op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFH_i_p_bz_s_x32_scaled)4664: static_cast<Instr>(PRFH_i_p_bz_d_x32_scaled);4665break;4666case kSRegSize:4667op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFW_i_p_bz_s_x32_scaled)4668: static_cast<Instr>(PRFW_i_p_bz_d_x32_scaled);4669break;4670case kDRegSize:4671op = zm.IsLaneSizeS() ? static_cast<Instr>(PRFD_i_p_bz_s_x32_scaled)4672: static_cast<Instr>(PRFD_i_p_bz_d_x32_scaled);4673break;4674default:4675VIXL_UNIMPLEMENTED();4676break;4677}46784679if (mod == SVE_SXTW) {4680sx = 1 << 22;4681}4682}46834684Emit(op | SVEImmPrefetchOperation(prfop) | PgLow8(pg) | sx |4685RnSP(addr.GetScalarBase()) | Rm(zm));4686}46874688void Assembler::SVEPrefetchHelper(PrefetchOperation prfop,4689const PRegister& pg,4690const SVEMemOperand& addr,4691int prefetch_size) {4692if (addr.IsVectorPlusImmediate()) {4693// For example:4694// [z0.s, #0]4695SVEGatherPrefetchVectorPlusImmediateHelper(prfop, pg, addr, prefetch_size);46964697} else if (addr.IsScalarPlusImmediate()) {4698// For example:4699// [x0, #42, mul vl]4700SVEGatherPrefetchScalarPlusImmediateHelper(prfop, pg, addr, prefetch_size);47014702} else if (addr.IsScalarPlusVector()) {4703// For example:4704// [x0, z0.s, sxtw]4705SVEContiguousPrefetchScalarPlusVectorHelper(prfop, pg, addr, prefetch_size);47064707} else if (addr.IsScalarPlusScalar()) {4708// For example:4709// [x0, x1]4710SVEContiguousPrefetchScalarPlusScalarHelper(prfop, pg, addr, prefetch_size);47114712} else {4713VIXL_UNIMPLEMENTED();4714}4715}47164717void Assembler::prfb(PrefetchOperation prfop,4718const PRegister& pg,4719const SVEMemOperand& addr) {4720VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4721SVEPrefetchHelper(prfop, pg, addr, kBRegSize);4722}47234724void Assembler::prfd(PrefetchOperation prfop,4725const PRegister& pg,4726const SVEMemOperand& addr) {4727VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4728SVEPrefetchHelper(prfop, pg, addr, kDRegSize);4729}47304731void Assembler::prfh(PrefetchOperation prfop,4732const PRegister& pg,4733const SVEMemOperand& addr) {4734VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4735SVEPrefetchHelper(prfop, pg, addr, kHRegSize);4736}47374738void Assembler::prfw(PrefetchOperation prfop,4739const PRegister& pg,4740const SVEMemOperand& addr) {4741VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4742SVEPrefetchHelper(prfop, pg, addr, kSRegSize);4743}47444745void Assembler::SVELd1St1ScaImmHelper(const ZRegister& zt,4746const PRegister& pg,4747const SVEMemOperand& addr,4748Instr regoffset_op,4749Instr immoffset_op,4750int imm_divisor) {4751VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4752VIXL_ASSERT(addr.IsScalarPlusScalar() || addr.IsScalarPlusImmediate());47534754Instr op;4755if (addr.IsScalarPlusScalar()) {4756op = regoffset_op | Rm(addr.GetScalarOffset());4757} else {4758int64_t imm = addr.GetImmediateOffset();4759VIXL_ASSERT(((imm % imm_divisor) == 0) && IsInt4(imm / imm_divisor));4760op = immoffset_op | ImmField<19, 16>(imm / imm_divisor);4761}4762Emit(op | Rt(zt) | PgLow8(pg) | RnSP(addr.GetScalarBase()));4763}47644765void Assembler::SVELd1VecScaHelper(const ZRegister& zt,4766const PRegister& pg,4767const SVEMemOperand& addr,4768uint32_t msize_bytes_log2,4769bool is_signed) {4770VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));4771VIXL_ASSERT(addr.IsVectorPlusScalar());4772ZRegister zn = addr.GetVectorBase();4773VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());4774VIXL_ASSERT(AreSameLaneSize(zn, zt));47754776uint32_t esize = zn.GetLaneSizeInBytesLog2();4777uint32_t b14_13 = 0;4778if (!is_signed) b14_13 = zn.IsLaneSizeS() ? 0x1 : 0x2;47794780Instr op = 0x04008000; // LDNT1 with vector plus scalar addressing mode.4781op |= (esize << 30) | (msize_bytes_log2 << 23) | (b14_13 << 13);4782Emit(op | Rt(zt) | PgLow8(pg) |4783SVEMemOperandHelper(msize_bytes_log2, 1, addr, true));4784}47854786void Assembler::SVESt1VecScaHelper(const ZRegister& zt,4787const PRegister& pg,4788const SVEMemOperand& addr,4789uint32_t msize_bytes_log2) {4790VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));4791VIXL_ASSERT(addr.IsVectorPlusScalar());4792ZRegister zn = addr.GetVectorBase();4793VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());4794VIXL_ASSERT(AreSameLaneSize(zn, zt));47954796uint32_t bit22 = zn.IsLaneSizeS() ? (1 << 22) : 0;4797Instr op = 0xe4002000; // STNT1 with vector plus scalar addressing mode.4798op |= bit22 | (msize_bytes_log2 << 23);4799Emit(op | Rt(zt) | PgLow8(pg) |4800SVEMemOperandHelper(msize_bytes_log2, 1, addr, true));4801}48024803#define VIXL_SVE_LD1R_LIST(V) \4804V(qb, 0, B, LD1RQB_z_p_br_contiguous, LD1RQB_z_p_bi_u8, 16) \4805V(qh, 1, H, LD1RQH_z_p_br_contiguous, LD1RQH_z_p_bi_u16, 16) \4806V(qw, 2, S, LD1RQW_z_p_br_contiguous, LD1RQW_z_p_bi_u32, 16) \4807V(qd, 3, D, LD1RQD_z_p_br_contiguous, LD1RQD_z_p_bi_u64, 16) \4808V(ob, 0, B, 0xa4200000, 0xa4202000, 32) \4809V(oh, 1, H, 0xa4a00000, 0xa4a02000, 32) \4810V(ow, 2, S, 0xa5200000, 0xa5202000, 32) \4811V(od, 3, D, 0xa5a00000, 0xa5a02000, 32)48124813#define VIXL_DEFINE_ASM_FUNC(FN, SH, SZ, SCA, IMM, BYTES) \4814void Assembler::ld1r##FN(const ZRegister& zt, \4815const PRegisterZ& pg, \4816const SVEMemOperand& addr) { \4817VIXL_ASSERT((BYTES == 16) || \4818((BYTES == 32) && (CPUHas(CPUFeatures::kSVEF64MM)))); \4819VIXL_ASSERT(addr.IsScalarPlusImmediate() || addr.IsEquivalentToLSL(SH)); \4820VIXL_ASSERT(zt.IsLaneSize##SZ()); \4821SVELd1St1ScaImmHelper(zt, pg, addr, SCA, IMM, BYTES); \4822}4823VIXL_SVE_LD1R_LIST(VIXL_DEFINE_ASM_FUNC)4824#undef VIXL_DEFINE_ASM_FUNC4825#undef VIXL_SVE_LD1R_LIST48264827#define VIXL_DEFINE_LDFF1(MSZ, LANE_SIZE) \4828void Assembler::ldff1##MSZ(const ZRegister& zt, \4829const PRegisterZ& pg, \4830const SVEMemOperand& addr) { \4831VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \4832SVELdff1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, false); \4833}4834VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_LDFF1)48354836#define VIXL_DEFINE_LDFF1S(MSZ, LANE_SIZE) \4837void Assembler::ldff1s##MSZ(const ZRegister& zt, \4838const PRegisterZ& pg, \4839const SVEMemOperand& addr) { \4840VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \4841SVELdff1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr, true); \4842}4843VIXL_SVE_LOAD_STORE_SIGNED_VARIANT_LIST(VIXL_DEFINE_LDFF1S)48444845void Assembler::ldnf1b(const ZRegister& zt,4846const PRegisterZ& pg,4847const SVEMemOperand& addr) {4848VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4849VIXL_ASSERT(addr.IsPlainRegister() ||4850(addr.IsScalarPlusImmediate() &&4851(addr.GetOffsetModifier() == SVE_MUL_VL)));48524853SVELdSt1Helper(0,4854zt,4855pg,4856addr,4857/* is_signed = */ false,4858SVEContiguousNonFaultLoad_ScalarPlusImmFixed);4859}48604861void Assembler::ldnf1d(const ZRegister& zt,4862const PRegisterZ& pg,4863const SVEMemOperand& addr) {4864VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4865VIXL_ASSERT(addr.IsPlainRegister() ||4866(addr.IsScalarPlusImmediate() &&4867(addr.GetOffsetModifier() == SVE_MUL_VL)));48684869SVELdSt1Helper(3,4870zt,4871pg,4872addr,4873/* is_signed = */ false,4874SVEContiguousNonFaultLoad_ScalarPlusImmFixed);4875}48764877void Assembler::ldnf1h(const ZRegister& zt,4878const PRegisterZ& pg,4879const SVEMemOperand& addr) {4880VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4881VIXL_ASSERT(addr.IsPlainRegister() ||4882(addr.IsScalarPlusImmediate() &&4883(addr.GetOffsetModifier() == SVE_MUL_VL)));48844885SVELdSt1Helper(1,4886zt,4887pg,4888addr,4889/* is_signed = */ false,4890SVEContiguousNonFaultLoad_ScalarPlusImmFixed);4891}48924893void Assembler::ldnf1sb(const ZRegister& zt,4894const PRegisterZ& pg,4895const SVEMemOperand& addr) {4896VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4897VIXL_ASSERT(addr.IsPlainRegister() ||4898(addr.IsScalarPlusImmediate() &&4899(addr.GetOffsetModifier() == SVE_MUL_VL)));49004901SVELdSt1Helper(0,4902zt,4903pg,4904addr,4905/* is_signed = */ true,4906SVEContiguousNonFaultLoad_ScalarPlusImmFixed);4907}49084909void Assembler::ldnf1sh(const ZRegister& zt,4910const PRegisterZ& pg,4911const SVEMemOperand& addr) {4912VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4913VIXL_ASSERT(addr.IsPlainRegister() ||4914(addr.IsScalarPlusImmediate() &&4915(addr.GetOffsetModifier() == SVE_MUL_VL)));49164917SVELdSt1Helper(1,4918zt,4919pg,4920addr,4921/* is_signed = */ true,4922SVEContiguousNonFaultLoad_ScalarPlusImmFixed);4923}49244925void Assembler::ldnf1sw(const ZRegister& zt,4926const PRegisterZ& pg,4927const SVEMemOperand& addr) {4928VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4929VIXL_ASSERT(addr.IsPlainRegister() ||4930(addr.IsScalarPlusImmediate() &&4931(addr.GetOffsetModifier() == SVE_MUL_VL)));49324933SVELdSt1Helper(2,4934zt,4935pg,4936addr,4937/* is_signed = */ true,4938SVEContiguousNonFaultLoad_ScalarPlusImmFixed);4939}49404941void Assembler::ldnf1w(const ZRegister& zt,4942const PRegisterZ& pg,4943const SVEMemOperand& addr) {4944VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));4945VIXL_ASSERT(addr.IsPlainRegister() ||4946(addr.IsScalarPlusImmediate() &&4947(addr.GetOffsetModifier() == SVE_MUL_VL)));49484949SVELdSt1Helper(2,4950zt,4951pg,4952addr,4953/* is_signed = */ false,4954SVEContiguousNonFaultLoad_ScalarPlusImmFixed);4955}49564957void Assembler::ldnt1b(const ZRegister& zt,4958const PRegisterZ& pg,4959const SVEMemOperand& addr) {4960VIXL_ASSERT(addr.IsPlainScalar() ||4961(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||4962(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(0)) ||4963(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));4964if (addr.IsVectorPlusScalar()) {4965SVELd1VecScaHelper(zt, pg, addr, 0, /* is_signed = */ false);4966} else {4967SVELd1St1ScaImmHelper(zt,4968pg,4969addr,4970LDNT1B_z_p_br_contiguous,4971LDNT1B_z_p_bi_contiguous);4972}4973}49744975void Assembler::ldnt1d(const ZRegister& zt,4976const PRegisterZ& pg,4977const SVEMemOperand& addr) {4978VIXL_ASSERT(addr.IsPlainScalar() ||4979(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||4980(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(3)) ||4981(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));4982if (addr.IsVectorPlusScalar()) {4983SVELd1VecScaHelper(zt, pg, addr, 3, /* is_signed = */ false);4984} else {4985SVELd1St1ScaImmHelper(zt,4986pg,4987addr,4988LDNT1D_z_p_br_contiguous,4989LDNT1D_z_p_bi_contiguous);4990}4991}49924993void Assembler::ldnt1h(const ZRegister& zt,4994const PRegisterZ& pg,4995const SVEMemOperand& addr) {4996VIXL_ASSERT(addr.IsPlainScalar() ||4997(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||4998(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(1)) ||4999(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));5000if (addr.IsVectorPlusScalar()) {5001SVELd1VecScaHelper(zt, pg, addr, 1, /* is_signed = */ false);5002} else {5003SVELd1St1ScaImmHelper(zt,5004pg,5005addr,5006LDNT1H_z_p_br_contiguous,5007LDNT1H_z_p_bi_contiguous);5008}5009}50105011void Assembler::ldnt1w(const ZRegister& zt,5012const PRegisterZ& pg,5013const SVEMemOperand& addr) {5014VIXL_ASSERT(addr.IsPlainScalar() ||5015(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||5016(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(2)) ||5017(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));5018if (addr.IsVectorPlusScalar()) {5019SVELd1VecScaHelper(zt, pg, addr, 2, /* is_signed = */ false);5020} else {5021SVELd1St1ScaImmHelper(zt,5022pg,5023addr,5024LDNT1W_z_p_br_contiguous,5025LDNT1W_z_p_bi_contiguous);5026}5027}50285029void Assembler::ldnt1sb(const ZRegister& zt,5030const PRegisterZ& pg,5031const SVEMemOperand& addr) {5032VIXL_ASSERT(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2));5033SVELd1VecScaHelper(zt, pg, addr, 0, /* is_signed = */ true);5034}50355036void Assembler::ldnt1sh(const ZRegister& zt,5037const PRegisterZ& pg,5038const SVEMemOperand& addr) {5039VIXL_ASSERT(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2));5040SVELd1VecScaHelper(zt, pg, addr, 1, /* is_signed = */ true);5041}50425043void Assembler::ldnt1sw(const ZRegister& zt,5044const PRegisterZ& pg,5045const SVEMemOperand& addr) {5046VIXL_ASSERT(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2));5047SVELd1VecScaHelper(zt, pg, addr, 2, /* is_signed = */ true);5048}50495050Instr Assembler::SVEMemOperandHelper(unsigned msize_in_bytes_log2,5051int num_regs,5052const SVEMemOperand& addr,5053bool is_load) {5054VIXL_ASSERT((num_regs >= 1) && (num_regs <= 4));50555056Instr op = 0xfffffff;5057if (addr.IsScalarPlusImmediate()) {5058VIXL_ASSERT((addr.GetImmediateOffset() == 0) || addr.IsMulVl());5059int64_t imm = addr.GetImmediateOffset();5060VIXL_ASSERT((imm % num_regs) == 0);5061op = RnSP(addr.GetScalarBase()) | ImmField<19, 16>(imm / num_regs);50625063} else if (addr.IsScalarPlusScalar()) {5064VIXL_ASSERT(addr.GetScalarOffset().IsZero() ||5065addr.IsEquivalentToLSL(msize_in_bytes_log2));5066op = RnSP(addr.GetScalarBase()) | Rm(addr.GetScalarOffset());50675068} else if (addr.IsVectorPlusImmediate()) {5069ZRegister zn = addr.GetVectorBase();5070uint64_t imm = addr.GetImmediateOffset();5071VIXL_ASSERT(num_regs == 1);5072VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());5073VIXL_ASSERT(IsMultiple(imm, (1 << msize_in_bytes_log2)));5074op = Rn(zn) | ImmUnsignedField<20, 16>(imm >> msize_in_bytes_log2);5075} else if (addr.IsVectorPlusScalar()) {5076VIXL_ASSERT(addr.GetOffsetModifier() == NO_SVE_OFFSET_MODIFIER);5077VIXL_ASSERT(addr.GetShiftAmount() == 0);5078ZRegister zn = addr.GetVectorBase();5079VIXL_ASSERT(zn.IsLaneSizeS() || zn.IsLaneSizeD());5080Register xm = addr.GetScalarOffset();5081op = Rn(zn) | Rm(xm);5082} else if (addr.IsScalarPlusVector()) {5083// We have to support several different addressing modes. Some instructions5084// support a subset of these, but the SVEMemOperand encoding is consistent.5085Register xn = addr.GetScalarBase();5086ZRegister zm = addr.GetVectorOffset();5087SVEOffsetModifier mod = addr.GetOffsetModifier();5088Instr modifier_bit = 1 << (is_load ? 22 : 14);5089Instr xs = (mod == SVE_SXTW) ? modifier_bit : 0;5090VIXL_ASSERT(num_regs == 1);50915092if (mod == SVE_LSL) {5093// 64-bit scaled offset: [<Xn|SP>, <Zm>.D, LSL #<shift>]5094VIXL_ASSERT(zm.IsLaneSizeD());5095VIXL_ASSERT(addr.GetShiftAmount() == msize_in_bytes_log2);5096} else if (mod == NO_SVE_OFFSET_MODIFIER) {5097// 64-bit unscaled offset: [<Xn|SP>, <Zm>.D]5098VIXL_ASSERT(zm.IsLaneSizeD());5099VIXL_ASSERT(addr.GetShiftAmount() == 0);5100} else {5101// 32-bit scaled offset: [<Xn|SP>, <Zm>.S, <mod> #<shift>]5102// 32-bit unscaled offset: [<Xn|SP>, <Zm>.S, <mod>]5103// 32-bit unpacked scaled offset: [<Xn|SP>, <Zm>.D, <mod> #<shift>]5104// 32-bit unpacked unscaled offset: [<Xn|SP>, <Zm>.D, <mod>]5105VIXL_ASSERT(zm.IsLaneSizeS() || zm.IsLaneSizeD());5106VIXL_ASSERT((mod == SVE_SXTW) || (mod == SVE_UXTW));5107VIXL_ASSERT((addr.GetShiftAmount() == 0) ||5108(addr.GetShiftAmount() == msize_in_bytes_log2));5109}51105111// The form itself is encoded in the instruction opcode.5112op = RnSP(xn) | Rm(zm) | xs;5113} else {5114VIXL_UNIMPLEMENTED();5115}51165117return op;5118}51195120// SVEMemStore.51215122void Assembler::SVESt1Helper(unsigned msize_in_bytes_log2,5123const ZRegister& zt,5124const PRegister& pg,5125const SVEMemOperand& addr) {5126if (addr.IsScalarPlusScalar()) {5127// Rm must not be xzr.5128VIXL_ASSERT(!addr.GetScalarOffset().IsZero());5129}51305131if (addr.IsScatterGather()) {5132bool is_load = false;5133bool is_signed = false;5134bool is_ff = false;5135SVEScatterGatherHelper(msize_in_bytes_log2,5136zt,5137pg,5138addr,5139is_load,5140is_signed,5141is_ff);5142return;5143}51445145Instr op;5146if (addr.IsScalarPlusImmediate()) {5147op = SVEContiguousStore_ScalarPlusImmFixed;5148} else if (addr.IsScalarPlusScalar()) {5149op = SVEContiguousStore_ScalarPlusScalarFixed;5150} else {5151VIXL_UNIMPLEMENTED();5152op = 0xffffffff;5153}5154SVELdSt1Helper(msize_in_bytes_log2, zt, pg, addr, false, op);5155}51565157void Assembler::SVESt234Helper(int num_regs,5158const ZRegister& zt1,5159const PRegister& pg,5160const SVEMemOperand& addr) {5161if (addr.IsScalarPlusScalar()) {5162// Rm must not be xzr.5163VIXL_ASSERT(!addr.GetScalarOffset().IsZero());5164}51655166Instr op;5167if (addr.IsScalarPlusImmediate()) {5168op = SVEStoreMultipleStructures_ScalarPlusImmFixed;5169} else if (addr.IsScalarPlusScalar()) {5170op = SVEStoreMultipleStructures_ScalarPlusScalarFixed;5171} else {5172// These instructions don't support any other addressing modes.5173VIXL_ABORT();5174}5175SVELdSt234Helper(num_regs, zt1, pg, addr, op);5176}51775178#define VIXL_DEFINE_ST1(MSZ, LANE_SIZE) \5179void Assembler::st1##MSZ(const ZRegister& zt, \5180const PRegister& pg, \5181const SVEMemOperand& addr) { \5182VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \5183SVESt1Helper(k##LANE_SIZE##RegSizeInBytesLog2, zt, pg, addr); \5184}5185#define VIXL_DEFINE_ST2(MSZ, LANE_SIZE) \5186void Assembler::st2##MSZ(const ZRegister& zt1, \5187const ZRegister& zt2, \5188const PRegister& pg, \5189const SVEMemOperand& addr) { \5190USE(zt2); \5191VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \5192VIXL_ASSERT(AreConsecutive(zt1, zt2)); \5193VIXL_ASSERT(AreSameFormat(zt1, zt2)); \5194VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \5195SVESt234Helper(2, zt1, pg, addr); \5196}5197#define VIXL_DEFINE_ST3(MSZ, LANE_SIZE) \5198void Assembler::st3##MSZ(const ZRegister& zt1, \5199const ZRegister& zt2, \5200const ZRegister& zt3, \5201const PRegister& pg, \5202const SVEMemOperand& addr) { \5203USE(zt2, zt3); \5204VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \5205VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3)); \5206VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3)); \5207VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \5208SVESt234Helper(3, zt1, pg, addr); \5209}5210#define VIXL_DEFINE_ST4(MSZ, LANE_SIZE) \5211void Assembler::st4##MSZ(const ZRegister& zt1, \5212const ZRegister& zt2, \5213const ZRegister& zt3, \5214const ZRegister& zt4, \5215const PRegister& pg, \5216const SVEMemOperand& addr) { \5217USE(zt2, zt3, zt4); \5218VIXL_ASSERT(CPUHas(CPUFeatures::kSVE)); \5219VIXL_ASSERT(AreConsecutive(zt1, zt2, zt3, zt4)); \5220VIXL_ASSERT(AreSameFormat(zt1, zt2, zt3, zt4)); \5221VIXL_ASSERT(zt1.IsLaneSize##LANE_SIZE()); \5222SVESt234Helper(4, zt1, pg, addr); \5223}52245225VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST1)5226VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST2)5227VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST3)5228VIXL_SVE_LOAD_STORE_VARIANT_LIST(VIXL_DEFINE_ST4)52295230void Assembler::stnt1b(const ZRegister& zt,5231const PRegister& pg,5232const SVEMemOperand& addr) {5233VIXL_ASSERT(addr.IsPlainScalar() ||5234(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||5235(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(0)) ||5236(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));5237if (addr.IsVectorPlusScalar()) {5238SVESt1VecScaHelper(zt, pg, addr, 0);5239} else {5240SVELd1St1ScaImmHelper(zt,5241pg,5242addr,5243STNT1B_z_p_br_contiguous,5244STNT1B_z_p_bi_contiguous);5245}5246}52475248void Assembler::stnt1d(const ZRegister& zt,5249const PRegister& pg,5250const SVEMemOperand& addr) {5251VIXL_ASSERT(addr.IsPlainScalar() ||5252(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||5253(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(3)) ||5254(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));5255if (addr.IsVectorPlusScalar()) {5256SVESt1VecScaHelper(zt, pg, addr, 3);5257} else {5258SVELd1St1ScaImmHelper(zt,5259pg,5260addr,5261STNT1D_z_p_br_contiguous,5262STNT1D_z_p_bi_contiguous);5263}5264}52655266void Assembler::stnt1h(const ZRegister& zt,5267const PRegister& pg,5268const SVEMemOperand& addr) {5269VIXL_ASSERT(addr.IsPlainScalar() ||5270(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||5271(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(1)) ||5272(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));5273if (addr.IsVectorPlusScalar()) {5274SVESt1VecScaHelper(zt, pg, addr, 1);5275} else {5276SVELd1St1ScaImmHelper(zt,5277pg,5278addr,5279STNT1H_z_p_br_contiguous,5280STNT1H_z_p_bi_contiguous);5281}5282}52835284void Assembler::stnt1w(const ZRegister& zt,5285const PRegister& pg,5286const SVEMemOperand& addr) {5287VIXL_ASSERT(addr.IsPlainScalar() ||5288(addr.IsScalarPlusImmediate() && addr.IsMulVl()) ||5289(addr.IsScalarPlusScalar() && addr.IsEquivalentToLSL(2)) ||5290(addr.IsVectorPlusScalar() && CPUHas(CPUFeatures::kSVE2)));5291if (addr.IsVectorPlusScalar()) {5292SVESt1VecScaHelper(zt, pg, addr, 2);5293} else {5294SVELd1St1ScaImmHelper(zt,5295pg,5296addr,5297STNT1W_z_p_br_contiguous,5298STNT1W_z_p_bi_contiguous);5299}5300}53015302void Assembler::str(const CPURegister& rt, const SVEMemOperand& addr) {5303// STR <Pt/Zt>, [<Xn|SP>{, #<imm>, MUL VL}]53045305VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5306VIXL_ASSERT(rt.IsPRegister() || rt.IsZRegister());5307VIXL_ASSERT(addr.IsPlainScalar() ||5308(addr.IsScalarPlusImmediate() &&5309(addr.GetOffsetModifier() == SVE_MUL_VL)));5310int64_t imm9 = addr.GetImmediateOffset();5311VIXL_ASSERT(IsInt9(imm9));5312Instr imm9l = ExtractUnsignedBitfield32(2, 0, imm9) << 10;5313Instr imm9h = ExtractUnsignedBitfield32(8, 3, imm9) << 16;53145315Instr op = STR_z_bi;5316if (rt.IsPRegister()) {5317op = STR_p_bi;5318}5319Emit(op | Rt(rt) | RnSP(addr.GetScalarBase()) | imm9h | imm9l);5320}53215322// SVEMulIndex.53235324void Assembler::sdot(const ZRegister& zda,5325const ZRegister& zn,5326const ZRegister& zm,5327int index) {5328VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5329VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));5330VIXL_ASSERT(AreSameLaneSize(zn, zm));53315332Instr op = 0xffffffff;5333switch (zda.GetLaneSizeInBits()) {5334case kSRegSize:5335VIXL_ASSERT(IsUint2(index));5336op = SDOT_z_zzzi_s | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn);5337break;5338case kDRegSize:5339VIXL_ASSERT(IsUint1(index));5340op = SDOT_z_zzzi_d | Rx<19, 16>(zm) | (index << 20) | Rd(zda) | Rn(zn);5341break;5342default:5343VIXL_UNIMPLEMENTED();5344break;5345}53465347Emit(op);5348}53495350void Assembler::udot(const ZRegister& zda,5351const ZRegister& zn,5352const ZRegister& zm,5353int index) {5354VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5355VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));5356VIXL_ASSERT(AreSameLaneSize(zn, zm));53575358Instr op = 0xffffffff;5359switch (zda.GetLaneSizeInBits()) {5360case kSRegSize:5361VIXL_ASSERT(IsUint2(index));5362op = UDOT_z_zzzi_s | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn);5363break;5364case kDRegSize:5365VIXL_ASSERT(IsUint1(index));5366op = UDOT_z_zzzi_d | Rx<19, 16>(zm) | (index << 20) | Rd(zda) | Rn(zn);5367break;5368default:5369VIXL_UNIMPLEMENTED();5370break;5371}53725373Emit(op);5374}53755376// SVEPartitionBreak.53775378void Assembler::brka(const PRegisterWithLaneSize& pd,5379const PRegister& pg,5380const PRegisterWithLaneSize& pn) {5381VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5382VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());5383VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());53845385Instr m = pg.IsMerging() ? 0x00000010 : 0x00000000;5386Emit(BRKA_p_p_p | Pd(pd) | Pg<13, 10>(pg) | m | Pn(pn));5387}53885389void Assembler::brkas(const PRegisterWithLaneSize& pd,5390const PRegisterZ& pg,5391const PRegisterWithLaneSize& pn) {5392VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5393VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());53945395Emit(BRKAS_p_p_p_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));5396}53975398void Assembler::brkb(const PRegisterWithLaneSize& pd,5399const PRegister& pg,5400const PRegisterWithLaneSize& pn) {5401VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5402VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());5403VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());54045405Instr m = pg.IsMerging() ? 0x00000010 : 0x00000000;5406Emit(BRKB_p_p_p | Pd(pd) | Pg<13, 10>(pg) | m | Pn(pn));5407}54085409void Assembler::brkbs(const PRegisterWithLaneSize& pd,5410const PRegisterZ& pg,5411const PRegisterWithLaneSize& pn) {5412VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5413VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());54145415Emit(BRKBS_p_p_p_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));5416}54175418void Assembler::brkn(const PRegisterWithLaneSize& pd,5419const PRegisterZ& pg,5420const PRegisterWithLaneSize& pn,5421const PRegisterWithLaneSize& pm) {5422USE(pm);5423VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5424VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());5425VIXL_ASSERT(pd.Is(pm));54265427Emit(BRKN_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));5428}54295430void Assembler::brkns(const PRegisterWithLaneSize& pd,5431const PRegisterZ& pg,5432const PRegisterWithLaneSize& pn,5433const PRegisterWithLaneSize& pm) {5434USE(pm);5435VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5436VIXL_ASSERT(pd.IsLaneSizeB() && pn.IsLaneSizeB());5437VIXL_ASSERT(pd.Is(pm));54385439Emit(BRKNS_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn));5440}54415442// SVEPermutePredicate.54435444void Assembler::punpkhi(const PRegisterWithLaneSize& pd,5445const PRegisterWithLaneSize& pn) {5446// PUNPKHI <Pd>.H, <Pn>.B5447// 0000 0101 0011 0001 0100 000. ...0 ....5448// H<16> = 1 | Pn<8:5> | Pd<3:0>54495450VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5451VIXL_ASSERT(pd.IsLaneSizeH());5452VIXL_ASSERT(pn.IsLaneSizeB());54535454Emit(PUNPKHI_p_p | Pd(pd) | Pn(pn));5455}54565457void Assembler::punpklo(const PRegisterWithLaneSize& pd,5458const PRegisterWithLaneSize& pn) {5459// PUNPKLO <Pd>.H, <Pn>.B5460// 0000 0101 0011 0000 0100 000. ...0 ....5461// H<16> = 0 | Pn<8:5> | Pd<3:0>54625463VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5464VIXL_ASSERT(pd.IsLaneSizeH());5465VIXL_ASSERT(pn.IsLaneSizeB());54665467Emit(PUNPKLO_p_p | Pd(pd) | Pn(pn));5468}54695470void Assembler::rev(const PRegisterWithLaneSize& pd,5471const PRegisterWithLaneSize& pn) {5472// REV <Pd>.<T>, <Pn>.<T>5473// 0000 0101 ..11 0100 0100 000. ...0 ....5474// size<23:22> | Pn<8:5> | Pd<3:0>54755476VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5477VIXL_ASSERT(AreSameLaneSize(pd, pn));54785479Emit(REV_p_p | SVESize(pd) | Pd(pd) | Rx<8, 5>(pn));5480}54815482void Assembler::trn1(const PRegisterWithLaneSize& pd,5483const PRegisterWithLaneSize& pn,5484const PRegisterWithLaneSize& pm) {5485// TRN1 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>5486// 0000 0101 ..10 .... 0101 000. ...0 ....5487// size<23:22> | Pm<19:16> | opc<12:11> = 10 | H<10> = 0 | Pn<8:5> | Pd<3:0>54885489VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5490VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));54915492Emit(TRN1_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));5493}54945495void Assembler::trn2(const PRegisterWithLaneSize& pd,5496const PRegisterWithLaneSize& pn,5497const PRegisterWithLaneSize& pm) {5498// TRN2 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>5499// 0000 0101 ..10 .... 0101 010. ...0 ....5500// size<23:22> | Pm<19:16> | opc<12:11> = 10 | H<10> = 1 | Pn<8:5> | Pd<3:0>55015502VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5503VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));55045505Emit(TRN2_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));5506}55075508void Assembler::uzp1(const PRegisterWithLaneSize& pd,5509const PRegisterWithLaneSize& pn,5510const PRegisterWithLaneSize& pm) {5511// UZP1 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>5512// 0000 0101 ..10 .... 0100 100. ...0 ....5513// size<23:22> | Pm<19:16> | opc<12:11> = 01 | H<10> = 0 | Pn<8:5> | Pd<3:0>55145515VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5516VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));55175518Emit(UZP1_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));5519}55205521void Assembler::uzp2(const PRegisterWithLaneSize& pd,5522const PRegisterWithLaneSize& pn,5523const PRegisterWithLaneSize& pm) {5524// UZP2 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>5525// 0000 0101 ..10 .... 0100 110. ...0 ....5526// size<23:22> | Pm<19:16> | opc<12:11> = 01 | H<10> = 1 | Pn<8:5> | Pd<3:0>55275528VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5529VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));55305531Emit(UZP2_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));5532}55335534void Assembler::zip1(const PRegisterWithLaneSize& pd,5535const PRegisterWithLaneSize& pn,5536const PRegisterWithLaneSize& pm) {5537// ZIP1 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>5538// 0000 0101 ..10 .... 0100 000. ...0 ....5539// size<23:22> | Pm<19:16> | opc<12:11> = 00 | H<10> = 0 | Pn<8:5> | Pd<3:0>55405541VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5542VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));55435544Emit(ZIP1_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));5545}55465547void Assembler::zip2(const PRegisterWithLaneSize& pd,5548const PRegisterWithLaneSize& pn,5549const PRegisterWithLaneSize& pm) {5550// ZIP2 <Pd>.<T>, <Pn>.<T>, <Pm>.<T>5551// 0000 0101 ..10 .... 0100 010. ...0 ....5552// size<23:22> | Pm<19:16> | opc<12:11> = 00 | H<10> = 1 | Pn<8:5> | Pd<3:0>55535554VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5555VIXL_ASSERT(AreSameLaneSize(pd, pn, pm));55565557Emit(ZIP2_p_pp | SVESize(pd) | Pd(pd) | Pn(pn) | Pm(pm));5558}55595560// SVEPermuteVectorExtract.55615562void Assembler::ext(const ZRegister& zd,5563const ZRegister& zn,5564const ZRegister& zm,5565unsigned offset) {5566// EXT <Zdn>.B, <Zdn>.B, <Zm>.B, #<imm>5567// 0000 0101 001. .... 000. .... .... ....5568// imm8h<20:16> | imm8l<12:10> | Zm<9:5> | Zdn<4:0>55695570// EXT <Zd>.B, { <Zn1>.B, <Zn2>.B }, #<imm>5571// 0000 0101 011. .... 000. .... .... ....5572// imm8h<20:16> | imm8l<12:10> | Zn<9:5> | Zd<4:0>55735574VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5575VIXL_ASSERT(IsUint8(offset));55765577int imm8h = ExtractUnsignedBitfield32(7, 3, offset);5578int imm8l = ExtractUnsignedBitfield32(2, 0, offset);55795580Instr op;5581if (zd.Is(zn)) {5582// Destructive form.5583op = EXT_z_zi_des | Rn(zm);5584} else {5585// Constructive form (requires SVE2).5586VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2) && AreConsecutive(zn, zm));5587op = 0x05600000 | Rn(zn);5588}55895590Emit(op | Rd(zd) | ImmUnsignedField<20, 16>(imm8h) |5591ImmUnsignedField<12, 10>(imm8l));5592}55935594// SVEPermuteVectorInterleaving.55955596void Assembler::trn1(const ZRegister& zd,5597const ZRegister& zn,5598const ZRegister& zm) {5599// TRN1 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>5600// 0000 0101 ..1. .... 0111 00.. .... ....5601// size<23:22> | Zm<20:16> | opc<12:10> = 100 | Zn<9:5> | Zd<4:0>56025603VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5604VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));56055606Emit(TRN1_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));5607}56085609void Assembler::trn2(const ZRegister& zd,5610const ZRegister& zn,5611const ZRegister& zm) {5612// TRN2 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>5613// 0000 0101 ..1. .... 0111 01.. .... ....5614// size<23:22> | Zm<20:16> | opc<12:10> = 101 | Zn<9:5> | Zd<4:0>56155616VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5617VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));56185619Emit(TRN2_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));5620}56215622void Assembler::uzp1(const ZRegister& zd,5623const ZRegister& zn,5624const ZRegister& zm) {5625// UZP1 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>5626// 0000 0101 ..1. .... 0110 10.. .... ....5627// size<23:22> | Zm<20:16> | opc<12:10> = 010 | Zn<9:5> | Zd<4:0>56285629VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5630VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));56315632Emit(UZP1_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));5633}56345635void Assembler::uzp2(const ZRegister& zd,5636const ZRegister& zn,5637const ZRegister& zm) {5638// UZP2 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>5639// 0000 0101 ..1. .... 0110 11.. .... ....5640// size<23:22> | Zm<20:16> | opc<12:10> = 011 | Zn<9:5> | Zd<4:0>56415642VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5643VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));56445645Emit(UZP2_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));5646}56475648void Assembler::zip1(const ZRegister& zd,5649const ZRegister& zn,5650const ZRegister& zm) {5651// ZIP1 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>5652// 0000 0101 ..1. .... 0110 00.. .... ....5653// size<23:22> | Zm<20:16> | opc<12:10> = 000 | Zn<9:5> | Zd<4:0>56545655VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5656VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));56575658Emit(ZIP1_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));5659}56605661void Assembler::zip2(const ZRegister& zd,5662const ZRegister& zn,5663const ZRegister& zm) {5664// ZIP2 <Zd>.<T>, <Zn>.<T>, <Zm>.<T>5665// 0000 0101 ..1. .... 0110 01.. .... ....5666// size<23:22> | Zm<20:16> | opc<12:10> = 001 | Zn<9:5> | Zd<4:0>56675668VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5669VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));56705671Emit(ZIP2_z_zz | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));5672}56735674// SVEPermuteVectorPredicated.56755676void Assembler::clasta(const Register& rd,5677const PRegister& pg,5678const Register& rn,5679const ZRegister& zm) {5680// CLASTA <R><dn>, <Pg>, <R><dn>, <Zm>.<T>5681// 0000 0101 ..11 0000 101. .... .... ....5682// size<23:22> | B<16> = 0 | Pg<12:10> | Zm<9:5> | Rdn<4:0>56835684USE(rn);5685VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5686VIXL_ASSERT(rd.Is(rn));56875688Emit(CLASTA_r_p_z | SVESize(zm) | Rd(rd) | PgLow8(pg) | Rn(zm));5689}56905691void Assembler::clasta(const VRegister& vd,5692const PRegister& pg,5693const VRegister& vn,5694const ZRegister& zm) {5695// CLASTA <V><dn>, <Pg>, <V><dn>, <Zm>.<T>5696// 0000 0101 ..10 1010 100. .... .... ....5697// size<23:22> | B<16> = 0 | Pg<12:10> | Zm<9:5> | Vdn<4:0>56985699USE(vn);5700VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5701VIXL_ASSERT(vd.Is(vn));5702VIXL_ASSERT(vd.IsScalar());5703VIXL_ASSERT(AreSameLaneSize(vd, zm));57045705Emit(CLASTA_v_p_z | SVESize(zm) | Rd(vd) | PgLow8(pg) | Rn(zm));5706}57075708void Assembler::clasta(const ZRegister& zd,5709const PRegister& pg,5710const ZRegister& zn,5711const ZRegister& zm) {5712// CLASTA <Zdn>.<T>, <Pg>, <Zdn>.<T>, <Zm>.<T>5713// 0000 0101 ..10 1000 100. .... .... ....5714// size<23:22> | B<16> = 0 | Pg<12:10> | Zm<9:5> | Zdn<4:0>57155716USE(zn);5717VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5718VIXL_ASSERT(zd.Is(zn));5719VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));57205721Emit(CLASTA_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));5722}57235724void Assembler::clastb(const Register& rd,5725const PRegister& pg,5726const Register& rn,5727const ZRegister& zm) {5728// CLASTB <R><dn>, <Pg>, <R><dn>, <Zm>.<T>5729// 0000 0101 ..11 0001 101. .... .... ....5730// size<23:22> | B<16> = 1 | Pg<12:10> | Zm<9:5> | Rdn<4:0>57315732USE(rn);5733VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5734VIXL_ASSERT(rd.Is(rn));57355736Emit(CLASTB_r_p_z | SVESize(zm) | Rd(rd) | PgLow8(pg) | Rn(zm));5737}57385739void Assembler::clastb(const VRegister& vd,5740const PRegister& pg,5741const VRegister& vn,5742const ZRegister& zm) {5743// CLASTB <V><dn>, <Pg>, <V><dn>, <Zm>.<T>5744// 0000 0101 ..10 1011 100. .... .... ....5745// size<23:22> | B<16> = 1 | Pg<12:10> | Zm<9:5> | Vdn<4:0>57465747USE(vn);5748VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5749VIXL_ASSERT(vd.Is(vn));5750VIXL_ASSERT(vd.IsScalar());5751VIXL_ASSERT(AreSameLaneSize(vd, zm));57525753Emit(CLASTB_v_p_z | SVESize(zm) | Rd(vd) | PgLow8(pg) | Rn(zm));5754}57555756void Assembler::clastb(const ZRegister& zd,5757const PRegister& pg,5758const ZRegister& zn,5759const ZRegister& zm) {5760// CLASTB <Zdn>.<T>, <Pg>, <Zdn>.<T>, <Zm>.<T>5761// 0000 0101 ..10 1001 100. .... .... ....5762// size<23:22> | B<16> = 1 | Pg<12:10> | Zm<9:5> | Zdn<4:0>57635764USE(zn);5765VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5766VIXL_ASSERT(zd.Is(zn));5767VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));57685769Emit(CLASTB_z_p_zz | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));5770}57715772void Assembler::compact(const ZRegister& zd,5773const PRegister& pg,5774const ZRegister& zn) {5775// COMPACT <Zd>.<T>, <Pg>, <Zn>.<T>5776// 0000 0101 1.10 0001 100. .... .... ....5777// sz<22> | Pg<12:10> | Zn<9:5> | Zd<4:0>57785779VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5780VIXL_ASSERT(AreSameLaneSize(zd, zn));5781VIXL_ASSERT((zd.GetLaneSizeInBits() == kSRegSize) ||5782(zd.GetLaneSizeInBits() == kDRegSize));57835784Instr sz = (zd.GetLaneSizeInBits() == kDRegSize) ? (1 << 22) : 0;5785Emit(COMPACT_z_p_z | sz | Rd(zd) | PgLow8(pg) | Rn(zn));5786}57875788void Assembler::cpy(const ZRegister& zd,5789const PRegisterM& pg,5790const Register& rn) {5791// CPY <Zd>.<T>, <Pg>/M, <R><n|SP>5792// 0000 0101 ..10 1000 101. .... .... ....5793// size<23:22> | Pg<12:10> | Rn<9:5> | Zd<4:0>57945795VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5796VIXL_ASSERT(static_cast<unsigned>(rn.GetSizeInBits()) >=5797zd.GetLaneSizeInBits());57985799Emit(CPY_z_p_r | SVESize(zd) | Rd(zd) | PgLow8(pg) | RnSP(rn));5800}58015802void Assembler::cpy(const ZRegister& zd,5803const PRegisterM& pg,5804const VRegister& vn) {5805// CPY <Zd>.<T>, <Pg>/M, <V><n>5806// 0000 0101 ..10 0000 100. .... .... ....5807// size<23:22> | Pg<12:10> | Vn<9:5> | Zd<4:0>58085809VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5810VIXL_ASSERT(vn.IsScalar());5811VIXL_ASSERT(static_cast<unsigned>(vn.GetSizeInBits()) ==5812zd.GetLaneSizeInBits());58135814Emit(CPY_z_p_v | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(vn));5815}58165817void Assembler::lasta(const Register& rd,5818const PRegister& pg,5819const ZRegister& zn) {5820// LASTA <R><d>, <Pg>, <Zn>.<T>5821// 0000 0101 ..10 0000 101. .... .... ....5822// size<23:22> | B<16> = 0 | Pg<12:10> | Zn<9:5> | Rd<4:0>58235824VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));58255826Emit(LASTA_r_p_z | SVESize(zn) | Rd(rd) | PgLow8(pg) | Rn(zn));5827}58285829void Assembler::lasta(const VRegister& vd,5830const PRegister& pg,5831const ZRegister& zn) {5832// LASTA <V><d>, <Pg>, <Zn>.<T>5833// 0000 0101 ..10 0010 100. .... .... ....5834// size<23:22> | B<16> = 0 | Pg<12:10> | Zn<9:5> | Vd<4:0>58355836VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5837VIXL_ASSERT(vd.IsScalar());58385839Emit(LASTA_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));5840}58415842void Assembler::lastb(const Register& rd,5843const PRegister& pg,5844const ZRegister& zn) {5845// LASTB <R><d>, <Pg>, <Zn>.<T>5846// 0000 0101 ..10 0001 101. .... .... ....5847// size<23:22> | B<16> = 1 | Pg<12:10> | Zn<9:5> | Rd<4:0>58485849VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));58505851Emit(LASTB_r_p_z | SVESize(zn) | Rd(rd) | PgLow8(pg) | Rn(zn));5852}58535854void Assembler::lastb(const VRegister& vd,5855const PRegister& pg,5856const ZRegister& zn) {5857// LASTB <V><d>, <Pg>, <Zn>.<T>5858// 0000 0101 ..10 0011 100. .... .... ....5859// size<23:22> | B<16> = 1 | Pg<12:10> | Zn<9:5> | Vd<4:0>58605861VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5862VIXL_ASSERT(vd.IsScalar());58635864Emit(LASTB_v_p_z | SVESize(zn) | Rd(vd) | PgLow8(pg) | Rn(zn));5865}58665867void Assembler::rbit(const ZRegister& zd,5868const PRegisterM& pg,5869const ZRegister& zn) {5870// RBIT <Zd>.<T>, <Pg>/M, <Zn>.<T>5871// 0000 0101 ..10 0111 100. .... .... ....5872// size<23:22> | opc<17:16> = 11 | Pg<12:10> | Zn<9:5> | Zd<4:0>58735874VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5875VIXL_ASSERT(AreSameLaneSize(zd, zn));58765877Emit(RBIT_z_p_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));5878}58795880void Assembler::revb(const ZRegister& zd,5881const PRegisterM& pg,5882const ZRegister& zn) {5883// REVB <Zd>.<T>, <Pg>/M, <Zn>.<T>5884// 0000 0101 ..10 0100 100. .... .... ....5885// size<23:22> | opc<17:16> = 00 | Pg<12:10> | Zn<9:5> | Zd<4:0>58865887VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5888VIXL_ASSERT(AreSameLaneSize(zd, zn));5889VIXL_ASSERT(zd.IsLaneSizeH() || zd.IsLaneSizeS() || zd.IsLaneSizeD());58905891Emit(REVB_z_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));5892}58935894void Assembler::revh(const ZRegister& zd,5895const PRegisterM& pg,5896const ZRegister& zn) {5897// REVH <Zd>.<T>, <Pg>/M, <Zn>.<T>5898// 0000 0101 ..10 0101 100. .... .... ....5899// size<23:22> | opc<17:16> = 01 | Pg<12:10> | Zn<9:5> | Zd<4:0>59005901VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5902VIXL_ASSERT(AreSameLaneSize(zd, zn));5903VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());59045905Emit(REVH_z_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));5906}59075908void Assembler::revw(const ZRegister& zd,5909const PRegisterM& pg,5910const ZRegister& zn) {5911// REVW <Zd>.D, <Pg>/M, <Zn>.D5912// 0000 0101 ..10 0110 100. .... .... ....5913// size<23:22> | opc<17:16> = 10 | Pg<12:10> | Zn<9:5> | Zd<4:0>59145915VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5916VIXL_ASSERT(AreSameLaneSize(zd, zn));5917VIXL_ASSERT(zd.IsLaneSizeD());59185919Emit(REVW_z_z | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));5920}59215922void Assembler::splice(const ZRegister& zd,5923const PRegister& pg,5924const ZRegister& zn,5925const ZRegister& zm) {5926VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));59275928if (zd.Aliases(zn)) {5929// SPLICE <Zdn>.<T>, <Pg>, <Zdn>.<T>, <Zm>.<T>5930// 0000 0101 ..10 1100 100. .... .... ....5931// size<23:22> | Pg<12:10> | Zm<9:5> | Zdn<4:0>59325933USE(zn);5934VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5935VIXL_ASSERT(zd.Is(zn));59365937Emit(SPLICE_z_p_zz_des | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));5938} else {5939splice_con(zd, pg, zn, zm);5940}5941}59425943void Assembler::splice_con(const ZRegister& zd,5944const PRegister& pg,5945const ZRegister& zn1,5946const ZRegister& zn2) {5947// SPLICE <Zd>.<T>, <Pg>, { <Zn1>.<T>, <Zn2>.<T> }5948// 0000 0101 ..10 1101 100. .... .... ....5949// size<23:22> | Pg<12:10> | Zn<9:5> | Zd<4:0>59505951USE(zn2);5952VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));5953VIXL_ASSERT(AreConsecutive(zn1, zn2));5954VIXL_ASSERT(AreSameLaneSize(zd, zn1, zn2));59555956Emit(0x052d8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn1));5957}59585959// SVEPermuteVectorUnpredicated.59605961void Assembler::dup(const ZRegister& zd, const Register& xn) {5962// DUP <Zd>.<T>, <R><n|SP>5963// 0000 0101 ..10 0000 0011 10.. .... ....5964// size<23:22> | Rn<9:5> | Zd<4:0>59655966VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));59675968Emit(DUP_z_r | SVESize(zd) | Rd(zd) | RnSP(xn));5969}59705971void Assembler::dup(const ZRegister& zd, const ZRegister& zn, unsigned index) {5972// DUP <Zd>.<T>, <Zn>.<T>[<imm>]5973// 0000 0101 ..1. .... 0010 00.. .... ....5974// imm2<23:22> | tsz<20:16> | Zn<9:5> | Zd<4:0>59755976VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));5977VIXL_ASSERT(AreSameFormat(zd, zn));5978VIXL_ASSERT((index * zd.GetLaneSizeInBits()) < 512);5979int n = zd.GetLaneSizeInBytesLog2();5980unsigned imm_7 = (index << (n + 1)) | (1 << n);5981VIXL_ASSERT(IsUint7(imm_7));5982unsigned imm_2 = ExtractUnsignedBitfield32(6, 5, imm_7);5983unsigned tsz_5 = ExtractUnsignedBitfield32(4, 0, imm_7);59845985Emit(DUP_z_zi | ImmUnsignedField<23, 22>(imm_2) |5986ImmUnsignedField<20, 16>(tsz_5) | Rd(zd) | Rn(zn));5987}59885989void Assembler::insr(const ZRegister& zdn, const Register& rm) {5990// INSR <Zdn>.<T>, <R><m>5991// 0000 0101 ..10 0100 0011 10.. .... ....5992// size<23:22> | Rm<9:5> | Zdn<4:0>59935994VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));59955996Emit(INSR_z_r | SVESize(zdn) | Rd(zdn) | Rn(rm));5997}59985999void Assembler::insr(const ZRegister& zdn, const VRegister& vm) {6000// INSR <Zdn>.<T>, <V><m>6001// 0000 0101 ..11 0100 0011 10.. .... ....6002// size<23:22> | Vm<9:5> | Zdn<4:0>60036004VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6005VIXL_ASSERT(vm.IsScalar());60066007Emit(INSR_z_v | SVESize(zdn) | Rd(zdn) | Rn(vm));6008}60096010void Assembler::rev(const ZRegister& zd, const ZRegister& zn) {6011// REV <Zd>.<T>, <Zn>.<T>6012// 0000 0101 ..11 1000 0011 10.. .... ....6013// size<23:22> | Zn<9:5> | Zd<4:0>60146015VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6016VIXL_ASSERT(AreSameFormat(zd, zn));60176018Emit(REV_z_z | SVESize(zd) | Rd(zd) | Rn(zn));6019}60206021void Assembler::sunpkhi(const ZRegister& zd, const ZRegister& zn) {6022// SUNPKHI <Zd>.<T>, <Zn>.<Tb>6023// 0000 0101 ..11 0001 0011 10.. .... ....6024// size<23:22> | U<17> = 0 | H<16> = 1 | Zn<9:5> | Zd<4:0>60256026VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6027VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));6028VIXL_ASSERT(!zd.IsLaneSizeB());60296030Emit(SUNPKHI_z_z | SVESize(zd) | Rd(zd) | Rn(zn));6031}60326033void Assembler::sunpklo(const ZRegister& zd, const ZRegister& zn) {6034// SUNPKLO <Zd>.<T>, <Zn>.<Tb>6035// 0000 0101 ..11 0000 0011 10.. .... ....6036// size<23:22> | U<17> = 0 | H<16> = 0 | Zn<9:5> | Zd<4:0>60376038VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6039VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));6040VIXL_ASSERT(!zd.IsLaneSizeB());60416042Emit(SUNPKLO_z_z | SVESize(zd) | Rd(zd) | Rn(zn));6043}60446045void Assembler::tbl(const ZRegister& zd,6046const ZRegister& zn,6047const ZRegister& zm) {6048// TBL <Zd>.<T>, { <Zn>.<T> }, <Zm>.<T>6049// 0000 0101 ..1. .... 0011 00.. .... ....6050// size<23:22> | Zm<20:16> | Zn<9:5> | Zd<4:0>60516052VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6053VIXL_ASSERT(AreSameFormat(zd, zn, zm));60546055Emit(TBL_z_zz_1 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));6056}60576058void Assembler::uunpkhi(const ZRegister& zd, const ZRegister& zn) {6059// UUNPKHI <Zd>.<T>, <Zn>.<Tb>6060// 0000 0101 ..11 0011 0011 10.. .... ....6061// size<23:22> | U<17> = 1 | H<16> = 1 | Zn<9:5> | Zd<4:0>60626063VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6064VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));6065VIXL_ASSERT(!zd.IsLaneSizeB());60666067Emit(UUNPKHI_z_z | SVESize(zd) | Rd(zd) | Rn(zn));6068}60696070void Assembler::uunpklo(const ZRegister& zd, const ZRegister& zn) {6071// UUNPKLO <Zd>.<T>, <Zn>.<Tb>6072// 0000 0101 ..11 0010 0011 10.. .... ....6073// size<23:22> | U<17> = 1 | H<16> = 0 | Zn<9:5> | Zd<4:0>60746075VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6076VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));6077VIXL_ASSERT(!zd.IsLaneSizeB());60786079Emit(UUNPKLO_z_z | SVESize(zd) | Rd(zd) | Rn(zn));6080}60816082// SVEPredicateCount.60836084void Assembler::cntp(const Register& xd,6085const PRegister& pg,6086const PRegisterWithLaneSize& pn) {6087// CNTP <Xd>, <Pg>, <Pn>.<T>6088// 0010 0101 ..10 0000 10.. ..0. .... ....6089// size<23:22> | opc<18:16> = 000 | Pg<13:10> | o2<9> = 0 | Pn<8:5> | Rd<4:0>60906091VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6092VIXL_ASSERT(xd.IsX());6093VIXL_ASSERT(pg.IsUnqualified());6094if (pg.HasLaneSize()) VIXL_ASSERT(AreSameFormat(pg, pn));60956096Emit(CNTP_r_p_p | SVESize(pn) | Rd(xd) | Pg<13, 10>(pg) | Pn(pn));6097}60986099// SVEPredicateLogicalOp.6100void Assembler::and_(const PRegisterWithLaneSize& pd,6101const PRegisterZ& pg,6102const PRegisterWithLaneSize& pn,6103const PRegisterWithLaneSize& pm) {6104VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6105VIXL_ASSERT(AreSameFormat(pd, pn, pm));6106VIXL_ASSERT(pd.IsLaneSizeB());6107Emit(AND_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6108}61096110void Assembler::ands(const PRegisterWithLaneSize& pd,6111const PRegisterZ& pg,6112const PRegisterWithLaneSize& pn,6113const PRegisterWithLaneSize& pm) {6114VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6115VIXL_ASSERT(AreSameFormat(pd, pn, pm));6116VIXL_ASSERT(pd.IsLaneSizeB());6117Emit(ANDS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6118}61196120void Assembler::bic(const PRegisterWithLaneSize& pd,6121const PRegisterZ& pg,6122const PRegisterWithLaneSize& pn,6123const PRegisterWithLaneSize& pm) {6124VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6125VIXL_ASSERT(AreSameFormat(pd, pn, pm));6126VIXL_ASSERT(pd.IsLaneSizeB());6127Emit(BIC_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6128}61296130void Assembler::bics(const PRegisterWithLaneSize& pd,6131const PRegisterZ& pg,6132const PRegisterWithLaneSize& pn,6133const PRegisterWithLaneSize& pm) {6134VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6135VIXL_ASSERT(AreSameFormat(pd, pn, pm));6136VIXL_ASSERT(pd.IsLaneSizeB());6137Emit(BICS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6138}61396140void Assembler::eor(const PRegisterWithLaneSize& pd,6141const PRegisterZ& pg,6142const PRegisterWithLaneSize& pn,6143const PRegisterWithLaneSize& pm) {6144VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6145VIXL_ASSERT(AreSameFormat(pd, pn, pm));6146VIXL_ASSERT(pd.IsLaneSizeB());6147Emit(EOR_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6148}61496150void Assembler::eors(const PRegisterWithLaneSize& pd,6151const PRegisterZ& pg,6152const PRegisterWithLaneSize& pn,6153const PRegisterWithLaneSize& pm) {6154VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6155VIXL_ASSERT(AreSameFormat(pd, pn, pm));6156VIXL_ASSERT(pd.IsLaneSizeB());6157Emit(EORS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6158}61596160void Assembler::nand(const PRegisterWithLaneSize& pd,6161const PRegisterZ& pg,6162const PRegisterWithLaneSize& pn,6163const PRegisterWithLaneSize& pm) {6164VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6165VIXL_ASSERT(AreSameFormat(pd, pn, pm));6166VIXL_ASSERT(pd.IsLaneSizeB());6167Emit(NAND_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6168}61696170void Assembler::nands(const PRegisterWithLaneSize& pd,6171const PRegisterZ& pg,6172const PRegisterWithLaneSize& pn,6173const PRegisterWithLaneSize& pm) {6174VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6175VIXL_ASSERT(AreSameFormat(pd, pn, pm));6176VIXL_ASSERT(pd.IsLaneSizeB());6177Emit(NANDS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6178}61796180void Assembler::nor(const PRegisterWithLaneSize& pd,6181const PRegisterZ& pg,6182const PRegisterWithLaneSize& pn,6183const PRegisterWithLaneSize& pm) {6184VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6185VIXL_ASSERT(AreSameFormat(pd, pn, pm));6186VIXL_ASSERT(pd.IsLaneSizeB());6187Emit(NOR_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6188}61896190void Assembler::nors(const PRegisterWithLaneSize& pd,6191const PRegisterZ& pg,6192const PRegisterWithLaneSize& pn,6193const PRegisterWithLaneSize& pm) {6194VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6195VIXL_ASSERT(AreSameFormat(pd, pn, pm));6196VIXL_ASSERT(pd.IsLaneSizeB());6197Emit(NORS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6198}61996200void Assembler::orn(const PRegisterWithLaneSize& pd,6201const PRegisterZ& pg,6202const PRegisterWithLaneSize& pn,6203const PRegisterWithLaneSize& pm) {6204VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6205VIXL_ASSERT(AreSameFormat(pd, pn, pm));6206VIXL_ASSERT(pd.IsLaneSizeB());6207Emit(ORN_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6208}62096210void Assembler::orns(const PRegisterWithLaneSize& pd,6211const PRegisterZ& pg,6212const PRegisterWithLaneSize& pn,6213const PRegisterWithLaneSize& pm) {6214VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6215VIXL_ASSERT(AreSameFormat(pd, pn, pm));6216VIXL_ASSERT(pd.IsLaneSizeB());6217Emit(ORNS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6218}62196220void Assembler::orr(const PRegisterWithLaneSize& pd,6221const PRegisterZ& pg,6222const PRegisterWithLaneSize& pn,6223const PRegisterWithLaneSize& pm) {6224VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6225VIXL_ASSERT(AreSameFormat(pd, pn, pm));6226VIXL_ASSERT(pd.IsLaneSizeB());6227Emit(ORR_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6228}62296230void Assembler::orrs(const PRegisterWithLaneSize& pd,6231const PRegisterZ& pg,6232const PRegisterWithLaneSize& pn,6233const PRegisterWithLaneSize& pm) {6234VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6235VIXL_ASSERT(AreSameFormat(pd, pn, pm));6236VIXL_ASSERT(pd.IsLaneSizeB());6237Emit(ORRS_p_p_pp_z | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6238}62396240void Assembler::sel(const PRegisterWithLaneSize& pd,6241const PRegister& pg,6242const PRegisterWithLaneSize& pn,6243const PRegisterWithLaneSize& pm) {6244VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6245Emit(SEL_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6246}62476248// SVEPredicateMisc.62496250void Assembler::pfalse(const PRegisterWithLaneSize& pd) {6251// PFALSE <Pd>.B6252// 0010 0101 0001 1000 1110 0100 0000 ....6253// op<23> = 0 | S<22> = 0 | Pd<3:0>62546255VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6256// Ignore the lane size, since it makes no difference to the operation.62576258Emit(PFALSE_p | Pd(pd));6259}62606261void Assembler::pfirst(const PRegisterWithLaneSize& pd,6262const PRegister& pg,6263const PRegisterWithLaneSize& pn) {6264// PFIRST <Pdn>.B, <Pg>, <Pdn>.B6265// 0010 0101 0101 1000 1100 000. ...0 ....6266// op<23> = 0 | S<22> = 1 | Pg<8:5> | Pdn<3:0>62676268USE(pn);6269VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6270VIXL_ASSERT(pd.Is(pn));6271VIXL_ASSERT(pd.IsLaneSizeB());62726273Emit(PFIRST_p_p_p | Pd(pd) | Pg<8, 5>(pg));6274}62756276void Assembler::pnext(const PRegisterWithLaneSize& pd,6277const PRegister& pg,6278const PRegisterWithLaneSize& pn) {6279// PNEXT <Pdn>.<T>, <Pg>, <Pdn>.<T>6280// 0010 0101 ..01 1001 1100 010. ...0 ....6281// size<23:22> | Pg<8:5> | Pdn<3:0>62826283USE(pn);6284VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6285VIXL_ASSERT(pd.Is(pn));62866287Emit(PNEXT_p_p_p | SVESize(pd) | Pd(pd) | Pg<8, 5>(pg));6288}62896290void Assembler::ptest(const PRegister& pg, const PRegisterWithLaneSize& pn) {6291// PTEST <Pg>, <Pn>.B6292// 0010 0101 0101 0000 11.. ..0. ...0 00006293// op<23> = 0 | S<22> = 1 | Pg<13:10> | Pn<8:5> | opc2<3:0> = 000062946295VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6296VIXL_ASSERT(pn.IsLaneSizeB());62976298Emit(PTEST_p_p | Pg<13, 10>(pg) | Rx<8, 5>(pn));6299}63006301void Assembler::ptrue(const PRegisterWithLaneSize& pd, int pattern) {6302// PTRUE <Pd>.<T>{, <pattern>}6303// 0010 0101 ..01 1000 1110 00.. ...0 ....6304// size<23:22> | S<16> = 0 | pattern<9:5> | Pd<3:0>63056306VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));63076308Emit(PTRUE_p_s | SVESize(pd) | Pd(pd) | ImmSVEPredicateConstraint(pattern));6309}63106311void Assembler::ptrues(const PRegisterWithLaneSize& pd, int pattern) {6312// PTRUES <Pd>.<T>{, <pattern>}6313// 0010 0101 ..01 1001 1110 00.. ...0 ....6314// size<23:22> | S<16> = 1 | pattern<9:5> | Pd<3:0>63156316VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));63176318Emit(PTRUES_p_s | SVESize(pd) | Pd(pd) | ImmSVEPredicateConstraint(pattern));6319}63206321void Assembler::rdffr(const PRegisterWithLaneSize& pd) {6322// RDFFR <Pd>.B6323// 0010 0101 0001 1001 1111 0000 0000 ....6324// op<23> = 0 | S<22> = 0 | Pd<3:0>63256326VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));63276328Emit(RDFFR_p_f | Pd(pd));6329}63306331void Assembler::rdffr(const PRegisterWithLaneSize& pd, const PRegisterZ& pg) {6332// RDFFR <Pd>.B, <Pg>/Z6333// 0010 0101 0001 1000 1111 000. ...0 ....6334// op<23> = 0 | S<22> = 0 | Pg<8:5> | Pd<3:0>63356336VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));63376338Emit(RDFFR_p_p_f | Pd(pd) | Pg<8, 5>(pg));6339}63406341void Assembler::rdffrs(const PRegisterWithLaneSize& pd, const PRegisterZ& pg) {6342// RDFFRS <Pd>.B, <Pg>/Z6343// 0010 0101 0101 1000 1111 000. ...0 ....6344// op<23> = 0 | S<22> = 1 | Pg<8:5> | Pd<3:0>63456346VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));63476348Emit(RDFFRS_p_p_f | Pd(pd) | Pg<8, 5>(pg));6349}63506351// SVEPropagateBreak.63526353void Assembler::brkpa(const PRegisterWithLaneSize& pd,6354const PRegisterZ& pg,6355const PRegisterWithLaneSize& pn,6356const PRegisterWithLaneSize& pm) {6357// BRKPA <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B6358// 0010 0101 0000 .... 11.. ..0. ...0 ....6359// op<23> = 0 | S<22> = 0 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 0 |6360// Pd<3:0>63616362VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));63636364Emit(BRKPA_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6365}63666367void Assembler::brkpas(const PRegisterWithLaneSize& pd,6368const PRegisterZ& pg,6369const PRegisterWithLaneSize& pn,6370const PRegisterWithLaneSize& pm) {6371// BRKPAS <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B6372// 0010 0101 0100 .... 11.. ..0. ...0 ....6373// op<23> = 0 | S<22> = 1 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 0 |6374// Pd<3:0>63756376VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));63776378Emit(BRKPAS_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6379}63806381void Assembler::brkpb(const PRegisterWithLaneSize& pd,6382const PRegisterZ& pg,6383const PRegisterWithLaneSize& pn,6384const PRegisterWithLaneSize& pm) {6385// BRKPB <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B6386// 0010 0101 0000 .... 11.. ..0. ...1 ....6387// op<23> = 0 | S<22> = 0 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 1 |6388// Pd<3:0>63896390VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));63916392Emit(BRKPB_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6393}63946395void Assembler::brkpbs(const PRegisterWithLaneSize& pd,6396const PRegisterZ& pg,6397const PRegisterWithLaneSize& pn,6398const PRegisterWithLaneSize& pm) {6399// BRKPBS <Pd>.B, <Pg>/Z, <Pn>.B, <Pm>.B6400// 0010 0101 0100 .... 11.. ..0. ...1 ....6401// op<23> = 0 | S<22> = 1 | Pm<19:16> | Pg<13:10> | Pn<8:5> | B<4> = 1 |6402// Pd<3:0>64036404VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));64056406Emit(BRKPBS_p_p_pp | Pd(pd) | Pg<13, 10>(pg) | Pn(pn) | Pm(pm));6407}64086409// SVEStackFrameAdjustment.64106411void Assembler::addpl(const Register& xd, const Register& xn, int imm6) {6412// ADDPL <Xd|SP>, <Xn|SP>, #<imm>6413// 0000 0100 011. .... 0101 0... .... ....6414// op<22> = 1 | Rn<20:16> | imm6<10:5> | Rd<4:0>64156416VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6417VIXL_ASSERT(xd.IsX());6418VIXL_ASSERT(xn.IsX());64196420Emit(ADDPL_r_ri | RdSP(xd) | RmSP(xn) | ImmField<10, 5>(imm6));6421}64226423void Assembler::addvl(const Register& xd, const Register& xn, int imm6) {6424// ADDVL <Xd|SP>, <Xn|SP>, #<imm>6425// 0000 0100 001. .... 0101 0... .... ....6426// op<22> = 0 | Rn<20:16> | imm6<10:5> | Rd<4:0>64276428VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6429VIXL_ASSERT(xd.IsX());6430VIXL_ASSERT(xn.IsX());64316432Emit(ADDVL_r_ri | RdSP(xd) | RmSP(xn) | ImmField<10, 5>(imm6));6433}64346435// SVEStackFrameSize.64366437void Assembler::rdvl(const Register& xd, int imm6) {6438// RDVL <Xd>, #<imm>6439// 0000 0100 1011 1111 0101 0... .... ....6440// op<22> = 0 | opc2<20:16> = 11111 | imm6<10:5> | Rd<4:0>64416442VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6443VIXL_ASSERT(xd.IsX());64446445Emit(RDVL_r_i | Rd(xd) | ImmField<10, 5>(imm6));6446}64476448// SVEVectorSelect.64496450void Assembler::sel(const ZRegister& zd,6451const PRegister& pg,6452const ZRegister& zn,6453const ZRegister& zm) {6454VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6455VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));64566457Emit(SEL_z_p_zz | SVESize(zd) | Rd(zd) | Pg<13, 10>(pg) | Rn(zn) | Rm(zm));6458}64596460// SVEWriteFFR.64616462void Assembler::setffr() {6463// SETFFR6464// 0010 0101 0010 1100 1001 0000 0000 00006465// opc<23:22> = 0064666467VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));64686469Emit(SETFFR_f);6470}64716472void Assembler::wrffr(const PRegisterWithLaneSize& pn) {6473// WRFFR <Pn>.B6474// 0010 0101 0010 1000 1001 000. ...0 00006475// opc<23:22> = 00 | Pn<8:5>64766477VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));64786479Emit(WRFFR_f_p | Rx<8, 5>(pn));6480}64816482// Aliases.64836484void Assembler::bic(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {6485and_(zd, zn, ~imm);6486}64876488void Assembler::eon(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {6489eor(zd, zn, ~imm);6490}64916492void Assembler::orn(const ZRegister& zd, const ZRegister& zn, uint64_t imm) {6493orr(zd, zn, ~imm);6494}649564966497void Assembler::fmov(const ZRegister& zd, const PRegisterM& pg, double imm) {6498if (IsPositiveZero(imm)) {6499cpy(zd, pg, 0);6500} else {6501fcpy(zd, pg, imm);6502}6503}65046505void Assembler::fmov(const ZRegister& zd, double imm) {6506if (IsPositiveZero(imm)) {6507dup(zd, 0);6508} else {6509fdup(zd, imm);6510}6511}65126513void Assembler::mov(const PRegister& pd, const PRegister& pn) {6514// If the inputs carry a lane size, they must match.6515VIXL_ASSERT((!pd.HasLaneSize() && !pn.HasLaneSize()) ||6516AreSameLaneSize(pd, pn));6517orr(pd.VnB(), pn.Zeroing(), pn.VnB(), pn.VnB());6518}65196520void Assembler::mov(const PRegisterWithLaneSize& pd,6521const PRegisterM& pg,6522const PRegisterWithLaneSize& pn) {6523VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6524sel(pd, pg, pn, pd);6525}65266527void Assembler::mov(const PRegisterWithLaneSize& pd,6528const PRegisterZ& pg,6529const PRegisterWithLaneSize& pn) {6530VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6531and_(pd, pg, pn, pn);6532}65336534void Assembler::mov(const ZRegister& zd,6535const PRegister& pg,6536int imm8,6537int shift) {6538VIXL_ASSERT(pg.IsMerging() || pg.IsZeroing());6539cpy(zd, pg, imm8, shift);6540}65416542void Assembler::mov(const ZRegister& zd, const Register& xn) { dup(zd, xn); }65436544void Assembler::mov(const ZRegister& zd, const VRegister& vn) {6545VIXL_ASSERT(vn.IsScalar());6546VIXL_ASSERT(AreSameLaneSize(zd, vn));6547dup(zd, vn.Z().WithSameLaneSizeAs(vn), 0);6548}65496550void Assembler::mov(const ZRegister& zd, const ZRegister& zn) {6551VIXL_ASSERT(AreSameLaneSize(zd, zn));6552orr(zd.VnD(), zn.VnD(), zn.VnD());6553}65546555void Assembler::mov(const ZRegister& zd, const ZRegister& zn, unsigned index) {6556VIXL_ASSERT(AreSameLaneSize(zd, zn));6557dup(zd, zn, index);6558}65596560void Assembler::mov(const ZRegister& zd,6561const PRegisterM& pg,6562const Register& rn) {6563cpy(zd, pg, rn);6564}65656566void Assembler::mov(const ZRegister& zd,6567const PRegisterM& pg,6568const VRegister& vn) {6569VIXL_ASSERT(vn.IsScalar());6570VIXL_ASSERT(AreSameLaneSize(zd, vn));6571cpy(zd, pg, vn);6572}65736574void Assembler::mov(const ZRegister& zd,6575const PRegisterM& pg,6576const ZRegister& zn) {6577VIXL_ASSERT(AreSameLaneSize(zd, zn));6578sel(zd, pg, zn, zd);6579}65806581void Assembler::mov(const ZRegister& zd, uint64_t imm) {6582// Mov is an alias of dupm for certain values of imm. Whilst this matters in6583// the disassembler, for the assembler, we don't distinguish between the6584// two mnemonics, and simply call dupm.6585dupm(zd, imm);6586}65876588void Assembler::mov(const ZRegister& zd, int imm8, int shift) {6589dup(zd, imm8, shift);6590}65916592void Assembler::movs(const PRegister& pd, const PRegister& pn) {6593VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6594orrs(pd.VnB(), pn.Zeroing(), pn.VnB(), pn.VnB());6595}65966597void Assembler::movs(const PRegisterWithLaneSize& pd,6598const PRegisterZ& pg,6599const PRegisterWithLaneSize& pn) {6600VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6601ands(pd, pg, pn, pn);6602}66036604void Assembler::not_(const PRegisterWithLaneSize& pd,6605const PRegisterZ& pg,6606const PRegisterWithLaneSize& pn) {6607VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6608eor(pd, pg, pn, pg.VnB());6609}66106611void Assembler::nots(const PRegisterWithLaneSize& pd,6612const PRegisterZ& pg,6613const PRegisterWithLaneSize& pn) {6614VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));6615eors(pd, pg, pn, pg.VnB());6616}66176618// SVE266196620void Assembler::adclb(const ZRegister& zda,6621const ZRegister& zn,6622const ZRegister& zm) {6623// ADCLB <Zda>.<T>, <Zn>.<T>, <Zm>.<T>6624// 0100 0101 0.0. .... 1101 00.. .... ....6625// size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>66266627VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6628VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));6629VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());66306631Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;6632Emit(0x4500d000 | sz | Rd(zda) | Rn(zn) | Rm(zm));6633}66346635void Assembler::adclt(const ZRegister& zda,6636const ZRegister& zn,6637const ZRegister& zm) {6638// ADCLT <Zda>.<T>, <Zn>.<T>, <Zm>.<T>6639// 0100 0101 0.0. .... 1101 01.. .... ....6640// size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>66416642VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6643VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));6644VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());66456646Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;6647Emit(0x4500d400 | sz | Rd(zda) | Rn(zn) | Rm(zm));6648}66496650void Assembler::addhnb(const ZRegister& zd,6651const ZRegister& zn,6652const ZRegister& zm) {6653// ADDHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>6654// 0100 0101 ..1. .... 0110 00.. .... ....6655// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>66566657VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6658VIXL_ASSERT(AreSameLaneSize(zn, zm));6659VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));6660VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);66616662Emit(0x45206000 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));6663}66646665void Assembler::addhnt(const ZRegister& zd,6666const ZRegister& zn,6667const ZRegister& zm) {6668// ADDHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>6669// 0100 0101 ..1. .... 0110 01.. .... ....6670// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>66716672VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6673VIXL_ASSERT(AreSameLaneSize(zn, zm));6674VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));6675VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);66766677Emit(0x45206400 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));6678}66796680void Assembler::addp(const ZRegister& zd,6681const PRegisterM& pg,6682const ZRegister& zn,6683const ZRegister& zm) {6684// ADDP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>6685// 0100 0100 ..01 0001 101. .... .... ....6686// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>66876688USE(zn);6689VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6690VIXL_ASSERT(zd.Is(zn));6691VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));66926693Emit(0x4411a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));6694}66956696void Assembler::bcax(const ZRegister& zd,6697const ZRegister& zn,6698const ZRegister& zm,6699const ZRegister& zk) {6700// BCAX <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D6701// 0000 0100 011. .... 0011 10.. .... ....6702// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>67036704USE(zn);6705VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6706VIXL_ASSERT(zd.Is(zn));6707VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));6708VIXL_ASSERT(zd.IsLaneSizeD());67096710Emit(0x04603800 | Rd(zd) | Rm(zm) | Rn(zk));6711}67126713void Assembler::bdep(const ZRegister& zd,6714const ZRegister& zn,6715const ZRegister& zm) {6716// BDEP <Zd>.<T>, <Zn>.<T>, <Zm>.<T>6717// 0100 0101 ..0. .... 1011 01.. .... ....6718// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>67196720VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6721VIXL_ASSERT(CPUHas(CPUFeatures::kSVEBitPerm));6722VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));67236724Emit(0x4500b400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));6725}67266727void Assembler::bext(const ZRegister& zd,6728const ZRegister& zn,6729const ZRegister& zm) {6730// BEXT <Zd>.<T>, <Zn>.<T>, <Zm>.<T>6731// 0100 0101 ..0. .... 1011 00.. .... ....6732// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>67336734VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6735VIXL_ASSERT(CPUHas(CPUFeatures::kSVEBitPerm));6736VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));67376738Emit(0x4500b000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));6739}67406741void Assembler::bgrp(const ZRegister& zd,6742const ZRegister& zn,6743const ZRegister& zm) {6744// BGRP <Zd>.<T>, <Zn>.<T>, <Zm>.<T>6745// 0100 0101 ..0. .... 1011 10.. .... ....6746// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>67476748VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6749VIXL_ASSERT(CPUHas(CPUFeatures::kSVEBitPerm));6750VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));67516752Emit(0x4500b800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));6753}67546755void Assembler::bsl(const ZRegister& zd,6756const ZRegister& zn,6757const ZRegister& zm,6758const ZRegister& zk) {6759// BSL <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D6760// 0000 0100 001. .... 0011 11.. .... ....6761// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>67626763USE(zn);6764VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6765VIXL_ASSERT(zd.Is(zn));6766VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));6767VIXL_ASSERT(zd.IsLaneSizeD());67686769Emit(0x04203c00 | Rd(zd) | Rm(zm) | Rn(zk));6770}67716772void Assembler::bsl1n(const ZRegister& zd,6773const ZRegister& zn,6774const ZRegister& zm,6775const ZRegister& zk) {6776// BSL1N <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D6777// 0000 0100 011. .... 0011 11.. .... ....6778// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>67796780USE(zn);6781VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6782VIXL_ASSERT(zd.Is(zn));6783VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));6784VIXL_ASSERT(zd.IsLaneSizeD());67856786Emit(0x04603c00 | Rd(zd) | Rm(zm) | Rn(zk));6787}67886789void Assembler::bsl2n(const ZRegister& zd,6790const ZRegister& zn,6791const ZRegister& zm,6792const ZRegister& zk) {6793// BSL2N <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D6794// 0000 0100 101. .... 0011 11.. .... ....6795// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>67966797USE(zn);6798VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6799VIXL_ASSERT(zd.Is(zn));6800VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));6801VIXL_ASSERT(zd.IsLaneSizeD());68026803Emit(0x04a03c00 | Rd(zd) | Rm(zm) | Rn(zk));6804}68056806void Assembler::cadd(const ZRegister& zd,6807const ZRegister& zn,6808const ZRegister& zm,6809int rot) {6810// CADD <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, <const>6811// 0100 0101 ..00 0000 1101 1... .... ....6812// size<23:22> | op<16> | rot<10> | Zm<9:5> | Zdn<4:0>68136814USE(zn);6815VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6816VIXL_ASSERT(zd.Is(zn));6817VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));6818VIXL_ASSERT((rot == 90) || (rot == 270));68196820Instr rotate_bit = (rot == 90) ? 0 : (1 << 10);6821Emit(0x4500d800 | rotate_bit | SVESize(zd) | Rd(zd) | Rn(zm));6822}68236824void Assembler::cdot(const ZRegister& zda,6825const ZRegister& zn,6826const ZRegister& zm,6827int index,6828int rot) {6829// CDOT <Zda>.D, <Zn>.H, <Zm>.H[<imm>], <const>6830// 0100 0100 111. .... 0100 .... .... ....6831// size<23:22> | opc<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>68326833VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6834VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));6835VIXL_ASSERT(AreSameLaneSize(zn, zm));6836VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());6837VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));6838VIXL_ASSERT(index >= 0);68396840Instr zm_and_idx = 0;6841if (zm.IsLaneSizeB()) {6842// Zm<18:16> | i2<20:19>6843VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 3));6844zm_and_idx = (index << 19) | Rx<18, 16>(zm);6845} else {6846// Zm<19:16> | i1<20>6847VIXL_ASSERT(zm.IsLaneSizeH());6848VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 1));6849zm_and_idx = (index << 20) | Rx<19, 16>(zm);6850}68516852Instr rotate_bits = (rot / 90) << 10;6853Emit(0x44a04000 | zm_and_idx | rotate_bits | SVESize(zda) | Rd(zda) | Rn(zn));6854}68556856void Assembler::cdot(const ZRegister& zda,6857const ZRegister& zn,6858const ZRegister& zm,6859int rot) {6860// CDOT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>, <const>6861// 0100 0100 ..0. .... 0001 .... .... ....6862// size<23:22> | Zm<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>68636864VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6865VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));6866VIXL_ASSERT(AreSameLaneSize(zn, zm));6867VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());6868VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 4));68696870Instr rotate_bits = (rot / 90) << 10;6871Emit(0x44001000 | rotate_bits | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));6872}68736874void Assembler::cmla(const ZRegister& zda,6875const ZRegister& zn,6876const ZRegister& zm,6877int index,6878int rot) {6879// CMLA <Zda>.H, <Zn>.H, <Zm>.H[<imm>], <const>6880// 0100 0100 101. .... 0110 .... .... ....6881// size<23:22> | opc<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>68826883VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6884VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));6885VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));68866887Instr rotate_bit = (rot / 90) << 10;6888Emit(0x44a06000 | SVEMulComplexIndexHelper(zm, index) | rotate_bit | Rd(zda) |6889Rn(zn));6890}68916892void Assembler::cmla(const ZRegister& zda,6893const ZRegister& zn,6894const ZRegister& zm,6895int rot) {6896// CMLA <Zda>.<T>, <Zn>.<T>, <Zm>.<T>, <const>6897// 0100 0100 ..0. .... 0010 .... .... ....6898// size<23:22> | Zm<20:16> | op<12> | rot<11:10> | Zn<9:5> | Zda<4:0>68996900VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6901VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));6902VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));69036904Instr rotate_bit = (rot / 90) << 10;6905Emit(0x44002000 | rotate_bit | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));6906}69076908void Assembler::eor3(const ZRegister& zd,6909const ZRegister& zn,6910const ZRegister& zm,6911const ZRegister& zk) {6912// EOR3 <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D6913// 0000 0100 001. .... 0011 10.. .... ....6914// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>69156916USE(zn);6917VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6918VIXL_ASSERT(zd.Is(zn));6919VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));6920VIXL_ASSERT(zd.IsLaneSizeD());69216922Emit(0x04203800 | Rd(zd) | Rm(zm) | Rn(zk));6923}69246925void Assembler::eorbt(const ZRegister& zd,6926const ZRegister& zn,6927const ZRegister& zm) {6928// EORBT <Zd>.<T>, <Zn>.<T>, <Zm>.<T>6929// 0100 0101 ..0. .... 1001 00.. .... ....6930// size<23:22> | Zm<20:16> | tb<10> | Zn<9:5> | Zd<4:0>69316932VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6933VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));69346935Emit(0x45009000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));6936}69376938void Assembler::eortb(const ZRegister& zd,6939const ZRegister& zn,6940const ZRegister& zm) {6941// EORTB <Zd>.<T>, <Zn>.<T>, <Zm>.<T>6942// 0100 0101 ..0. .... 1001 01.. .... ....6943// size<23:22> | Zm<20:16> | tb<10> | Zn<9:5> | Zd<4:0>69446945VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6946VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));69476948Emit(0x45009400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));6949}69506951void Assembler::faddp(const ZRegister& zd,6952const PRegisterM& pg,6953const ZRegister& zn,6954const ZRegister& zm) {6955// FADDP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>6956// 0110 0100 ..01 0000 100. .... .... ....6957// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>69586959USE(zn);6960VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));6961VIXL_ASSERT(zd.Is(zn));6962VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));6963VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);69646965Emit(0x64108000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));6966}69676968void Assembler::fcvtlt(const ZRegister& zd,6969const PRegisterM& pg,6970const ZRegister& zn) {6971// FCVTLT <Zd>.S, <Pg>/M, <Zn>.H6972// 0110 0100 1000 1001 101. .... .... ....6973// opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>69746975VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));69766977Instr op;6978if (zd.IsLaneSizeD() && zn.IsLaneSizeS()) {6979op = 0x64cba000;6980} else {6981VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeH());6982op = 0x6489a000;6983}69846985Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));6986}69876988void Assembler::fcvtnt(const ZRegister& zd,6989const PRegisterM& pg,6990const ZRegister& zn) {6991// FCVTNT <Zd>.S, <Pg>/M, <Zn>.D6992// 0110 0100 1100 1010 101. .... .... ....6993// opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>69946995VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));69966997Instr op;6998if (zd.IsLaneSizeS() && zn.IsLaneSizeD()) {6999op = 0x64caa000;7000} else {7001VIXL_ASSERT(zd.IsLaneSizeH() && zn.IsLaneSizeS());7002op = 0x6488a000;7003}7004Emit(op | Rd(zd) | PgLow8(pg) | Rn(zn));7005}70067007void Assembler::fcvtx(const ZRegister& zd,7008const PRegisterM& pg,7009const ZRegister& zn) {7010// FCVTX <Zd>.S, <Pg>/M, <Zn>.D7011// 0110 0101 0000 1010 101. .... .... ....7012// opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>70137014VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7015VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeD());70167017Emit(0x650aa000 | Rd(zd) | PgLow8(pg) | Rn(zn));7018}70197020void Assembler::fcvtxnt(const ZRegister& zd,7021const PRegisterM& pg,7022const ZRegister& zn) {7023// FCVTXNT <Zd>.S, <Pg>/M, <Zn>.D7024// 0110 0100 0000 1010 101. .... .... ....7025// opc<23:22> | opc2<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>70267027VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));70287029Emit(0x640aa000 | Rd(zd) | PgLow8(pg) | Rn(zn));7030}70317032void Assembler::flogb(const ZRegister& zd,7033const PRegisterM& pg,7034const ZRegister& zn) {7035// FLOGB <Zd>.<T>, <Pg>/M, <Zn>.<T>7036// 0110 0101 0001 1..0 101. .... .... ....7037// opc<23:22> | opc2<18:17> | U<16> | Pg<12:10> | Zn<9:5> | Zd<4:0> | size<>70387039VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7040VIXL_ASSERT(AreSameLaneSize(zd, zn));7041VIXL_ASSERT(!zd.IsLaneSizeB());70427043// Size field is encoded in bits <18:17> rather than <23:22>.7044Instr size = SVESize(zd) >> 5;7045Emit(0x6518a000 | size | Rd(zd) | PgLow8(pg) | Rn(zn));7046}70477048void Assembler::fmaxnmp(const ZRegister& zd,7049const PRegisterM& pg,7050const ZRegister& zn,7051const ZRegister& zm) {7052// FMAXNMP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7053// 0110 0100 ..01 0100 100. .... .... ....7054// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>70557056USE(zn);7057VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7058VIXL_ASSERT(zd.Is(zn));7059VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));7060VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);70617062Emit(0x64148000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7063}70647065void Assembler::fmaxp(const ZRegister& zd,7066const PRegisterM& pg,7067const ZRegister& zn,7068const ZRegister& zm) {7069// FMAXP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7070// 0110 0100 ..01 0110 100. .... .... ....7071// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>70727073USE(zn);7074VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7075VIXL_ASSERT(zd.Is(zn));7076VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));7077VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);70787079Emit(0x64168000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7080}70817082void Assembler::fminnmp(const ZRegister& zd,7083const PRegisterM& pg,7084const ZRegister& zn,7085const ZRegister& zm) {7086// FMINNMP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7087// 0110 0100 ..01 0101 100. .... .... ....7088// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>70897090USE(zn);7091VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7092VIXL_ASSERT(zd.Is(zn));7093VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));7094VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);70957096Emit(0x64158000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7097}70987099void Assembler::fminp(const ZRegister& zd,7100const PRegisterM& pg,7101const ZRegister& zn,7102const ZRegister& zm) {7103// FMINP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7104// 0110 0100 ..01 0111 100. .... .... ....7105// size<23:22> | opc<18:16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>71067107USE(zn);7108VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7109VIXL_ASSERT(zd.Is(zn));7110VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));7111VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);71127113Emit(0x64178000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7114}71157116void Assembler::fmlalb(const ZRegister& zda,7117const ZRegister& zn,7118const ZRegister& zm) {7119// FMLALB <Zda>.S, <Zn>.H, <Zm>.H7120// 0110 0100 101. .... 1000 00.. .... ....7121// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>71227123VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7124VIXL_ASSERT(zda.IsLaneSizeS());7125VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());71267127Emit(0x64a08000 | Rd(zda) | Rn(zn) | Rm(zm));7128}71297130void Assembler::fmlalb(const ZRegister& zda,7131const ZRegister& zn,7132const ZRegister& zm,7133int index) {7134VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7135VIXL_ASSERT(zda.IsLaneSizeS());7136VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());7137VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));7138Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |7139(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);71407141Emit(0x64a04000 | Rd(zda) | Rn(zn) | zm_and_idx);7142}71437144void Assembler::fmlalt(const ZRegister& zda,7145const ZRegister& zn,7146const ZRegister& zm) {7147// FMLALT <Zda>.S, <Zn>.H, <Zm>.H7148// 0110 0100 101. .... 1000 01.. .... ....7149// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>71507151VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7152VIXL_ASSERT(zda.IsLaneSizeS());7153VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());71547155Emit(0x64a08400 | Rd(zda) | Rn(zn) | Rm(zm));7156}71577158void Assembler::fmlalt(const ZRegister& zda,7159const ZRegister& zn,7160const ZRegister& zm,7161int index) {7162// FMLALT <Zda>.S, <Zn>.H, <Zm>.H7163// 0110 0100 101. .... 1000 01.. .... ....7164// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>71657166VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7167VIXL_ASSERT(zda.IsLaneSizeS());7168VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());7169VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));7170Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |7171(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);71727173Emit(0x64a04400 | Rd(zda) | Rn(zn) | zm_and_idx);7174}71757176void Assembler::fmlslb(const ZRegister& zda,7177const ZRegister& zn,7178const ZRegister& zm) {7179// FMLSLB <Zda>.S, <Zn>.H, <Zm>.H7180// 0110 0100 101. .... 1010 00.. .... ....7181// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>71827183VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7184VIXL_ASSERT(zda.IsLaneSizeS());7185VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());71867187Emit(0x64a0a000 | Rd(zda) | Rn(zn) | Rm(zm));7188}71897190void Assembler::fmlslb(const ZRegister& zda,7191const ZRegister& zn,7192const ZRegister& zm,7193int index) {7194// FMLSLB <Zda>.S, <Zn>.H, <Zm>.H7195// 0110 0100 101. .... 1010 00.. .... ....7196// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>71977198VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7199VIXL_ASSERT(zda.IsLaneSizeS());7200VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());7201VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));7202Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |7203(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);72047205Emit(0x64a06000 | Rd(zda) | Rn(zn) | zm_and_idx);7206}72077208void Assembler::fmlslt(const ZRegister& zda,7209const ZRegister& zn,7210const ZRegister& zm) {7211// FMLSLT <Zda>.S, <Zn>.H, <Zm>.H7212// 0110 0100 101. .... 1010 01.. .... ....7213// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>72147215VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7216VIXL_ASSERT(zda.IsLaneSizeS());7217VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());72187219Emit(0x64a0a400 | Rd(zda) | Rn(zn) | Rm(zm));7220}72217222void Assembler::fmlslt(const ZRegister& zda,7223const ZRegister& zn,7224const ZRegister& zm,7225int index) {7226// FMLSLT <Zda>.S, <Zn>.H, <Zm>.H7227// 0110 0100 101. .... 1010 01.. .... ....7228// o2<22> | Zm<20:16> | op<13> | T<10> | Zn<9:5> | Zda<4:0>72297230VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7231VIXL_ASSERT(zda.IsLaneSizeS());7232VIXL_ASSERT(zn.IsLaneSizeH() && zm.IsLaneSizeH());7233VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));7234Instr zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |7235(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);72367237Emit(0x64a06400 | Rd(zda) | Rn(zn) | zm_and_idx);7238}72397240void Assembler::histcnt(const ZRegister& zd,7241const PRegisterZ& pg,7242const ZRegister& zn,7243const ZRegister& zm) {7244// HISTCNT <Zd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>7245// 0100 0101 ..1. .... 110. .... .... ....7246// size<23:22> | Zm<20:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>72477248VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7249VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));7250VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeD());72517252Emit(0x4520c000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn) | Rm(zm));7253}72547255void Assembler::histseg(const ZRegister& zd,7256const ZRegister& zn,7257const ZRegister& zm) {7258// HISTSEG <Zd>.B, <Zn>.B, <Zm>.B7259// 0100 0101 ..1. .... 1010 00.. .... ....7260// size<23:22> | Zm<20:16> | Zn<9:5> | Zd<4:0>72617262VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7263VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));7264VIXL_ASSERT(zd.IsLaneSizeB());72657266Emit(0x4520a000 | Rd(zd) | Rn(zn) | Rm(zm));7267}72687269void Assembler::match(const PRegisterWithLaneSize& pd,7270const PRegisterZ& pg,7271const ZRegister& zn,7272const ZRegister& zm) {7273// MATCH <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>7274// 0100 0101 ..1. .... 100. .... ...0 ....7275// size<23:22> | Zm<20:16> | Pg<12:10> | Zn<9:5> | op<4> | Pd<3:0>72767277VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7278VIXL_ASSERT(AreSameLaneSize(pd, zn, zm));7279VIXL_ASSERT(zm.IsLaneSizeB() || zm.IsLaneSizeH());72807281Emit(0x45208000 | SVESize(zm) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));7282}72837284void Assembler::mla(const ZRegister& zda,7285const ZRegister& zn,7286const ZRegister& zm,7287int index) {7288// MLA <Zda>.D, <Zn>.D, <Zm>.D[<imm>]7289// 0100 0100 111. .... 0000 10.. .... ....7290// size<23:22> | opc<20:16> | S<10> | Zn<9:5> | Zda<4:0>72917292VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7293VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));72947295Instr synthesised_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),7296zm,7297index,72980x44200800,72990x44a00800,73000x44e00800);73017302Emit(synthesised_op | Rd(zda) | Rn(zn));7303}73047305void Assembler::mls(const ZRegister& zda,7306const ZRegister& zn,7307const ZRegister& zm,7308int index) {7309// MLS <Zda>.D, <Zn>.D, <Zm>.D[<imm>]7310// 0100 0100 111. .... 0000 11.. .... ....7311// size<23:22> | opc<20:16> | S<10> | Zn<9:5> | Zda<4:0>73127313VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7314VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));73157316Instr synthesised_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),7317zm,7318index,73190x44200c00,73200x44a00c00,73210x44e00c00);73227323Emit(synthesised_op | Rd(zda) | Rn(zn));7324}73257326void Assembler::mul(const ZRegister& zd,7327const ZRegister& zn,7328const ZRegister& zm,7329int index) {7330// MUL <Zd>.D, <Zn>.D, <Zm>.D[<imm>]7331// 0100 0100 111. .... 1111 10.. .... ....7332// size<23:22> | opc<20:16> | Zn<9:5> | Zd<4:0>73337334VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7335VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));73367337Instr synthesised_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),7338zm,7339index,73400x4420f800,73410x44a0f800,73420x44e0f800);73437344Emit(synthesised_op | Rd(zd) | Rn(zn));7345}73467347void Assembler::mul(const ZRegister& zd,7348const ZRegister& zn,7349const ZRegister& zm) {7350// MUL <Zd>.<T>, <Zn>.<T>, <Zm>.<T>7351// 0000 0100 ..1. .... 0110 00.. .... ....7352// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>73537354VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7355VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));73567357Emit(0x04206000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7358}73597360void Assembler::nbsl(const ZRegister& zd,7361const ZRegister& zn,7362const ZRegister& zm,7363const ZRegister& zk) {7364// NBSL <Zdn>.D, <Zdn>.D, <Zm>.D, <Zk>.D7365// 0000 0100 111. .... 0011 11.. .... ....7366// opc<23:22> | Zm<20:16> | o2<10> | Zk<9:5> | Zdn<4:0>73677368USE(zn);7369VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7370VIXL_ASSERT(zd.Is(zn));7371VIXL_ASSERT(AreSameLaneSize(zd, zn, zm, zk));7372VIXL_ASSERT(zd.IsLaneSizeD());73737374Emit(0x04e03c00 | Rd(zd) | Rm(zm) | Rn(zk));7375}73767377void Assembler::nmatch(const PRegisterWithLaneSize& pd,7378const PRegisterZ& pg,7379const ZRegister& zn,7380const ZRegister& zm) {7381// NMATCH <Pd>.<T>, <Pg>/Z, <Zn>.<T>, <Zm>.<T>7382// 0100 0101 ..1. .... 100. .... ...1 ....7383// size<23:22> | Zm<20:16> | Pg<12:10> | Zn<9:5> | op<4> | Pd<3:0>73847385VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7386VIXL_ASSERT(AreSameLaneSize(pd, zn, zm));7387VIXL_ASSERT(zm.IsLaneSizeB() || zm.IsLaneSizeH());73887389Emit(0x45208010 | SVESize(zm) | Pd(pd) | PgLow8(pg) | Rn(zn) | Rm(zm));7390}73917392void Assembler::pmul(const ZRegister& zd,7393const ZRegister& zn,7394const ZRegister& zm) {7395// PMUL <Zd>.B, <Zn>.B, <Zm>.B7396// 0000 0100 001. .... 0110 01.. .... ....7397// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>73987399VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));74007401Emit(0x04206400 | Rd(zd) | Rn(zn) | Rm(zm));7402}74037404void Assembler::pmullb(const ZRegister& zd,7405const ZRegister& zn,7406const ZRegister& zm) {7407// PMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7408// 0100 0101 ..0. .... 0110 10.. .... ....7409// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>74107411VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7412VIXL_ASSERT(AreSameLaneSize(zn, zm));7413VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS());7414VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);7415// SVEPmull128 is not supported7416VIXL_ASSERT(!zd.IsLaneSizeQ());74177418Emit(0x45006800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7419}74207421void Assembler::pmullt(const ZRegister& zd,7422const ZRegister& zn,7423const ZRegister& zm) {7424// PMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7425// 0100 0101 ..0. .... 0110 11.. .... ....7426// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>74277428VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7429VIXL_ASSERT(AreSameLaneSize(zn, zm));7430VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS());7431VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);7432// SVEPmull128 is not supported7433VIXL_ASSERT(!zd.IsLaneSizeQ());74347435Emit(0x45006c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7436}74377438void Assembler::raddhnb(const ZRegister& zd,7439const ZRegister& zn,7440const ZRegister& zm) {7441// RADDHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7442// 0100 0101 ..1. .... 0110 10.. .... ....7443// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>74447445VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7446VIXL_ASSERT(AreSameLaneSize(zn, zm));7447VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));7448VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);74497450Emit(0x45206800 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));7451}74527453void Assembler::raddhnt(const ZRegister& zd,7454const ZRegister& zn,7455const ZRegister& zm) {7456// RADDHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7457// 0100 0101 ..1. .... 0110 11.. .... ....7458// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>74597460VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7461VIXL_ASSERT(AreSameLaneSize(zn, zm));7462VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));7463VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);74647465Emit(0x45206c00 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));7466}74677468#define VIXL_SVE_SHR_LIST(V) \7469V(rshrnb, 0x45201800) \7470V(rshrnt, 0x45201c00) \7471V(shrnb, 0x45201000) \7472V(shrnt, 0x45201400) \7473V(sqrshrnb, 0x45202800) \7474V(sqrshrnt, 0x45202c00) \7475V(sqrshrunb, 0x45200800) \7476V(sqrshrunt, 0x45200c00) \7477V(sqshrnb, 0x45202000) \7478V(sqshrnt, 0x45202400) \7479V(sqshrunb, 0x45200000) \7480V(sqshrunt, 0x45200400) \7481V(uqrshrnb, 0x45203800) \7482V(uqrshrnt, 0x45203c00) \7483V(uqshrnb, 0x45203000) \7484V(uqshrnt, 0x45203400)74857486#define VIXL_DEFINE_ASM_FUNC(MNE, X) \7487void Assembler::MNE(const ZRegister& zd, const ZRegister& zn, int shift) { \7488VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2)); \7489VIXL_ASSERT(!zd.IsLaneSizeD() && !zd.IsLaneSizeQ()); \7490VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2)); \7491Instr encoded_imm = \7492EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits()); \7493SVEBitwiseShiftImmediate(zd, zn, encoded_imm, X); \7494}7495VIXL_SVE_SHR_LIST(VIXL_DEFINE_ASM_FUNC)7496#undef VIXL_DEFINE_ASM_FUNC74977498void Assembler::rsubhnb(const ZRegister& zd,7499const ZRegister& zn,7500const ZRegister& zm) {7501// RSUBHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7502// 0100 0101 ..1. .... 0111 10.. .... ....7503// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>75047505VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7506VIXL_ASSERT(AreSameLaneSize(zn, zm));7507VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));7508VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);75097510Emit(0x45207800 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));7511}75127513void Assembler::rsubhnt(const ZRegister& zd,7514const ZRegister& zn,7515const ZRegister& zm) {7516// RSUBHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7517// 0100 0101 ..1. .... 0111 11.. .... ....7518// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>75197520VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7521VIXL_ASSERT(AreSameLaneSize(zn, zm));7522VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));7523VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);75247525Emit(0x45207c00 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));7526}75277528void Assembler::saba(const ZRegister& zda,7529const ZRegister& zn,7530const ZRegister& zm) {7531// SABA <Zda>.<T>, <Zn>.<T>, <Zm>.<T>7532// 0100 0101 ..0. .... 1111 10.. .... ....7533// size<23:22> | Zm<20:16> | U<10> | Zn<9:5> | Zda<4:0>75347535VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7536VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));75377538Emit(0x4500f800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));7539}75407541void Assembler::sabalb(const ZRegister& zda,7542const ZRegister& zn,7543const ZRegister& zm) {7544// SABALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7545// 0100 0101 ..0. .... 1100 00.. .... ....7546// size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>75477548VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7549VIXL_ASSERT(AreSameLaneSize(zn, zm));7550VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));7551VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);75527553Emit(0x4500c000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));7554}75557556void Assembler::sabalt(const ZRegister& zda,7557const ZRegister& zn,7558const ZRegister& zm) {7559// SABALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7560// 0100 0101 ..0. .... 1100 01.. .... ....7561// size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>75627563VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7564VIXL_ASSERT(AreSameLaneSize(zn, zm));7565VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));7566VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);75677568Emit(0x4500c400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));7569}75707571void Assembler::sabdlb(const ZRegister& zd,7572const ZRegister& zn,7573const ZRegister& zm) {7574// SABDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7575// 0100 0101 ..0. .... 0011 00.. .... ....7576// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |7577// Zd<4:0>75787579VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7580VIXL_ASSERT(AreSameLaneSize(zn, zm));7581VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));7582VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);75837584Emit(0x45003000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7585}75867587void Assembler::sabdlt(const ZRegister& zd,7588const ZRegister& zn,7589const ZRegister& zm) {7590// SABDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7591// 0100 0101 ..0. .... 0011 01.. .... ....7592// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |7593// Zd<4:0>75947595VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7596VIXL_ASSERT(AreSameLaneSize(zn, zm));7597VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));7598VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);75997600Emit(0x45003400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7601}76027603void Assembler::sadalp(const ZRegister& zda,7604const PRegisterM& pg,7605const ZRegister& zn) {7606// SADALP <Zda>.<T>, <Pg>/M, <Zn>.<Tb>7607// 0100 0100 ..00 0100 101. .... .... ....7608// size<23:22> | U<16> | Pg<12:10> | Zn<9:5> | Zda<4:0>76097610VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7611VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));7612VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);76137614Emit(0x4404a000 | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn));7615}76167617void Assembler::saddlb(const ZRegister& zd,7618const ZRegister& zn,7619const ZRegister& zm) {7620// SADDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7621// 0100 0101 ..0. .... 0000 00.. .... ....7622// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |7623// Zd<4:0>76247625VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7626VIXL_ASSERT(AreSameLaneSize(zn, zm));7627VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));7628VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);76297630Emit(0x45000000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7631}76327633void Assembler::saddlbt(const ZRegister& zd,7634const ZRegister& zn,7635const ZRegister& zm) {7636// SADDLBT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7637// 0100 0101 ..0. .... 1000 00.. .... ....7638// size<23:22> | Zm<20:16> | S<11> | tb<10> | Zn<9:5> | Zd<4:0>76397640VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7641VIXL_ASSERT(AreSameLaneSize(zn, zm));7642VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));7643VIXL_ASSERT(zd.IsLaneSizeD() || zd.IsLaneSizeH() || zd.IsLaneSizeS());76447645Emit(0x45008000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7646}76477648void Assembler::saddlt(const ZRegister& zd,7649const ZRegister& zn,7650const ZRegister& zm) {7651// SADDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7652// 0100 0101 ..0. .... 0000 01.. .... ....7653// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |7654// Zd<4:0>76557656VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7657VIXL_ASSERT(AreSameLaneSize(zn, zm));7658VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));7659VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);76607661Emit(0x45000400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7662}76637664void Assembler::saddwb(const ZRegister& zd,7665const ZRegister& zn,7666const ZRegister& zm) {7667// SADDWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>7668// 0100 0101 ..0. .... 0100 00.. .... ....7669// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>76707671VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7672VIXL_ASSERT(AreSameLaneSize(zd, zn));7673VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));7674VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);76757676Emit(0x45004000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7677}76787679void Assembler::saddwt(const ZRegister& zd,7680const ZRegister& zn,7681const ZRegister& zm) {7682// SADDWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>7683// 0100 0101 ..0. .... 0100 01.. .... ....7684// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>76857686VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7687VIXL_ASSERT(AreSameLaneSize(zd, zn));7688VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));7689VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);76907691Emit(0x45004400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7692}76937694void Assembler::sbclb(const ZRegister& zda,7695const ZRegister& zn,7696const ZRegister& zm) {7697// SBCLB <Zda>.<T>, <Zn>.<T>, <Zm>.<T>7698// 0100 0101 1.0. .... 1101 00.. .... ....7699// size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>77007701VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7702VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));7703VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());77047705Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;7706Emit(0x4580d000 | sz | Rd(zda) | Rn(zn) | Rm(zm));7707}77087709void Assembler::sbclt(const ZRegister& zda,7710const ZRegister& zn,7711const ZRegister& zm) {7712// SBCLT <Zda>.<T>, <Zn>.<T>, <Zm>.<T>7713// 0100 0101 1.0. .... 1101 01.. .... ....7714// size<23:22> | Zm<20:16> | T<10> | Zn<9:5> | Zda<4:0>77157716VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7717VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));7718VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());77197720Instr sz = zda.IsLaneSizeD() ? (1 << 22) : 0;7721Emit(0x4580d400 | sz | Rd(zda) | Rn(zn) | Rm(zm));7722}77237724void Assembler::shadd(const ZRegister& zd,7725const PRegisterM& pg,7726const ZRegister& zn,7727const ZRegister& zm) {7728// SHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7729// 0100 0100 ..01 0000 100. .... .... ....7730// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>77317732USE(zn);7733VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7734VIXL_ASSERT(zd.Is(zn));7735VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));77367737Emit(0x44108000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7738}77397740void Assembler::shsub(const ZRegister& zd,7741const PRegisterM& pg,7742const ZRegister& zn,7743const ZRegister& zm) {7744// SHSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7745// 0100 0100 ..01 0010 100. .... .... ....7746// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>77477748USE(zn);7749VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7750VIXL_ASSERT(zd.Is(zn));7751VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));77527753Emit(0x44128000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7754}77557756void Assembler::shsubr(const ZRegister& zd,7757const PRegisterM& pg,7758const ZRegister& zn,7759const ZRegister& zm) {7760// SHSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7761// 0100 0100 ..01 0110 100. .... .... ....7762// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>77637764USE(zn);7765VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7766VIXL_ASSERT(zd.Is(zn));7767VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));77687769Emit(0x44168000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7770}77717772void Assembler::sli(const ZRegister& zd, const ZRegister& zn, int shift) {7773// SLI <Zd>.<T>, <Zn>.<T>, #<const>7774// 0100 0101 ..0. .... 1111 01.. .... ....7775// tszh<23:22> | tszl<20:19> | imm3<18:16> | op<10> | Zn<9:5> | Zd<4:0>77767777VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7778VIXL_ASSERT(AreSameLaneSize(zd, zn));7779Instr encoded_imm =7780EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());77817782SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500f400);7783}77847785void Assembler::smaxp(const ZRegister& zd,7786const PRegisterM& pg,7787const ZRegister& zn,7788const ZRegister& zm) {7789// SMAXP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7790// 0100 0100 ..01 0100 101. .... .... ....7791// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>77927793USE(zn);7794VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7795VIXL_ASSERT(zd.Is(zn));7796VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));77977798Emit(0x4414a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7799}78007801void Assembler::sminp(const ZRegister& zd,7802const PRegisterM& pg,7803const ZRegister& zn,7804const ZRegister& zm) {7805// SMINP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7806// 0100 0100 ..01 0110 101. .... .... ....7807// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>78087809USE(zn);7810VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7811VIXL_ASSERT(zd.Is(zn));7812VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));78137814Emit(0x4416a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7815}78167817#define VIXL_SVE_MULL_INDEX_LIST(V) \7818V(smullb, 0x44a0c000) \7819V(smullt, 0x44a0c400) \7820V(umullb, 0x44a0d000) \7821V(umullt, 0x44a0d400) \7822V(smlalb, 0x44a08000) \7823V(smlalt, 0x44a08400) \7824V(smlslb, 0x44a0a000) \7825V(smlslt, 0x44a0a400) \7826V(umlalb, 0x44a09000) \7827V(umlalt, 0x44a09400) \7828V(umlslb, 0x44a0b000) \7829V(umlslt, 0x44a0b400) \7830V(sqdmullb, 0x44a0e000) \7831V(sqdmullt, 0x44a0e400)78327833#define VIXL_DEFINE_ASM_FUNC(MNE, OP) \7834void Assembler::MNE(const ZRegister& zda, \7835const ZRegister& zn, \7836const ZRegister& zm, \7837int index) { \7838VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2)); \7839VIXL_ASSERT(AreSameLaneSize(zn, zm)); \7840VIXL_ASSERT(zda.IsLaneSizeD() || zda.IsLaneSizeS()); \7841VIXL_ASSERT(zda.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2); \7842Instr zm_with_index = SVEMulLongIndexHelper(zm, index); \7843Emit(OP | SVESize(zda) | Rd(zda) | Rn(zn) | zm_with_index); \7844}7845VIXL_SVE_MULL_INDEX_LIST(VIXL_DEFINE_ASM_FUNC)7846#undef VIXL_DEFINE_ASM_FuNC78477848void Assembler::smlalb(const ZRegister& zda,7849const ZRegister& zn,7850const ZRegister& zm) {7851// SMLALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7852// 0100 0100 ..0. .... 0100 00.. .... ....7853// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>78547855VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7856VIXL_ASSERT(!zda.IsLaneSizeB());7857VIXL_ASSERT(AreSameLaneSize(zn, zm));7858VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));78597860Emit(0x44004000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));7861}78627863void Assembler::smlalt(const ZRegister& zda,7864const ZRegister& zn,7865const ZRegister& zm) {7866// SMLALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7867// 0100 0100 ..0. .... 0100 01.. .... ....7868// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>78697870VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7871VIXL_ASSERT(!zda.IsLaneSizeB());7872VIXL_ASSERT(AreSameLaneSize(zn, zm));7873VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));78747875Emit(0x44004400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));7876}78777878void Assembler::smlslb(const ZRegister& zda,7879const ZRegister& zn,7880const ZRegister& zm) {7881// SMLSLB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7882// 0100 0100 ..0. .... 0101 00.. .... ....7883// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>78847885VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7886VIXL_ASSERT(!zda.IsLaneSizeB());7887VIXL_ASSERT(AreSameLaneSize(zn, zm));7888VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));78897890Emit(0x44005000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));7891}78927893void Assembler::smlslt(const ZRegister& zda,7894const ZRegister& zn,7895const ZRegister& zm) {7896// SMLSLT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7897// 0100 0100 ..0. .... 0101 01.. .... ....7898// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>78997900VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7901VIXL_ASSERT(!zda.IsLaneSizeB());7902VIXL_ASSERT(AreSameLaneSize(zn, zm));7903VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));79047905Emit(0x44005400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));7906}79077908void Assembler::smulh(const ZRegister& zd,7909const ZRegister& zn,7910const ZRegister& zm) {7911// SMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>7912// 0000 0100 ..1. .... 0110 10.. .... ....7913// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>79147915VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7916VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));79177918Emit(0x04206800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7919}79207921void Assembler::smullb(const ZRegister& zd,7922const ZRegister& zn,7923const ZRegister& zm) {7924// SMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7925// 0100 0101 ..0. .... 0111 00.. .... ....7926// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>79277928VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7929VIXL_ASSERT(AreSameLaneSize(zn, zm));7930VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());7931VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);79327933Emit(0x45007000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7934}79357936void Assembler::smullt(const ZRegister& zd,7937const ZRegister& zn,7938const ZRegister& zm) {7939// SMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>7940// 0100 0101 ..0. .... 0111 01.. .... ....7941// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>79427943VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7944VIXL_ASSERT(AreSameLaneSize(zn, zm));7945VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());7946VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);79477948Emit(0x45007400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));7949}79507951void Assembler::sqabs(const ZRegister& zd,7952const PRegisterM& pg,7953const ZRegister& zn) {7954// SQABS <Zd>.<T>, <Pg>/M, <Zn>.<T>7955// 0100 0100 ..00 1000 101. .... .... ....7956// size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>79577958VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7959VIXL_ASSERT(AreSameLaneSize(zd, zn));79607961Emit(0x4408a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));7962}79637964void Assembler::sqadd(const ZRegister& zd,7965const PRegisterM& pg,7966const ZRegister& zn,7967const ZRegister& zm) {7968// SQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>7969// 0100 0100 ..01 1000 100. .... .... ....7970// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>79717972USE(zn);7973VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7974VIXL_ASSERT(zd.Is(zn));7975VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));79767977Emit(0x44188000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));7978}79797980void Assembler::sqcadd(const ZRegister& zd,7981const ZRegister& zn,7982const ZRegister& zm,7983int rot) {7984// SQCADD <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, <const>7985// 0100 0101 ..00 0001 1101 1... .... ....7986// size<23:22> | op<16> | rot<10> | Zm<9:5> | Zdn<4:0>79877988USE(zn);7989VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));7990VIXL_ASSERT(zd.Is(zn));7991VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));7992VIXL_ASSERT((rot == 90) || (rot == 270));79937994Instr rotate_bit = (rot == 90) ? 0 : (1 << 10);7995Emit(0x4501d800 | rotate_bit | SVESize(zd) | Rd(zd) | Rn(zm));7996}79977998// This prototype maps to 2 instruction encodings:7999// sqdmlalb_z_zzzi_d8000// sqdmlalb_z_zzzi_s8001void Assembler::sqdmlalb(const ZRegister& zda,8002const ZRegister& zn,8003const ZRegister& zm,8004int index) {8005// SQDMLALB <Zda>.D, <Zn>.S, <Zm>.S[<imm>]8006// 0100 0100 111. .... 0010 .0.. .... ....8007// size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>80088009VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8010VIXL_ASSERT(AreSameLaneSize(zn, zm));8011VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());8012VIXL_ASSERT(index >= 0);80138014Instr zm_and_idx = 0;8015if (zm.IsLaneSizeH()) {8016// Zm<18:16> | i3h<20:19> | i3l<11>8017VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));8018zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |8019(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);8020} else {8021// Zm<19:16> | i2h<20> | i2l<11>8022VIXL_ASSERT(zm.IsLaneSizeS());8023VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));8024zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |8025Rx<19, 16>(zm);8026}80278028Emit(0x44202000 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));8029}80308031void Assembler::sqdmlalb(const ZRegister& zda,8032const ZRegister& zn,8033const ZRegister& zm) {8034// SQDMLALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8035// 0100 0100 ..0. .... 0110 00.. .... ....8036// size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>80378038VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8039VIXL_ASSERT(AreSameLaneSize(zn, zm));8040VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8041VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);80428043Emit(0x44006000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8044}80458046void Assembler::sqdmlalbt(const ZRegister& zda,8047const ZRegister& zn,8048const ZRegister& zm) {8049// SQDMLALBT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8050// 0100 0100 ..0. .... 0000 10.. .... ....8051// size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>80528053VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8054VIXL_ASSERT(AreSameLaneSize(zn, zm));8055VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8056VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);80578058Emit(0x44000800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8059}80608061// This prototype maps to 2 instruction encodings:8062// sqdmlalt_z_zzzi_d8063// sqdmlalt_z_zzzi_s8064void Assembler::sqdmlalt(const ZRegister& zda,8065const ZRegister& zn,8066const ZRegister& zm,8067int index) {8068// SQDMLALT <Zda>.D, <Zn>.S, <Zm>.S[<imm>]8069// 0100 0100 111. .... 0010 .1.. .... ....8070// size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>80718072VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8073VIXL_ASSERT(AreSameLaneSize(zn, zm));8074VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());8075VIXL_ASSERT(index >= 0);80768077Instr zm_and_idx = 0;8078if (zm.IsLaneSizeH()) {8079// Zm<18:16> | i3h<20:19> | i3l<11>8080VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));8081zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |8082(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);8083} else {8084// Zm<19:16> | i2h<20> | i2l<11>8085VIXL_ASSERT(zm.IsLaneSizeS());8086VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));8087zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |8088Rx<19, 16>(zm);8089}80908091Emit(0x44202400 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));8092}80938094void Assembler::sqdmlalt(const ZRegister& zda,8095const ZRegister& zn,8096const ZRegister& zm) {8097// SQDMLALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8098// 0100 0100 ..0. .... 0110 01.. .... ....8099// size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>81008101VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8102VIXL_ASSERT(AreSameLaneSize(zn, zm));8103VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8104VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);81058106Emit(0x44006400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8107}81088109// This prototype maps to 2 instruction encodings:8110// sqdmlslb_z_zzzi_d8111// sqdmlslb_z_zzzi_s8112void Assembler::sqdmlslb(const ZRegister& zda,8113const ZRegister& zn,8114const ZRegister& zm,8115int index) {8116// SQDMLSLB <Zda>.D, <Zn>.S, <Zm>.S[<imm>]8117// 0100 0100 111. .... 0011 .0.. .... ....8118// size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>81198120VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8121VIXL_ASSERT(AreSameLaneSize(zn, zm));8122VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());8123VIXL_ASSERT(index >= 0);81248125Instr zm_and_idx = 0;8126if (zm.IsLaneSizeH()) {8127// Zm<18:16> | i3h<20:19> | i3l<11>8128VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));8129zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |8130(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);8131} else {8132// Zm<19:16> | i2h<20> | i2l<11>8133VIXL_ASSERT(zm.IsLaneSizeS());8134VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));8135zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |8136Rx<19, 16>(zm);8137}81388139Emit(0x44203000 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));8140}81418142void Assembler::sqdmlslb(const ZRegister& zda,8143const ZRegister& zn,8144const ZRegister& zm) {8145// SQDMLSLB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8146// 0100 0100 ..0. .... 0110 10.. .... ....8147// size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>81488149VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8150VIXL_ASSERT(AreSameLaneSize(zn, zm));8151VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8152VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);81538154Emit(0x44006800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8155}81568157void Assembler::sqdmlslbt(const ZRegister& zda,8158const ZRegister& zn,8159const ZRegister& zm) {8160// SQDMLSLBT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8161// 0100 0100 ..0. .... 0000 11.. .... ....8162// size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>81638164VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8165VIXL_ASSERT(AreSameLaneSize(zn, zm));8166VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8167VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);81688169Emit(0x44000c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8170}81718172// This prototype maps to 2 instruction encodings:8173// sqdmlslt_z_zzzi_d8174// sqdmlslt_z_zzzi_s8175void Assembler::sqdmlslt(const ZRegister& zda,8176const ZRegister& zn,8177const ZRegister& zm,8178int index) {8179// SQDMLSLT <Zda>.D, <Zn>.S, <Zm>.S[<imm>]8180// 0100 0100 111. .... 0011 .1.. .... ....8181// size<23:22> | opc<20:16> | S<12> | il<11> | T<10> | Zn<9:5> | Zda<4:0>81828183VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8184VIXL_ASSERT(AreSameLaneSize(zn, zm));8185VIXL_ASSERT(zda.IsLaneSizeS() || zda.IsLaneSizeD());8186VIXL_ASSERT(index >= 0);81878188Instr zm_and_idx = 0;8189if (zm.IsLaneSizeH()) {8190// Zm<18:16> | i3h<20:19> | i3l<11>8191VIXL_ASSERT((zm.GetCode() <= 7) && (index <= 7));8192zm_and_idx = (ExtractUnsignedBitfield32(2, 1, index) << 19) |8193(ExtractBit(index, 0) << 11) | Rx<18, 16>(zm);8194} else {8195// Zm<19:16> | i2h<20> | i2l<11>8196VIXL_ASSERT(zm.IsLaneSizeS());8197VIXL_ASSERT((zm.GetCode() <= 15) && (index <= 3));8198zm_and_idx = (ExtractBit(index, 1) << 20) | (ExtractBit(index, 0) << 11) |8199Rx<19, 16>(zm);8200}82018202Emit(0x44203400 | zm_and_idx | SVESize(zda) | Rd(zda) | Rn(zn));8203}82048205void Assembler::sqdmlslt(const ZRegister& zda,8206const ZRegister& zn,8207const ZRegister& zm) {8208// SQDMLSLT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8209// 0100 0100 ..0. .... 0110 11.. .... ....8210// size<23:22> | Zm<20:16> | S<11> | T<10> | Zn<9:5> | Zda<4:0>82118212VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8213VIXL_ASSERT(AreSameLaneSize(zn, zm));8214VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8215VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);82168217Emit(0x44006c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8218}82198220void Assembler::sqdmulh(const ZRegister& zd,8221const ZRegister& zn,8222const ZRegister& zm,8223int index) {8224// SQDMULH <Zd>.D, <Zn>.D, <Zm>.D[<imm>]8225// 0100 0100 111. .... 1111 00.. .... ....8226// size<23:22> | opc<20:16> | R<10> | Zn<9:5> | Zd<4:0>82278228VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8229VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));82308231Instr synthesised_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),8232zm,8233index,82340x4420f000,82350x44a0f000,82360x44e0f000);82378238Emit(synthesised_op | Rd(zd) | Rn(zn));8239}82408241void Assembler::sqdmulh(const ZRegister& zd,8242const ZRegister& zn,8243const ZRegister& zm) {8244// SQDMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>8245// 0000 0100 ..1. .... 0111 00.. .... ....8246// size<23:22> | Zm<20:16> | R<10> | Zn<9:5> | Zd<4:0>82478248VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8249VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));82508251Emit(0x04207000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8252}82538254void Assembler::sqdmullb(const ZRegister& zd,8255const ZRegister& zn,8256const ZRegister& zm) {8257// SQDMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8258// 0100 0101 ..0. .... 0110 00.. .... ....8259// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>82608261VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8262VIXL_ASSERT(AreSameLaneSize(zn, zm));8263VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());8264VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);82658266Emit(0x45006000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8267}82688269void Assembler::sqdmullt(const ZRegister& zd,8270const ZRegister& zn,8271const ZRegister& zm) {8272// SQDMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8273// 0100 0101 ..0. .... 0110 01.. .... ....8274// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>82758276VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8277VIXL_ASSERT(AreSameLaneSize(zn, zm));8278VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());8279VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);82808281Emit(0x45006400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8282}82838284void Assembler::sqneg(const ZRegister& zd,8285const PRegisterM& pg,8286const ZRegister& zn) {8287// SQNEG <Zd>.<T>, <Pg>/M, <Zn>.<T>8288// 0100 0100 ..00 1001 101. .... .... ....8289// size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>82908291VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8292VIXL_ASSERT(AreSameLaneSize(zd, zn));82938294Emit(0x4409a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));8295}82968297void Assembler::sqrdcmlah(const ZRegister& zda,8298const ZRegister& zn,8299const ZRegister& zm,8300int index,8301int rot) {8302// SQRDCMLAH <Zda>.H, <Zn>.H, <Zm>.H[<imm>], <const>8303// 0100 0100 101. .... 0111 .... .... ....8304// size<23:22> | opc<20:16> | rot<11:10> | Zn<9:5> | Zda<4:0>83058306VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8307VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));8308VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));83098310Instr rotate_bit = (rot / 90) << 10;8311Emit(0x44a07000 | SVEMulComplexIndexHelper(zm, index) | rotate_bit | Rd(zda) |8312Rn(zn));8313}83148315void Assembler::sqrdcmlah(const ZRegister& zda,8316const ZRegister& zn,8317const ZRegister& zm,8318int rot) {8319// SQRDCMLAH <Zda>.<T>, <Zn>.<T>, <Zm>.<T>, <const>8320// 0100 0100 ..0. .... 0011 .... .... ....8321// size<23:22> | Zm<20:16> | op<12> | rot<11:10> | Zn<9:5> | Zda<4:0>83228323VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8324VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));8325VIXL_ASSERT((rot == 0) || (rot == 90) || (rot == 180) || (rot == 270));83268327Instr rotate_bit = (rot / 90) << 10;8328Emit(0x44003000 | rotate_bit | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8329}83308331// This prototype maps to 3 instruction encodings:8332// sqrdmlah_z_zzzi_d8333// sqrdmlah_z_zzzi_h8334// sqrdmlah_z_zzzi_s8335void Assembler::sqrdmlah(const ZRegister& zda,8336const ZRegister& zn,8337const ZRegister& zm,8338int index) {8339VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8340VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));83418342Instr op_h = 0x44201000;8343Instr op_s = op_h | (1 << 23);8344Instr op_d = op_h | (3 << 22);8345// The encoding of opcode, index, Zm, and size are synthesized in this8346// variable.8347Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),8348zm,8349index,8350op_h,8351op_s,8352op_d);83538354Emit(synthesized_op | Rd(zda) | Rn(zn));8355}83568357void Assembler::sqrdmlah(const ZRegister& zda,8358const ZRegister& zn,8359const ZRegister& zm) {8360// SQRDMLAH <Zda>.<T>, <Zn>.<T>, <Zm>.<T>8361// 0100 0100 ..0. .... 0111 00.. .... ....8362// size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>83638364VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8365VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));83668367Emit(0x44007000 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8368}83698370// This prototype maps to 3 instruction encodings:8371// sqrdmlsh_z_zzzi_d8372// sqrdmlsh_z_zzzi_h8373// sqrdmlsh_z_zzzi_s8374void Assembler::sqrdmlsh(const ZRegister& zda,8375const ZRegister& zn,8376const ZRegister& zm,8377int index) {8378VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8379VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));83808381Instr op_h = 0x44201400;8382Instr op_s = op_h | (1 << 23);8383Instr op_d = op_h | (3 << 22);8384// The encoding of opcode, index, Zm, and size are synthesized in this8385// variable.8386Instr synthesized_op = SVEMulIndexHelper(zda.GetLaneSizeInBytesLog2(),8387zm,8388index,8389op_h,8390op_s,8391op_d);83928393Emit(synthesized_op | Rd(zda) | Rn(zn));8394}83958396void Assembler::sqrdmlsh(const ZRegister& zda,8397const ZRegister& zn,8398const ZRegister& zm) {8399// SQRDMLSH <Zda>.<T>, <Zn>.<T>, <Zm>.<T>8400// 0100 0100 ..0. .... 0111 01.. .... ....8401// size<23:22> | Zm<20:16> | S<10> | Zn<9:5> | Zda<4:0>84028403VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8404VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));84058406Emit(0x44007400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8407}84088409void Assembler::sqrdmulh(const ZRegister& zd,8410const ZRegister& zn,8411const ZRegister& zm,8412int index) {8413// SQRDMULH <Zd>.D, <Zn>.D, <Zm>.D[<imm>]8414// 0100 0100 111. .... 1111 01.. .... ....8415// size<23:22> | opc<20:16> | R<10> | Zn<9:5> | Zd<4:0>84168417VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8418VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));84198420Instr synthesised_op = SVEMulIndexHelper(zd.GetLaneSizeInBytesLog2(),8421zm,8422index,84230x4420f400,84240x44a0f400,84250x44e0f400);84268427Emit(synthesised_op | Rd(zd) | Rn(zn));8428}84298430void Assembler::sqrdmulh(const ZRegister& zd,8431const ZRegister& zn,8432const ZRegister& zm) {8433// SQRDMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>8434// 0000 0100 ..1. .... 0111 01.. .... ....8435// size<23:22> | Zm<20:16> | R<10> | Zn<9:5> | Zd<4:0>84368437VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8438VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));84398440Emit(0x04207400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8441}84428443void Assembler::sqrshl(const ZRegister& zd,8444const PRegisterM& pg,8445const ZRegister& zn,8446const ZRegister& zm) {8447// SQRSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8448// 0100 0100 ..00 1010 100. .... .... ....8449// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |8450// Zdn<4:0>84518452USE(zn);8453VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8454VIXL_ASSERT(zd.Is(zn));8455VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));84568457Emit(0x440a8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8458}84598460void Assembler::sqrshlr(const ZRegister& zd,8461const PRegisterM& pg,8462const ZRegister& zn,8463const ZRegister& zm) {8464// SQRSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8465// 0100 0100 ..00 1110 100. .... .... ....8466// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |8467// Zdn<4:0>84688469USE(zn);8470VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8471VIXL_ASSERT(zd.Is(zn));8472VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));84738474Emit(0x440e8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8475}84768477void Assembler::sqshl(const ZRegister& zd,8478const PRegisterM& pg,8479const ZRegister& zn,8480int shift) {8481// SQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>8482// 0000 0100 ..00 0110 100. .... .... ....8483// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |8484// imm3<7:5> | Zdn<4:0>84858486USE(zn);8487VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8488VIXL_ASSERT(zd.Is(zn));8489Instr encoded_imm =8490EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());8491SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x04068000);8492}84938494void Assembler::sqshl(const ZRegister& zd,8495const PRegisterM& pg,8496const ZRegister& zn,8497const ZRegister& zm) {8498// SQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8499// 0100 0100 ..00 1000 100. .... .... ....8500// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |8501// Zdn<4:0>85028503USE(zn);8504VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8505VIXL_ASSERT(zd.Is(zn));8506VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));85078508Emit(0x44088000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8509}85108511void Assembler::sqshlr(const ZRegister& zd,8512const PRegisterM& pg,8513const ZRegister& zn,8514const ZRegister& zm) {8515// SQSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8516// 0100 0100 ..00 1100 100. .... .... ....8517// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |8518// Zdn<4:0>85198520USE(zn);8521VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8522VIXL_ASSERT(zd.Is(zn));8523VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));85248525Emit(0x440c8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8526}85278528void Assembler::sqshlu(const ZRegister& zd,8529const PRegisterM& pg,8530const ZRegister& zn,8531int shift) {8532// SQSHLU <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>8533// 0000 0100 ..00 1111 100. .... .... ....8534// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |8535// imm3<7:5> | Zdn<4:0>85368537USE(zn);8538VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8539VIXL_ASSERT(zd.Is(zn));85408541Instr encoded_imm =8542EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());8543SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x040f8000);8544}85458546void Assembler::sqsub(const ZRegister& zd,8547const PRegisterM& pg,8548const ZRegister& zn,8549const ZRegister& zm) {8550// SQSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8551// 0100 0100 ..01 1010 100. .... .... ....8552// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>85538554USE(zn);8555VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8556VIXL_ASSERT(zd.Is(zn));8557VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));85588559Emit(0x441a8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8560}85618562void Assembler::sqsubr(const ZRegister& zd,8563const PRegisterM& pg,8564const ZRegister& zn,8565const ZRegister& zm) {8566// SQSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8567// 0100 0100 ..01 1110 100. .... .... ....8568// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>85698570USE(zn);8571VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8572VIXL_ASSERT(zd.Is(zn));8573VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));85748575Emit(0x441e8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8576}85778578void Assembler::sqxtnb(const ZRegister& zd, const ZRegister& zn) {8579// SQXTNB <Zd>.<T>, <Zn>.<Tb>8580// 0100 0101 0.1. .000 0100 00.. .... ....8581// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>85828583VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8584VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());8585VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));85868587// XTN instructions look like immediate shifts with zero shift distance.8588Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());8589SVEBitwiseShiftImmediate(zd, zn, size, 0x45204000);8590}85918592void Assembler::sqxtnt(const ZRegister& zd, const ZRegister& zn) {8593// SQXTNT <Zd>.<T>, <Zn>.<Tb>8594// 0100 0101 0.1. .000 0100 01.. .... ....8595// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>85968597VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8598VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());8599VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));86008601// XTN instructions look like immediate shifts with zero shift distance.8602Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());8603SVEBitwiseShiftImmediate(zd, zn, size, 0x45204400);8604}86058606void Assembler::sqxtunb(const ZRegister& zd, const ZRegister& zn) {8607// SQXTUNB <Zd>.<T>, <Zn>.<Tb>8608// 0100 0101 0.1. .000 0101 00.. .... ....8609// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>86108611VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8612VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());8613VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));86148615// XTN instructions look like immediate shifts with zero shift distance.8616Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());8617SVEBitwiseShiftImmediate(zd, zn, size, 0x45205000);8618}86198620void Assembler::sqxtunt(const ZRegister& zd, const ZRegister& zn) {8621// SQXTUNT <Zd>.<T>, <Zn>.<Tb>8622// 0100 0101 0.1. .000 0101 01.. .... ....8623// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>86248625VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8626VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());8627VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));86288629// XTN instructions look like immediate shifts with zero shift distance.8630Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());8631SVEBitwiseShiftImmediate(zd, zn, size, 0x45205400);8632}86338634void Assembler::srhadd(const ZRegister& zd,8635const PRegisterM& pg,8636const ZRegister& zn,8637const ZRegister& zm) {8638// SRHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8639// 0100 0100 ..01 0100 100. .... .... ....8640// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>86418642USE(zn);8643VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8644VIXL_ASSERT(zd.Is(zn));8645VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));86468647Emit(0x44148000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8648}86498650void Assembler::sri(const ZRegister& zd, const ZRegister& zn, int shift) {8651// SRI <Zd>.<T>, <Zn>.<T>, #<const>8652// 0100 0101 ..0. .... 1111 00.. .... ....8653// tszh<23:22> | tszl<20:19> | imm3<18:16> | op<10> | Zn<9:5> | Zd<4:0>86548655VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8656VIXL_ASSERT(AreSameLaneSize(zd, zn));8657Instr encoded_imm =8658EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());86598660SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500f000);8661}86628663void Assembler::srshl(const ZRegister& zd,8664const PRegisterM& pg,8665const ZRegister& zn,8666const ZRegister& zm) {8667// SRSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8668// 0100 0100 ..00 0010 100. .... .... ....8669// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |8670// Zdn<4:0>86718672USE(zn);8673VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8674VIXL_ASSERT(zd.Is(zn));8675VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));86768677Emit(0x44028000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8678}86798680void Assembler::srshlr(const ZRegister& zd,8681const PRegisterM& pg,8682const ZRegister& zn,8683const ZRegister& zm) {8684// SRSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8685// 0100 0100 ..00 0110 100. .... .... ....8686// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |8687// Zdn<4:0>86888689USE(zn);8690VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8691VIXL_ASSERT(zd.Is(zn));8692VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));86938694Emit(0x44068000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8695}86968697void Assembler::srshr(const ZRegister& zd,8698const PRegisterM& pg,8699const ZRegister& zn,8700int shift) {8701// SRSHR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>8702// 0000 0100 ..00 1100 100. .... .... ....8703// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |8704// imm3<7:5> | Zdn<4:0>87058706USE(zn);8707VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8708VIXL_ASSERT(zd.Is(zn));8709Instr encoded_imm =8710EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());8711SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x040c8000);8712}87138714void Assembler::srsra(const ZRegister& zda, const ZRegister& zn, int shift) {8715// SRSRA <Zda>.<T>, <Zn>.<T>, #<const>8716// 0100 0101 ..0. .... 1110 10.. .... ....8717// tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |8718// Zda<4:0>87198720VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8721VIXL_ASSERT(AreSameLaneSize(zda, zn));8722Instr encoded_imm =8723EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());87248725SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500e800);8726}87278728void Assembler::sshllb(const ZRegister& zd, const ZRegister& zn, int shift) {8729// SSHLLB <Zd>.<T>, <Zn>.<Tb>, #<const>8730// 0100 0101 0.0. .... 1010 00.. .... ....8731// tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>87328733VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8734VIXL_ASSERT(!zd.IsLaneSizeB());8735VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));87368737Instr encoded_imm =8738EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());8739SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500a000);8740}87418742void Assembler::sshllt(const ZRegister& zd, const ZRegister& zn, int shift) {8743// SSHLLT <Zd>.<T>, <Zn>.<Tb>, #<const>8744// 0100 0101 0.0. .... 1010 01.. .... ....8745// tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>87468747VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8748VIXL_ASSERT(!zd.IsLaneSizeB());8749VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));87508751Instr encoded_imm =8752EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());8753SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500a400);8754}87558756void Assembler::ssra(const ZRegister& zda, const ZRegister& zn, int shift) {8757// SSRA <Zda>.<T>, <Zn>.<T>, #<const>8758// 0100 0101 ..0. .... 1110 00.. .... ....8759// tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |8760// Zda<4:0>87618762VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8763VIXL_ASSERT(AreSameLaneSize(zda, zn));8764Instr encoded_imm =8765EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());87668767SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500e000);8768}87698770void Assembler::ssublb(const ZRegister& zd,8771const ZRegister& zn,8772const ZRegister& zm) {8773// SSUBLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8774// 0100 0101 ..0. .... 0001 00.. .... ....8775// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |8776// Zd<4:0>87778778VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8779VIXL_ASSERT(AreSameLaneSize(zn, zm));8780VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8781VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);87828783Emit(0x45001000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8784}87858786void Assembler::ssublbt(const ZRegister& zd,8787const ZRegister& zn,8788const ZRegister& zm) {8789// SSUBLBT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8790// 0100 0101 ..0. .... 1000 10.. .... ....8791// size<23:22> | Zm<20:16> | S<11> | tb<10> | Zn<9:5> | Zd<4:0>87928793VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8794VIXL_ASSERT(AreSameLaneSize(zn, zm));8795VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8796VIXL_ASSERT(zd.IsLaneSizeD() || zd.IsLaneSizeH() || zd.IsLaneSizeS());87978798Emit(0x45008800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8799}88008801void Assembler::ssublt(const ZRegister& zd,8802const ZRegister& zn,8803const ZRegister& zm) {8804// SSUBLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8805// 0100 0101 ..0. .... 0001 01.. .... ....8806// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |8807// Zd<4:0>88088809VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8810VIXL_ASSERT(AreSameLaneSize(zn, zm));8811VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8812VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);88138814Emit(0x45001400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8815}88168817void Assembler::ssubltb(const ZRegister& zd,8818const ZRegister& zn,8819const ZRegister& zm) {8820// SSUBLTB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8821// 0100 0101 ..0. .... 1000 11.. .... ....8822// size<23:22> | Zm<20:16> | S<11> | tb<10> | Zn<9:5> | Zd<4:0>88238824VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8825VIXL_ASSERT(AreSameLaneSize(zn, zm));8826VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));8827VIXL_ASSERT(zd.IsLaneSizeD() || zd.IsLaneSizeH() || zd.IsLaneSizeS());88288829Emit(0x45008c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8830}88318832void Assembler::ssubwb(const ZRegister& zd,8833const ZRegister& zn,8834const ZRegister& zm) {8835// SSUBWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>8836// 0100 0101 ..0. .... 0101 00.. .... ....8837// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>88388839VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8840VIXL_ASSERT(AreSameLaneSize(zd, zn));8841VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));8842VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);88438844Emit(0x45005000 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8845}88468847void Assembler::ssubwt(const ZRegister& zd,8848const ZRegister& zn,8849const ZRegister& zm) {8850// SSUBWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>8851// 0100 0101 ..0. .... 0101 01.. .... ....8852// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>88538854VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8855VIXL_ASSERT(AreSameLaneSize(zd, zn));8856VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));8857VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);88588859Emit(0x45005400 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8860}88618862#if 08863// This prototype maps to 2 instruction encodings:8864// stnt1b_z_p_ar_d_64_unscaled8865// stnt1b_z_p_ar_s_x32_unscaled8866void Assembler::stnt1b(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {8867// STNT1B { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]8868// 1110 0100 000. .... 001. .... .... ....8869// msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>88708871VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));88728873Emit(0xe4002000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));8874}88758876void Assembler::stnt1d(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {8877// STNT1D { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]8878// 1110 0101 100. .... 001. .... .... ....8879// msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>88808881VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));88828883Emit(0xe5802000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));8884}88858886// This prototype maps to 2 instruction encodings:8887// stnt1h_z_p_ar_d_64_unscaled8888// stnt1h_z_p_ar_s_x32_unscaled8889void Assembler::stnt1h(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {8890// STNT1H { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]8891// 1110 0100 100. .... 001. .... .... ....8892// msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>88938894VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));88958896Emit(0xe4802000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));8897}88988899// This prototype maps to 2 instruction encodings:8900// stnt1w_z_p_ar_d_64_unscaled8901// stnt1w_z_p_ar_s_x32_unscaled8902void Assembler::stnt1w(const ZRegister& zt, const PRegister& pg, const ZRegister& zn, const Register& rm) {8903// STNT1W { <Zt>.D }, <Pg>, [<Zn>.D{, <Xm>}]8904// 1110 0101 000. .... 001. .... .... ....8905// msz<24:23> | Rm<20:16> | Pg<12:10> | Zn<9:5> | Zt<4:0>89068907VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));89088909Emit(0xe5002000 | Rt(zt) | PgLow8(pg) | Rn(zn) | Rm(rm));8910}8911#endif89128913void Assembler::subhnb(const ZRegister& zd,8914const ZRegister& zn,8915const ZRegister& zm) {8916// SUBHNB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8917// 0100 0101 ..1. .... 0111 00.. .... ....8918// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>89198920VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8921VIXL_ASSERT(AreSameLaneSize(zn, zm));8922VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));8923VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);89248925Emit(0x45207000 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));8926}89278928void Assembler::subhnt(const ZRegister& zd,8929const ZRegister& zn,8930const ZRegister& zm) {8931// SUBHNT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>8932// 0100 0101 ..1. .... 0111 01.. .... ....8933// size<23:22> | Zm<20:16> | S<12> | R<11> | T<10> | Zn<9:5> | Zd<4:0>89348935VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8936VIXL_ASSERT(AreSameLaneSize(zn, zm));8937VIXL_ASSERT(zn.GetLaneSizeInBytes() == (zd.GetLaneSizeInBytes() * 2));8938VIXL_ASSERT(zn.GetLaneSizeInBytes() != kBRegSizeInBytes);89398940Emit(0x45207400 | SVESize(zn) | Rd(zd) | Rn(zn) | Rm(zm));8941}89428943void Assembler::suqadd(const ZRegister& zd,8944const PRegisterM& pg,8945const ZRegister& zn,8946const ZRegister& zm) {8947// SUQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>8948// 0100 0100 ..01 1100 100. .... .... ....8949// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>89508951USE(zn);8952VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8953VIXL_ASSERT(zd.Is(zn));8954VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));89558956Emit(0x441c8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));8957}89588959void Assembler::tbl(const ZRegister& zd,8960const ZRegister& zn1,8961const ZRegister& zn2,8962const ZRegister& zm) {8963// TBL <Zd>.<T>, { <Zn1>.<T>, <Zn2>.<T> }, <Zm>.<T>8964// 0000 0101 ..1. .... 0010 10.. .... ....8965// size<23:22> | Zm<20:16> | op<10> | Zn<9:5> | Zd<4:0>89668967USE(zn2);8968VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8969VIXL_ASSERT(AreConsecutive(zn1, zn2));8970VIXL_ASSERT(AreSameLaneSize(zd, zn1, zn2, zm));89718972Emit(0x05202800 | SVESize(zd) | Rd(zd) | Rn(zn1) | Rn(zn2) | Rm(zm));8973}89748975void Assembler::tbx(const ZRegister& zd,8976const ZRegister& zn,8977const ZRegister& zm) {8978// TBX <Zd>.<T>, <Zn>.<T>, <Zm>.<T>8979// 0000 0101 ..1. .... 0010 11.. .... ....8980// size<23:22> | Zm<20:16> | op<10> | Zn<9:5> | Zd<4:0>89818982VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8983VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));89848985Emit(0x05202c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));8986}89878988void Assembler::uaba(const ZRegister& zda,8989const ZRegister& zn,8990const ZRegister& zm) {8991// UABA <Zda>.<T>, <Zn>.<T>, <Zm>.<T>8992// 0100 0101 ..0. .... 1111 11.. .... ....8993// size<23:22> | Zm<20:16> | U<10> | Zn<9:5> | Zda<4:0>89948995VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));8996VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));89978998Emit(0x4500fc00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));8999}90009001void Assembler::uabalb(const ZRegister& zda,9002const ZRegister& zn,9003const ZRegister& zm) {9004// UABALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9005// 0100 0101 ..0. .... 1100 10.. .... ....9006// size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>90079008VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9009VIXL_ASSERT(AreSameLaneSize(zn, zm));9010VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));9011VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);90129013Emit(0x4500c800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));9014}90159016void Assembler::uabalt(const ZRegister& zda,9017const ZRegister& zn,9018const ZRegister& zm) {9019// UABALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9020// 0100 0101 ..0. .... 1100 11.. .... ....9021// size<23:22> | Zm<20:16> | U<11> | T<10> | Zn<9:5> | Zda<4:0>90229023VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9024VIXL_ASSERT(AreSameLaneSize(zn, zm));9025VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));9026VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);90279028Emit(0x4500cc00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));9029}90309031void Assembler::uabdlb(const ZRegister& zd,9032const ZRegister& zn,9033const ZRegister& zm) {9034// UABDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9035// 0100 0101 ..0. .... 0011 10.. .... ....9036// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |9037// Zd<4:0>90389039VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9040VIXL_ASSERT(AreSameLaneSize(zn, zm));9041VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));9042VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);90439044Emit(0x45003800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9045}90469047void Assembler::uabdlt(const ZRegister& zd,9048const ZRegister& zn,9049const ZRegister& zm) {9050// UABDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9051// 0100 0101 ..0. .... 0011 11.. .... ....9052// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |9053// Zd<4:0>90549055VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9056VIXL_ASSERT(AreSameLaneSize(zn, zm));9057VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));9058VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);90599060Emit(0x45003c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9061}90629063void Assembler::uadalp(const ZRegister& zda,9064const PRegisterM& pg,9065const ZRegister& zn) {9066// UADALP <Zda>.<T>, <Pg>/M, <Zn>.<Tb>9067// 0100 0100 ..00 0101 101. .... .... ....9068// size<23:22> | U<16> | Pg<12:10> | Zn<9:5> | Zda<4:0>90699070VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9071VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));9072VIXL_ASSERT(zda.GetLaneSizeInBytes() != kBRegSizeInBytes);90739074Emit(0x4405a000 | SVESize(zda) | Rd(zda) | PgLow8(pg) | Rn(zn));9075}90769077void Assembler::uaddlb(const ZRegister& zd,9078const ZRegister& zn,9079const ZRegister& zm) {9080// UADDLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9081// 0100 0101 ..0. .... 0000 10.. .... ....9082// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |9083// Zd<4:0>90849085VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9086VIXL_ASSERT(AreSameLaneSize(zn, zm));9087VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));9088VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);90899090Emit(0x45000800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9091}90929093void Assembler::uaddlt(const ZRegister& zd,9094const ZRegister& zn,9095const ZRegister& zm) {9096// UADDLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9097// 0100 0101 ..0. .... 0000 11.. .... ....9098// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |9099// Zd<4:0>91009101VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9102VIXL_ASSERT(AreSameLaneSize(zn, zm));9103VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));9104VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);91059106Emit(0x45000c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9107}91089109void Assembler::uaddwb(const ZRegister& zd,9110const ZRegister& zn,9111const ZRegister& zm) {9112// UADDWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>9113// 0100 0101 ..0. .... 0100 10.. .... ....9114// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>91159116VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9117VIXL_ASSERT(AreSameLaneSize(zd, zn));9118VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));9119VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);91209121Emit(0x45004800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9122}91239124void Assembler::uaddwt(const ZRegister& zd,9125const ZRegister& zn,9126const ZRegister& zm) {9127// UADDWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>9128// 0100 0101 ..0. .... 0100 11.. .... ....9129// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>91309131VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9132VIXL_ASSERT(AreSameLaneSize(zd, zn));9133VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));9134VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);91359136Emit(0x45004c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9137}91389139void Assembler::uhadd(const ZRegister& zd,9140const PRegisterM& pg,9141const ZRegister& zn,9142const ZRegister& zm) {9143// UHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9144// 0100 0100 ..01 0001 100. .... .... ....9145// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>91469147USE(zn);9148VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9149VIXL_ASSERT(zd.Is(zn));9150VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));91519152Emit(0x44118000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9153}91549155void Assembler::uhsub(const ZRegister& zd,9156const PRegisterM& pg,9157const ZRegister& zn,9158const ZRegister& zm) {9159// UHSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9160// 0100 0100 ..01 0011 100. .... .... ....9161// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>91629163USE(zn);9164VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9165VIXL_ASSERT(zd.Is(zn));9166VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));91679168Emit(0x44138000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9169}91709171void Assembler::uhsubr(const ZRegister& zd,9172const PRegisterM& pg,9173const ZRegister& zn,9174const ZRegister& zm) {9175// UHSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9176// 0100 0100 ..01 0111 100. .... .... ....9177// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>91789179USE(zn);9180VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9181VIXL_ASSERT(zd.Is(zn));9182VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));91839184Emit(0x44178000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9185}91869187void Assembler::umaxp(const ZRegister& zd,9188const PRegisterM& pg,9189const ZRegister& zn,9190const ZRegister& zm) {9191// UMAXP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9192// 0100 0100 ..01 0101 101. .... .... ....9193// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>91949195USE(zn);9196VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9197VIXL_ASSERT(zd.Is(zn));9198VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));91999200Emit(0x4415a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9201}92029203void Assembler::uminp(const ZRegister& zd,9204const PRegisterM& pg,9205const ZRegister& zn,9206const ZRegister& zm) {9207// UMINP <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9208// 0100 0100 ..01 0111 101. .... .... ....9209// size<23:22> | opc<18:17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>92109211USE(zn);9212VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9213VIXL_ASSERT(zd.Is(zn));9214VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));92159216Emit(0x4417a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9217}92189219void Assembler::umlalb(const ZRegister& zda,9220const ZRegister& zn,9221const ZRegister& zm) {9222// UMLALB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9223// 0100 0100 ..0. .... 0100 10.. .... ....9224// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>92259226VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9227VIXL_ASSERT(!zda.IsLaneSizeB());9228VIXL_ASSERT(AreSameLaneSize(zn, zm));9229VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));92309231Emit(0x44004800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));9232}92339234void Assembler::umlalt(const ZRegister& zda,9235const ZRegister& zn,9236const ZRegister& zm) {9237// UMLALT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9238// 0100 0100 ..0. .... 0100 11.. .... ....9239// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>92409241VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9242VIXL_ASSERT(!zda.IsLaneSizeB());9243VIXL_ASSERT(AreSameLaneSize(zn, zm));9244VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));92459246Emit(0x44004c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));9247}92489249void Assembler::umlslb(const ZRegister& zda,9250const ZRegister& zn,9251const ZRegister& zm) {9252// UMLSLB <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9253// 0100 0100 ..0. .... 0101 10.. .... ....9254// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>92559256VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9257VIXL_ASSERT(!zda.IsLaneSizeB());9258VIXL_ASSERT(AreSameLaneSize(zn, zm));9259VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));92609261Emit(0x44005800 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));9262}92639264void Assembler::umlslt(const ZRegister& zda,9265const ZRegister& zn,9266const ZRegister& zm) {9267// UMLSLT <Zda>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9268// 0100 0100 ..0. .... 0101 11.. .... ....9269// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zda<4:0>92709271VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9272VIXL_ASSERT(!zda.IsLaneSizeB());9273VIXL_ASSERT(AreSameLaneSize(zn, zm));9274VIXL_ASSERT(zda.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));92759276Emit(0x44005c00 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));9277}92789279void Assembler::umulh(const ZRegister& zd,9280const ZRegister& zn,9281const ZRegister& zm) {9282// UMULH <Zd>.<T>, <Zn>.<T>, <Zm>.<T>9283// 0000 0100 ..1. .... 0110 11.. .... ....9284// size<23:22> | Zm<20:16> | opc<11:10> | Zn<9:5> | Zd<4:0>92859286VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9287VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));92889289Emit(0x04206c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9290}92919292void Assembler::umullb(const ZRegister& zd,9293const ZRegister& zn,9294const ZRegister& zm) {9295// UMULLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9296// 0100 0101 ..0. .... 0111 10.. .... ....9297// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>92989299VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9300VIXL_ASSERT(AreSameLaneSize(zn, zm));9301VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());9302VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);93039304Emit(0x45007800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9305}93069307void Assembler::umullt(const ZRegister& zd,9308const ZRegister& zn,9309const ZRegister& zm) {9310// UMULLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9311// 0100 0101 ..0. .... 0111 11.. .... ....9312// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>93139314VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9315VIXL_ASSERT(AreSameLaneSize(zn, zm));9316VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeQ());9317VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);93189319Emit(0x45007c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9320}93219322void Assembler::uqadd(const ZRegister& zd,9323const PRegisterM& pg,9324const ZRegister& zn,9325const ZRegister& zm) {9326// UQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9327// 0100 0100 ..01 1001 100. .... .... ....9328// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>93299330USE(zn);9331VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9332VIXL_ASSERT(zd.Is(zn));9333VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));93349335Emit(0x44198000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9336}93379338void Assembler::uqrshl(const ZRegister& zd,9339const PRegisterM& pg,9340const ZRegister& zn,9341const ZRegister& zm) {9342// UQRSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9343// 0100 0100 ..00 1011 100. .... .... ....9344// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |9345// Zdn<4:0>93469347USE(zn);9348VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9349VIXL_ASSERT(zd.Is(zn));9350VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));93519352Emit(0x440b8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9353}93549355void Assembler::uqrshlr(const ZRegister& zd,9356const PRegisterM& pg,9357const ZRegister& zn,9358const ZRegister& zm) {9359// UQRSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9360// 0100 0100 ..00 1111 100. .... .... ....9361// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |9362// Zdn<4:0>93639364USE(zn);9365VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9366VIXL_ASSERT(zd.Is(zn));9367VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));93689369Emit(0x440f8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9370}93719372void Assembler::uqshl(const ZRegister& zd,9373const PRegisterM& pg,9374const ZRegister& zn,9375int shift) {9376// UQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>9377// 0000 0100 ..00 0111 100. .... .... ....9378// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |9379// imm3<7:5> | Zdn<4:0>93809381USE(zn);9382VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9383VIXL_ASSERT(zd.Is(zn));9384Instr encoded_imm =9385EncodeSVEShiftLeftImmediate(shift, zd.GetLaneSizeInBits());9386SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x04078000);9387}93889389void Assembler::uqshl(const ZRegister& zd,9390const PRegisterM& pg,9391const ZRegister& zn,9392const ZRegister& zm) {9393// UQSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9394// 0100 0100 ..00 1001 100. .... .... ....9395// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |9396// Zdn<4:0>93979398USE(zn);9399VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9400VIXL_ASSERT(zd.Is(zn));9401VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));94029403Emit(0x44098000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9404}94059406void Assembler::uqshlr(const ZRegister& zd,9407const PRegisterM& pg,9408const ZRegister& zn,9409const ZRegister& zm) {9410// UQSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9411// 0100 0100 ..00 1101 100. .... .... ....9412// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |9413// Zdn<4:0>94149415USE(zn);9416VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9417VIXL_ASSERT(zd.Is(zn));9418VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));94199420Emit(0x440d8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9421}94229423void Assembler::uqsub(const ZRegister& zd,9424const PRegisterM& pg,9425const ZRegister& zn,9426const ZRegister& zm) {9427// UQSUB <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9428// 0100 0100 ..01 1011 100. .... .... ....9429// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>94309431USE(zn);9432VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9433VIXL_ASSERT(zd.Is(zn));9434VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));94359436Emit(0x441b8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9437}94389439void Assembler::uqsubr(const ZRegister& zd,9440const PRegisterM& pg,9441const ZRegister& zn,9442const ZRegister& zm) {9443// UQSUBR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9444// 0100 0100 ..01 1111 100. .... .... ....9445// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>94469447USE(zn);9448VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9449VIXL_ASSERT(zd.Is(zn));9450VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));94519452Emit(0x441f8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9453}94549455void Assembler::uqxtnb(const ZRegister& zd, const ZRegister& zn) {9456// UQXTNB <Zd>.<T>, <Zn>.<Tb>9457// 0100 0101 0.1. .000 0100 10.. .... ....9458// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>94599460VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9461VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());9462VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));94639464// XTN instructions look like immediate shifts with zero shift distance.9465Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());9466SVEBitwiseShiftImmediate(zd, zn, size, 0x45204800);9467}94689469void Assembler::uqxtnt(const ZRegister& zd, const ZRegister& zn) {9470// UQXTNT <Zd>.<T>, <Zn>.<Tb>9471// 0100 0101 0.1. .000 0100 11.. .... ....9472// tszh<22> | tszl<20:19> | opc<12:11> | T<10> | Zn<9:5> | Zd<4:0>94739474VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9475VIXL_ASSERT(zd.IsLaneSizeS() || zd.IsLaneSizeH() || zd.IsLaneSizeB());9476VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() / 2));94779478// XTN instructions look like immediate shifts with zero shift distance.9479Instr size = EncodeSVEShiftLeftImmediate(0, zd.GetLaneSizeInBits());9480SVEBitwiseShiftImmediate(zd, zn, size, 0x45204c00);9481}94829483void Assembler::urecpe(const ZRegister& zd,9484const PRegisterM& pg,9485const ZRegister& zn) {9486// URECPE <Zd>.S, <Pg>/M, <Zn>.S9487// 0100 0100 ..00 0000 101. .... .... ....9488// size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>94899490VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9491VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeS());94929493Emit(0x4400a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));9494}94959496void Assembler::urhadd(const ZRegister& zd,9497const PRegisterM& pg,9498const ZRegister& zn,9499const ZRegister& zm) {9500// URHADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9501// 0100 0100 ..01 0101 100. .... .... ....9502// size<23:22> | R<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>95039504USE(zn);9505VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9506VIXL_ASSERT(zd.Is(zn));9507VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));95089509Emit(0x44158000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9510}95119512void Assembler::urshl(const ZRegister& zd,9513const PRegisterM& pg,9514const ZRegister& zn,9515const ZRegister& zm) {9516// URSHL <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9517// 0100 0100 ..00 0011 100. .... .... ....9518// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |9519// Zdn<4:0>95209521USE(zn);9522VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9523VIXL_ASSERT(zd.Is(zn));9524VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));95259526Emit(0x44038000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9527}95289529void Assembler::urshlr(const ZRegister& zd,9530const PRegisterM& pg,9531const ZRegister& zn,9532const ZRegister& zm) {9533// URSHLR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9534// 0100 0100 ..00 0111 100. .... .... ....9535// size<23:22> | Q<19> | R<18> | N<17> | U<16> | Pg<12:10> | Zm<9:5> |9536// Zdn<4:0>95379538USE(zn);9539VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9540VIXL_ASSERT(zd.Is(zn));9541VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));95429543Emit(0x44078000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9544}95459546void Assembler::urshr(const ZRegister& zd,9547const PRegisterM& pg,9548const ZRegister& zn,9549int shift) {9550// URSHR <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, #<const>9551// 0000 0100 ..00 1101 100. .... .... ....9552// tszh<23:22> | opc<19:18> | L<17> | U<16> | Pg<12:10> | tszl<9:8> |9553// imm3<7:5> | Zdn<4:0>95549555USE(zn);9556VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9557VIXL_ASSERT(zd.Is(zn));9558Instr encoded_imm =9559EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());9560SVEBitwiseShiftImmediatePred(zd, pg, encoded_imm, 0x040d8000);9561}95629563void Assembler::ursqrte(const ZRegister& zd,9564const PRegisterM& pg,9565const ZRegister& zn) {9566// URSQRTE <Zd>.S, <Pg>/M, <Zn>.S9567// 0100 0100 ..00 0001 101. .... .... ....9568// size<23:22> | Q<19> | opc<17:16> | Pg<12:10> | Zn<9:5> | Zd<4:0>95699570VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9571VIXL_ASSERT(zd.IsLaneSizeS() && zn.IsLaneSizeS());95729573Emit(0x4401a000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zn));9574}95759576void Assembler::ursra(const ZRegister& zda, const ZRegister& zn, int shift) {9577// URSRA <Zda>.<T>, <Zn>.<T>, #<const>9578// 0100 0101 ..0. .... 1110 11.. .... ....9579// tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |9580// Zda<4:0>95819582VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9583VIXL_ASSERT(AreSameLaneSize(zda, zn));9584Instr encoded_imm =9585EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());95869587SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500ec00);9588}95899590void Assembler::ushllb(const ZRegister& zd, const ZRegister& zn, int shift) {9591// USHLLB <Zd>.<T>, <Zn>.<Tb>, #<const>9592// 0100 0101 0.0. .... 1010 10.. .... ....9593// tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>95949595VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9596VIXL_ASSERT(!zd.IsLaneSizeB());9597VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));95989599Instr encoded_imm =9600EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());9601SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500a800);9602}96039604void Assembler::ushllt(const ZRegister& zd, const ZRegister& zn, int shift) {9605// USHLLT <Zd>.<T>, <Zn>.<Tb>, #<const>9606// 0100 0101 0.0. .... 1010 11.. .... ....9607// tszh<22> | tszl<20:19> | imm3<18:16> | U<11> | T<10> | Zn<9:5> | Zd<4:0>96089609VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9610VIXL_ASSERT(!zd.IsLaneSizeB());9611VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));96129613Instr encoded_imm =9614EncodeSVEShiftLeftImmediate(shift, zn.GetLaneSizeInBits());9615SVEBitwiseShiftImmediate(zd, zn, encoded_imm, 0x4500ac00);9616}96179618void Assembler::usqadd(const ZRegister& zd,9619const PRegisterM& pg,9620const ZRegister& zn,9621const ZRegister& zm) {9622// USQADD <Zdn>.<T>, <Pg>/M, <Zdn>.<T>, <Zm>.<T>9623// 0100 0100 ..01 1101 100. .... .... ....9624// size<23:22> | op<18> | S<17> | U<16> | Pg<12:10> | Zm<9:5> | Zdn<4:0>96259626USE(zn);9627VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9628VIXL_ASSERT(zd.Is(zn));9629VIXL_ASSERT(AreSameLaneSize(zd, zn, zm));96309631Emit(0x441d8000 | SVESize(zd) | Rd(zd) | PgLow8(pg) | Rn(zm));9632}96339634void Assembler::usra(const ZRegister& zda, const ZRegister& zn, int shift) {9635// USRA <Zda>.<T>, <Zn>.<T>, #<const>9636// 0100 0101 ..0. .... 1110 01.. .... ....9637// tszh<23:22> | tszl<20:19> | imm3<18:16> | R<11> | U<10> | Zn<9:5> |9638// Zda<4:0>96399640VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9641VIXL_ASSERT(AreSameLaneSize(zda, zn));9642Instr encoded_imm =9643EncodeSVEShiftRightImmediate(shift, zda.GetLaneSizeInBits());96449645SVEBitwiseShiftImmediate(zda, zn, encoded_imm, 0x4500e400);9646}96479648void Assembler::usublb(const ZRegister& zd,9649const ZRegister& zn,9650const ZRegister& zm) {9651// USUBLB <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9652// 0100 0101 ..0. .... 0001 10.. .... ....9653// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |9654// Zd<4:0>96559656VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9657VIXL_ASSERT(AreSameLaneSize(zn, zm));9658VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));9659VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);96609661Emit(0x45001800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9662}96639664void Assembler::usublt(const ZRegister& zd,9665const ZRegister& zn,9666const ZRegister& zm) {9667// USUBLT <Zd>.<T>, <Zn>.<Tb>, <Zm>.<Tb>9668// 0100 0101 ..0. .... 0001 11.. .... ....9669// size<23:22> | Zm<20:16> | op<13> | S<12> | U<11> | T<10> | Zn<9:5> |9670// Zd<4:0>96719672VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9673VIXL_ASSERT(AreSameLaneSize(zn, zm));9674VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zn.GetLaneSizeInBytes() * 2));9675VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);96769677Emit(0x45001c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9678}96799680void Assembler::usubwb(const ZRegister& zd,9681const ZRegister& zn,9682const ZRegister& zm) {9683// USUBWB <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>9684// 0100 0101 ..0. .... 0101 10.. .... ....9685// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>96869687VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9688VIXL_ASSERT(AreSameLaneSize(zd, zn));9689VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));9690VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);96919692Emit(0x45005800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9693}96949695void Assembler::usubwt(const ZRegister& zd,9696const ZRegister& zn,9697const ZRegister& zm) {9698// USUBWT <Zd>.<T>, <Zn>.<T>, <Zm>.<Tb>9699// 0100 0101 ..0. .... 0101 11.. .... ....9700// size<23:22> | Zm<20:16> | S<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>97019702VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9703VIXL_ASSERT(AreSameLaneSize(zd, zn));9704VIXL_ASSERT(zd.GetLaneSizeInBytes() == (zm.GetLaneSizeInBytes() * 2));9705VIXL_ASSERT(zd.GetLaneSizeInBytes() != kBRegSizeInBytes);97069707Emit(0x45005c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));9708}97099710void Assembler::whilege(const PRegisterWithLaneSize& pd,9711const Register& rn,9712const Register& rm) {9713// WHILEGE <Pd>.<T>, <R><n>, <R><m>9714// 0010 0101 ..1. .... 000. 00.. ...0 ....9715// size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |9716// Pd<3:0>97179718VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9719VIXL_ASSERT(AreSameSizeAndType(rn, rm));9720const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;97219722Emit(0x25200000 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));9723}97249725void Assembler::whilegt(const PRegisterWithLaneSize& pd,9726const Register& rn,9727const Register& rm) {9728// WHILEGT <Pd>.<T>, <R><n>, <R><m>9729// 0010 0101 ..1. .... 000. 00.. ...1 ....9730// size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |9731// Pd<3:0>97329733VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9734VIXL_ASSERT(AreSameSizeAndType(rn, rm));9735const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;97369737Emit(0x25200010 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));9738}97399740void Assembler::whilehi(const PRegisterWithLaneSize& pd,9741const Register& rn,9742const Register& rm) {9743// WHILEHI <Pd>.<T>, <R><n>, <R><m>9744// 0010 0101 ..1. .... 000. 10.. ...1 ....9745// size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |9746// Pd<3:0>97479748VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9749VIXL_ASSERT(AreSameSizeAndType(rn, rm));9750const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;97519752Emit(0x25200810 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));9753}97549755void Assembler::whilehs(const PRegisterWithLaneSize& pd,9756const Register& rn,9757const Register& rm) {9758// WHILEHS <Pd>.<T>, <R><n>, <R><m>9759// 0010 0101 ..1. .... 000. 10.. ...0 ....9760// size<23:22> | Rm<20:16> | sf<12> | U<11> | lt<10> | Rn<9:5> | eq<4> |9761// Pd<3:0>97629763VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9764VIXL_ASSERT(AreSameSizeAndType(rn, rm));9765const Instr sf = rn.Is64Bits() ? 0x00001000 : 0x00000000;97669767Emit(0x25200800 | SVESize(pd) | sf | Pd(pd) | Rn(rn) | Rm(rm));9768}97699770void Assembler::whilerw(const PRegisterWithLaneSize& pd,9771const Register& rn,9772const Register& rm) {9773// WHILERW <Pd>.<T>, <Xn>, <Xm>9774// 0010 0101 ..1. .... 0011 00.. ...1 ....9775// size<23:22> | Rm<20:16> | Rn<9:5> | rw<4> | Pd<3:0>97769777VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9778VIXL_ASSERT(rn.IsX() && rm.IsX());97799780Emit(0x25203010 | SVESize(pd) | Pd(pd) | Rn(rn) | Rm(rm));9781}97829783void Assembler::whilewr(const PRegisterWithLaneSize& pd,9784const Register& rn,9785const Register& rm) {9786// WHILEWR <Pd>.<T>, <Xn>, <Xm>9787// 0010 0101 ..1. .... 0011 00.. ...0 ....9788// size<23:22> | Rm<20:16> | Rn<9:5> | rw<4> | Pd<3:0>97899790VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9791VIXL_ASSERT(rn.IsX() && rm.IsX());97929793Emit(0x25203000 | SVESize(pd) | Pd(pd) | Rn(rn) | Rm(rm));9794}97959796void Assembler::xar(const ZRegister& zd,9797const ZRegister& zn,9798const ZRegister& zm,9799int shift) {9800// XAR <Zdn>.<T>, <Zdn>.<T>, <Zm>.<T>, #<const>9801// 0000 0100 ..1. .... 0011 01.. .... ....9802// tszh<23:22> | tszl<20:19> | imm3<18:16> | Zm<9:5> | Zdn<4:0>98039804USE(zn);9805VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));9806VIXL_ASSERT(zd.Is(zn));9807VIXL_ASSERT(AreSameLaneSize(zd, zm));98089809Instr encoded_imm =9810EncodeSVEShiftRightImmediate(shift, zd.GetLaneSizeInBits());9811SVEBitwiseShiftImmediate(zd, zm, encoded_imm, 0x04203400);9812}98139814void Assembler::fmmla(const ZRegister& zda,9815const ZRegister& zn,9816const ZRegister& zm) {9817VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));9818VIXL_ASSERT((CPUHas(CPUFeatures::kSVEF32MM) && zda.IsLaneSizeS()) ||9819(CPUHas(CPUFeatures::kSVEF64MM) && zda.IsLaneSizeD()));9820VIXL_ASSERT(AreSameLaneSize(zda, zn, zm));98219822Emit(0x6420e400 | SVESize(zda) | Rd(zda) | Rn(zn) | Rm(zm));9823}98249825void Assembler::smmla(const ZRegister& zda,9826const ZRegister& zn,9827const ZRegister& zm) {9828VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));9829VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));9830VIXL_ASSERT(zda.IsLaneSizeS());9831VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());98329833Emit(0x45009800 | Rd(zda) | Rn(zn) | Rm(zm));9834}98359836void Assembler::usmmla(const ZRegister& zda,9837const ZRegister& zn,9838const ZRegister& zm) {9839VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));9840VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));9841VIXL_ASSERT(zda.IsLaneSizeS());9842VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());98439844Emit(0x45809800 | Rd(zda) | Rn(zn) | Rm(zm));9845}98469847void Assembler::ummla(const ZRegister& zda,9848const ZRegister& zn,9849const ZRegister& zm) {9850VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));9851VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));9852VIXL_ASSERT(zda.IsLaneSizeS());9853VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());98549855Emit(0x45c09800 | Rd(zda) | Rn(zn) | Rm(zm));9856}98579858void Assembler::usdot(const ZRegister& zda,9859const ZRegister& zn,9860const ZRegister& zm) {9861VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));9862VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));9863VIXL_ASSERT(zda.IsLaneSizeS());9864VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());98659866Emit(0x44807800 | Rd(zda) | Rn(zn) | Rm(zm));9867}98689869void Assembler::usdot(const ZRegister& zda,9870const ZRegister& zn,9871const ZRegister& zm,9872int index) {9873VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));9874VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));9875VIXL_ASSERT(zda.IsLaneSizeS());9876VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());9877VIXL_ASSERT(zm.GetCode() <= 7);9878VIXL_ASSERT(IsUint2(index));98799880Emit(0x44a01800 | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn));9881}98829883void Assembler::sudot(const ZRegister& zda,9884const ZRegister& zn,9885const ZRegister& zm,9886int index) {9887VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));9888VIXL_ASSERT(CPUHas(CPUFeatures::kSVEI8MM));9889VIXL_ASSERT(zda.IsLaneSizeS());9890VIXL_ASSERT(zn.IsLaneSizeB() && zm.IsLaneSizeB());9891VIXL_ASSERT(zm.GetCode() <= 7);9892VIXL_ASSERT(IsUint2(index));98939894Emit(0x44a01c00 | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn));9895}98969897} // namespace aarch649898} // namespace vixl989999009901