Path: blob/master/dep/vixl/src/aarch64/simulator-aarch64.cc
4261 views
// Copyright 2015, VIXL authors1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are met:5//6// * Redistributions of source code must retain the above copyright notice,7// this list of conditions and the following disclaimer.8// * Redistributions in binary form must reproduce the above copyright notice,9// this list of conditions and the following disclaimer in the documentation10// and/or other materials provided with the distribution.11// * Neither the name of ARM Limited nor the names of its contributors may be12// used to endorse or promote products derived from this software without13// specific prior written permission.14//15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE19// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER22// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,23// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2526#ifdef VIXL_INCLUDE_SIMULATOR_AARCH642728#include "simulator-aarch64.h"2930#include <cmath>31#include <cstring>32#include <errno.h>33#include <limits>34#include <sys/mman.h>35#include <unistd.h>3637namespace vixl {38namespace aarch64 {3940using vixl::internal::SimFloat16;4142const Instruction* Simulator::kEndOfSimAddress = NULL;4344MemoryAccessResult TryMemoryAccess(uintptr_t address, uintptr_t access_size) {45#ifdef VIXL_ENABLE_IMPLICIT_CHECKS46for (uintptr_t i = 0; i < access_size; i++) {47if (_vixl_internal_ReadMemory(address, i) == MemoryAccessResult::Failure) {48// The memory access failed.49return MemoryAccessResult::Failure;50}51}5253// Either the memory access did not raise a signal or the signal handler did54// not correctly return MemoryAccessResult::Failure.55return MemoryAccessResult::Success;56#else57USE(address);58USE(access_size);59return MemoryAccessResult::Success;60#endif // VIXL_ENABLE_IMPLICIT_CHECKS61}6263bool MetaDataDepot::MetaDataMTE::is_active = false;6465void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {66int width = msb - lsb + 1;67VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));6869bits <<= lsb;70uint32_t mask = ((1 << width) - 1) << lsb;71VIXL_ASSERT((mask & write_ignore_mask_) == 0);7273value_ = (value_ & ~mask) | (bits & mask);74}757677SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {78switch (id) {79case NZCV:80return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);81case FPCR:82return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);83default:84VIXL_UNREACHABLE();85return SimSystemRegister();86}87}8889const Simulator::FormToVisitorFnMap* Simulator::GetFormToVisitorFnMap() {90static const FormToVisitorFnMap form_to_visitor = {91DEFAULT_FORM_TO_VISITOR_MAP(Simulator),92SIM_AUD_VISITOR_MAP(Simulator),93{"smlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},94{"smlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},95{"smull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},96{"sqdmlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},97{"sqdmlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},98{"sqdmull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},99{"umlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},100{"umlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},101{"umull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},102{"fcmla_asimdelem_c_h"_h, &Simulator::SimulateNEONComplexMulByElement},103{"fcmla_asimdelem_c_s"_h, &Simulator::SimulateNEONComplexMulByElement},104{"fmlal2_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},105{"fmlal_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},106{"fmlsl2_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},107{"fmlsl_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},108{"fmla_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},109{"fmls_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},110{"fmulx_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},111{"fmul_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},112{"fmla_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},113{"fmls_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},114{"fmulx_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},115{"fmul_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},116{"sdot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},117{"udot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},118{"adclb_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},119{"adclt_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},120{"addhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},121{"addhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},122{"addp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},123{"bcax_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},124{"bdep_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},125{"bext_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},126{"bgrp_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},127{"bsl1n_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},128{"bsl2n_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},129{"bsl_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},130{"cadd_z_zz"_h, &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},131{"cdot_z_zzz"_h, &Simulator::SimulateSVEComplexDotProduct},132{"cdot_z_zzzi_d"_h, &Simulator::SimulateSVEComplexDotProduct},133{"cdot_z_zzzi_s"_h, &Simulator::SimulateSVEComplexDotProduct},134{"cmla_z_zzz"_h, &Simulator::SimulateSVEComplexIntMulAdd},135{"cmla_z_zzzi_h"_h, &Simulator::SimulateSVEComplexIntMulAdd},136{"cmla_z_zzzi_s"_h, &Simulator::SimulateSVEComplexIntMulAdd},137{"eor3_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},138{"eorbt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},139{"eortb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},140{"ext_z_zi_con"_h, &Simulator::Simulate_ZdB_Zn1B_Zn2B_imm},141{"faddp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},142{"fcvtlt_z_p_z_h2s"_h, &Simulator::SimulateSVEFPConvertLong},143{"fcvtlt_z_p_z_s2d"_h, &Simulator::SimulateSVEFPConvertLong},144{"fcvtnt_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD},145{"fcvtnt_z_p_z_s2h"_h, &Simulator::Simulate_ZdH_PgM_ZnS},146{"fcvtx_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD},147{"fcvtxnt_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD},148{"flogb_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT},149{"fmaxnmp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},150{"fmaxp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},151{"fminnmp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},152{"fminp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},153{"fmlalb_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},154{"fmlalb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},155{"fmlalt_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},156{"fmlalt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},157{"fmlslb_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},158{"fmlslb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},159{"fmlslt_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},160{"fmlslt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},161{"histcnt_z_p_zz"_h, &Simulator::Simulate_ZdT_PgZ_ZnT_ZmT},162{"histseg_z_zz"_h, &Simulator::Simulate_ZdB_ZnB_ZmB},163{"ldnt1b_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},164{"ldnt1b_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},165{"ldnt1d_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},166{"ldnt1h_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},167{"ldnt1h_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},168{"ldnt1sb_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},169{"ldnt1sb_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},170{"ldnt1sh_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},171{"ldnt1sh_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},172{"ldnt1sw_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},173{"ldnt1w_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},174{"ldnt1w_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},175{"match_p_p_zz"_h, &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},176{"mla_z_zzzi_d"_h, &Simulator::SimulateSVEMlaMlsIndex},177{"mla_z_zzzi_h"_h, &Simulator::SimulateSVEMlaMlsIndex},178{"mla_z_zzzi_s"_h, &Simulator::SimulateSVEMlaMlsIndex},179{"mls_z_zzzi_d"_h, &Simulator::SimulateSVEMlaMlsIndex},180{"mls_z_zzzi_h"_h, &Simulator::SimulateSVEMlaMlsIndex},181{"mls_z_zzzi_s"_h, &Simulator::SimulateSVEMlaMlsIndex},182{"mul_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},183{"mul_z_zzi_d"_h, &Simulator::SimulateSVEMulIndex},184{"mul_z_zzi_h"_h, &Simulator::SimulateSVEMulIndex},185{"mul_z_zzi_s"_h, &Simulator::SimulateSVEMulIndex},186{"nbsl_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},187{"nmatch_p_p_zz"_h, &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},188{"pmul_z_zz"_h, &Simulator::Simulate_ZdB_ZnB_ZmB},189{"pmullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},190{"pmullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},191{"raddhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},192{"raddhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},193{"rshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},194{"rshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},195{"rsubhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},196{"rsubhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},197{"saba_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnT_ZmT},198{"sabalb_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},199{"sabalt_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},200{"sabdlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},201{"sabdlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},202{"sadalp_z_p_z"_h, &Simulator::Simulate_ZdaT_PgM_ZnTb},203{"saddlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},204{"saddlbt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},205{"saddlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},206{"saddwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},207{"saddwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},208{"sbclb_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},209{"sbclt_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},210{"shadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},211{"shrnb_z_zi"_h, &Simulator::SimulateSVENarrow},212{"shrnt_z_zi"_h, &Simulator::SimulateSVENarrow},213{"shsub_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},214{"shsubr_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},215{"sli_z_zzi"_h, &Simulator::Simulate_ZdT_ZnT_const},216{"smaxp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},217{"sminp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},218{"smlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},219{"smlalb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},220{"smlalb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},221{"smlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},222{"smlalt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},223{"smlalt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},224{"smlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},225{"smlslb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},226{"smlslb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},227{"smlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},228{"smlslt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},229{"smlslt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},230{"smulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},231{"smullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},232{"smullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},233{"smullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},234{"smullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},235{"smullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},236{"smullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},237{"splice_z_p_zz_con"_h, &Simulator::VisitSVEVectorSplice},238{"sqabs_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT},239{"sqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},240{"sqcadd_z_zz"_h, &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},241{"sqdmlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},242{"sqdmlalb_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},243{"sqdmlalb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},244{"sqdmlalbt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},245{"sqdmlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},246{"sqdmlalt_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},247{"sqdmlalt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},248{"sqdmlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},249{"sqdmlslb_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},250{"sqdmlslb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},251{"sqdmlslbt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},252{"sqdmlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},253{"sqdmlslt_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},254{"sqdmlslt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},255{"sqdmulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},256{"sqdmulh_z_zzi_d"_h, &Simulator::SimulateSVESaturatingMulHighIndex},257{"sqdmulh_z_zzi_h"_h, &Simulator::SimulateSVESaturatingMulHighIndex},258{"sqdmulh_z_zzi_s"_h, &Simulator::SimulateSVESaturatingMulHighIndex},259{"sqdmullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},260{"sqdmullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},261{"sqdmullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},262{"sqdmullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},263{"sqdmullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},264{"sqdmullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},265{"sqneg_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT},266{"sqrdcmlah_z_zzz"_h, &Simulator::SimulateSVEComplexIntMulAdd},267{"sqrdcmlah_z_zzzi_h"_h, &Simulator::SimulateSVEComplexIntMulAdd},268{"sqrdcmlah_z_zzzi_s"_h, &Simulator::SimulateSVEComplexIntMulAdd},269{"sqrdmlah_z_zzz"_h, &Simulator::SimulateSVESaturatingMulAddHigh},270{"sqrdmlah_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingMulAddHigh},271{"sqrdmlah_z_zzzi_h"_h, &Simulator::SimulateSVESaturatingMulAddHigh},272{"sqrdmlah_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingMulAddHigh},273{"sqrdmlsh_z_zzz"_h, &Simulator::SimulateSVESaturatingMulAddHigh},274{"sqrdmlsh_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingMulAddHigh},275{"sqrdmlsh_z_zzzi_h"_h, &Simulator::SimulateSVESaturatingMulAddHigh},276{"sqrdmlsh_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingMulAddHigh},277{"sqrdmulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},278{"sqrdmulh_z_zzi_d"_h, &Simulator::SimulateSVESaturatingMulHighIndex},279{"sqrdmulh_z_zzi_h"_h, &Simulator::SimulateSVESaturatingMulHighIndex},280{"sqrdmulh_z_zzi_s"_h, &Simulator::SimulateSVESaturatingMulHighIndex},281{"sqrshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},282{"sqrshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},283{"sqrshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},284{"sqrshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},285{"sqrshrunb_z_zi"_h, &Simulator::SimulateSVENarrow},286{"sqrshrunt_z_zi"_h, &Simulator::SimulateSVENarrow},287{"sqshl_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},288{"sqshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},289{"sqshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},290{"sqshlu_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},291{"sqshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},292{"sqshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},293{"sqshrunb_z_zi"_h, &Simulator::SimulateSVENarrow},294{"sqshrunt_z_zi"_h, &Simulator::SimulateSVENarrow},295{"sqsub_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},296{"sqsubr_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},297{"sqxtnb_z_zz"_h, &Simulator::SimulateSVENarrow},298{"sqxtnt_z_zz"_h, &Simulator::SimulateSVENarrow},299{"sqxtunb_z_zz"_h, &Simulator::SimulateSVENarrow},300{"sqxtunt_z_zz"_h, &Simulator::SimulateSVENarrow},301{"srhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},302{"sri_z_zzi"_h, &Simulator::Simulate_ZdT_ZnT_const},303{"srshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},304{"srshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},305{"srshr_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},306{"srsra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},307{"sshllb_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},308{"sshllt_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},309{"ssra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},310{"ssublb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},311{"ssublbt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},312{"ssublt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},313{"ssubltb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},314{"ssubwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},315{"ssubwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},316{"stnt1b_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},317{"stnt1b_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm},318{"stnt1d_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},319{"stnt1h_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},320{"stnt1h_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm},321{"stnt1w_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},322{"stnt1w_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm},323{"subhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},324{"subhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},325{"suqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},326{"tbl_z_zz_2"_h, &Simulator::VisitSVETableLookup},327{"tbx_z_zz"_h, &Simulator::VisitSVETableLookup},328{"uaba_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnT_ZmT},329{"uabalb_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},330{"uabalt_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},331{"uabdlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},332{"uabdlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},333{"uadalp_z_p_z"_h, &Simulator::Simulate_ZdaT_PgM_ZnTb},334{"uaddlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},335{"uaddlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},336{"uaddwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},337{"uaddwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},338{"uhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},339{"uhsub_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},340{"uhsubr_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},341{"umaxp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},342{"uminp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},343{"umlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},344{"umlalb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},345{"umlalb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},346{"umlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},347{"umlalt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},348{"umlalt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},349{"umlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},350{"umlslb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},351{"umlslb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},352{"umlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},353{"umlslt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},354{"umlslt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},355{"umulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},356{"umullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},357{"umullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},358{"umullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},359{"umullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},360{"umullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},361{"umullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},362{"uqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},363{"uqrshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},364{"uqrshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},365{"uqrshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},366{"uqrshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},367{"uqshl_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},368{"uqshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},369{"uqshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},370{"uqshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},371{"uqshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},372{"uqsub_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},373{"uqsubr_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},374{"uqxtnb_z_zz"_h, &Simulator::SimulateSVENarrow},375{"uqxtnt_z_zz"_h, &Simulator::SimulateSVENarrow},376{"urecpe_z_p_z"_h, &Simulator::Simulate_ZdS_PgM_ZnS},377{"urhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},378{"urshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},379{"urshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},380{"urshr_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},381{"ursqrte_z_p_z"_h, &Simulator::Simulate_ZdS_PgM_ZnS},382{"ursra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},383{"ushllb_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},384{"ushllt_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},385{"usqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},386{"usra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},387{"usublb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},388{"usublt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},389{"usubwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},390{"usubwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},391{"whilege_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},392{"whilegt_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},393{"whilehi_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},394{"whilehs_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},395{"whilerw_p_rr"_h, &Simulator::Simulate_PdT_Xn_Xm},396{"whilewr_p_rr"_h, &Simulator::Simulate_PdT_Xn_Xm},397{"xar_z_zzi"_h, &Simulator::SimulateSVEExclusiveOrRotate},398{"smmla_z_zzz"_h, &Simulator::SimulateMatrixMul},399{"ummla_z_zzz"_h, &Simulator::SimulateMatrixMul},400{"usmmla_z_zzz"_h, &Simulator::SimulateMatrixMul},401{"smmla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul},402{"ummla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul},403{"usmmla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul},404{"fmmla_z_zzz_s"_h, &Simulator::SimulateSVEFPMatrixMul},405{"fmmla_z_zzz_d"_h, &Simulator::SimulateSVEFPMatrixMul},406{"ld1row_z_p_bi_u32"_h,407&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},408{"ld1row_z_p_br_contiguous"_h,409&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},410{"ld1rod_z_p_bi_u64"_h,411&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},412{"ld1rod_z_p_br_contiguous"_h,413&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},414{"ld1rob_z_p_bi_u8"_h,415&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},416{"ld1rob_z_p_br_contiguous"_h,417&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},418{"ld1roh_z_p_bi_u16"_h,419&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},420{"ld1roh_z_p_br_contiguous"_h,421&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},422{"usdot_z_zzz_s"_h, &Simulator::VisitSVEIntMulAddUnpredicated},423{"sudot_z_zzzi_s"_h, &Simulator::VisitSVEMulIndex},424{"usdot_z_zzzi_s"_h, &Simulator::VisitSVEMulIndex},425{"usdot_asimdsame2_d"_h, &Simulator::VisitNEON3SameExtra},426{"sudot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},427{"usdot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},428{"addg_64_addsub_immtags"_h, &Simulator::SimulateMTEAddSubTag},429{"gmi_64g_dp_2src"_h, &Simulator::SimulateMTETagMaskInsert},430{"irg_64i_dp_2src"_h, &Simulator::Simulate_XdSP_XnSP_Xm},431{"ldg_64loffset_ldsttags"_h, &Simulator::SimulateMTELoadTag},432{"st2g_64soffset_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},433{"st2g_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},434{"st2g_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},435{"stgp_64_ldstpair_off"_h, &Simulator::SimulateMTEStoreTagPair},436{"stgp_64_ldstpair_post"_h, &Simulator::SimulateMTEStoreTagPair},437{"stgp_64_ldstpair_pre"_h, &Simulator::SimulateMTEStoreTagPair},438{"stg_64soffset_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},439{"stg_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},440{"stg_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},441{"stz2g_64soffset_ldsttags"_h,442&Simulator::Simulator::SimulateMTEStoreTag},443{"stz2g_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},444{"stz2g_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},445{"stzg_64soffset_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},446{"stzg_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},447{"stzg_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},448{"subg_64_addsub_immtags"_h, &Simulator::SimulateMTEAddSubTag},449{"subps_64s_dp_2src"_h, &Simulator::SimulateMTESubPointer},450{"subp_64s_dp_2src"_h, &Simulator::SimulateMTESubPointer},451{"cpyen_cpy_memcms"_h, &Simulator::SimulateCpyE},452{"cpyern_cpy_memcms"_h, &Simulator::SimulateCpyE},453{"cpyewn_cpy_memcms"_h, &Simulator::SimulateCpyE},454{"cpye_cpy_memcms"_h, &Simulator::SimulateCpyE},455{"cpyfen_cpy_memcms"_h, &Simulator::SimulateCpyE},456{"cpyfern_cpy_memcms"_h, &Simulator::SimulateCpyE},457{"cpyfewn_cpy_memcms"_h, &Simulator::SimulateCpyE},458{"cpyfe_cpy_memcms"_h, &Simulator::SimulateCpyE},459{"cpyfmn_cpy_memcms"_h, &Simulator::SimulateCpyM},460{"cpyfmrn_cpy_memcms"_h, &Simulator::SimulateCpyM},461{"cpyfmwn_cpy_memcms"_h, &Simulator::SimulateCpyM},462{"cpyfm_cpy_memcms"_h, &Simulator::SimulateCpyM},463{"cpyfpn_cpy_memcms"_h, &Simulator::SimulateCpyFP},464{"cpyfprn_cpy_memcms"_h, &Simulator::SimulateCpyFP},465{"cpyfpwn_cpy_memcms"_h, &Simulator::SimulateCpyFP},466{"cpyfp_cpy_memcms"_h, &Simulator::SimulateCpyFP},467{"cpymn_cpy_memcms"_h, &Simulator::SimulateCpyM},468{"cpymrn_cpy_memcms"_h, &Simulator::SimulateCpyM},469{"cpymwn_cpy_memcms"_h, &Simulator::SimulateCpyM},470{"cpym_cpy_memcms"_h, &Simulator::SimulateCpyM},471{"cpypn_cpy_memcms"_h, &Simulator::SimulateCpyP},472{"cpyprn_cpy_memcms"_h, &Simulator::SimulateCpyP},473{"cpypwn_cpy_memcms"_h, &Simulator::SimulateCpyP},474{"cpyp_cpy_memcms"_h, &Simulator::SimulateCpyP},475{"setp_set_memcms"_h, &Simulator::SimulateSetP},476{"setpn_set_memcms"_h, &Simulator::SimulateSetP},477{"setgp_set_memcms"_h, &Simulator::SimulateSetGP},478{"setgpn_set_memcms"_h, &Simulator::SimulateSetGP},479{"setm_set_memcms"_h, &Simulator::SimulateSetM},480{"setmn_set_memcms"_h, &Simulator::SimulateSetM},481{"setgm_set_memcms"_h, &Simulator::SimulateSetGM},482{"setgmn_set_memcms"_h, &Simulator::SimulateSetGM},483{"sete_set_memcms"_h, &Simulator::SimulateSetE},484{"seten_set_memcms"_h, &Simulator::SimulateSetE},485{"setge_set_memcms"_h, &Simulator::SimulateSetE},486{"setgen_set_memcms"_h, &Simulator::SimulateSetE},487{"abs_32_dp_1src"_h, &Simulator::VisitDataProcessing1Source},488{"abs_64_dp_1src"_h, &Simulator::VisitDataProcessing1Source},489{"cnt_32_dp_1src"_h, &Simulator::VisitDataProcessing1Source},490{"cnt_64_dp_1src"_h, &Simulator::VisitDataProcessing1Source},491{"ctz_32_dp_1src"_h, &Simulator::VisitDataProcessing1Source},492{"ctz_64_dp_1src"_h, &Simulator::VisitDataProcessing1Source},493{"smax_32_dp_2src"_h, &Simulator::SimulateSignedMinMax},494{"smax_64_dp_2src"_h, &Simulator::SimulateSignedMinMax},495{"smin_32_dp_2src"_h, &Simulator::SimulateSignedMinMax},496{"smin_64_dp_2src"_h, &Simulator::SimulateSignedMinMax},497{"smax_32_minmax_imm"_h, &Simulator::SimulateSignedMinMax},498{"smax_64_minmax_imm"_h, &Simulator::SimulateSignedMinMax},499{"smin_32_minmax_imm"_h, &Simulator::SimulateSignedMinMax},500{"smin_64_minmax_imm"_h, &Simulator::SimulateSignedMinMax},501{"umax_32_dp_2src"_h, &Simulator::SimulateUnsignedMinMax},502{"umax_64_dp_2src"_h, &Simulator::SimulateUnsignedMinMax},503{"umin_32_dp_2src"_h, &Simulator::SimulateUnsignedMinMax},504{"umin_64_dp_2src"_h, &Simulator::SimulateUnsignedMinMax},505{"umax_32u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax},506{"umax_64u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax},507{"umin_32u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax},508{"umin_64u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax},509};510return &form_to_visitor;511}512513// Try to access the piece of memory given by the address passed in RDI and the514// offset passed in RSI, using testb. If a signal is raised then the signal515// handler should set RIP to _vixl_internal_AccessMemory_continue and RAX to516// MemoryAccessResult::Failure. If no signal is raised then zero RAX before517// returning.518#ifdef VIXL_ENABLE_IMPLICIT_CHECKS519#ifdef __x86_64__520asm(R"(521.globl _vixl_internal_ReadMemory522_vixl_internal_ReadMemory:523testb (%rdi, %rsi), %al524xorq %rax, %rax525ret526.globl _vixl_internal_AccessMemory_continue527_vixl_internal_AccessMemory_continue:528ret529)");530#else531asm(R"(532.globl _vixl_internal_ReadMemory533_vixl_internal_ReadMemory:534ret535)");536#endif // __x86_64__537#endif // VIXL_ENABLE_IMPLICIT_CHECKS538539Simulator::Simulator(Decoder* decoder, FILE* stream, SimStack::Allocated stack)540: memory_(std::move(stack)),541last_instr_(NULL),542cpu_features_auditor_(decoder, CPUFeatures::All()) {543// Ensure that shift operations act as the simulator expects.544VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);545VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);546547// Set up a placeholder pipe for CanReadMemory.548VIXL_CHECK(pipe(placeholder_pipe_fd_) == 0);549550// Set up the decoder.551decoder_ = decoder;552decoder_->AppendVisitor(this);553554stream_ = stream;555556print_disasm_ = new PrintDisassembler(stream_);557558memory_.AppendMetaData(&meta_data_);559560// The Simulator and Disassembler share the same available list, held by the561// auditor. The Disassembler only annotates instructions with features that562// are _not_ available, so registering the auditor should have no effect563// unless the simulator is about to abort (due to missing features). In564// practice, this means that with trace enabled, the simulator will crash just565// after the disassembler prints the instruction, with the missing features566// enumerated.567print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);568569SetColouredTrace(false);570trace_parameters_ = LOG_NONE;571572// We have to configure the SVE vector register length before calling573// ResetState().574SetVectorLengthInBits(kZRegMinSize);575576ResetState();577578// Print a warning about exclusive-access instructions, but only the first579// time they are encountered. This warning can be silenced using580// SilenceExclusiveAccessWarning().581print_exclusive_access_warning_ = true;582583guard_pages_ = false;584585// Initialize the common state of RNDR and RNDRRS.586uint16_t seed[3] = {11, 22, 33};587VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rand_state_));588memcpy(rand_state_, seed, sizeof(rand_state_));589590// Initialize all bits of pseudo predicate register to true.591LogicPRegister ones(pregister_all_true_);592ones.SetAllBits();593594// Initialize the debugger but disable it by default.595SetDebuggerEnabled(false);596debugger_ = std::make_unique<Debugger>(this);597}598599void Simulator::ResetSystemRegisters() {600// Reset the system registers.601nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);602fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);603ResetFFR();604}605606void Simulator::ResetRegisters() {607for (unsigned i = 0; i < kNumberOfRegisters; i++) {608WriteXRegister(i, 0xbadbeef);609}610// Returning to address 0 exits the Simulator.611WriteLr(kEndOfSimAddress);612}613614void Simulator::ResetVRegisters() {615// Set SVE/FP registers to a value that is a NaN in both 32-bit and 64-bit FP.616VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);617int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;618for (unsigned i = 0; i < kNumberOfZRegisters; i++) {619VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());620vregisters_[i].NotifyAccessAsZ();621for (int lane = 0; lane < lane_count; lane++) {622// Encode the register number and (D-sized) lane into each NaN, to623// make them easier to trace.624uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |625(0x0000000000000001 * lane);626VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));627VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));628vregisters_[i].Insert(lane, nan_bits);629}630}631}632633void Simulator::ResetPRegisters() {634VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);635int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;636// Ensure the register configuration fits in this bit encoding.637VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);638VIXL_ASSERT(lane_count <= UINT8_MAX);639for (unsigned i = 0; i < kNumberOfPRegisters; i++) {640VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());641for (int lane = 0; lane < lane_count; lane++) {642// Encode the register number and (H-sized) lane into each lane slot.643uint16_t bits = (0x0100 * lane) | i;644pregisters_[i].Insert(lane, bits);645}646}647}648649void Simulator::ResetFFR() {650VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);651int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes;652ffr_register_.Write(static_cast<uint16_t>(GetUintMask(default_active_lanes)));653}654655void Simulator::ResetState() {656ResetSystemRegisters();657ResetRegisters();658ResetVRegisters();659ResetPRegisters();660661WriteSp(memory_.GetStack().GetBase());662663pc_ = NULL;664pc_modified_ = false;665666// BTI state.667btype_ = DefaultBType;668next_btype_ = DefaultBType;669670meta_data_.ResetState();671}672673void Simulator::SetVectorLengthInBits(unsigned vector_length) {674VIXL_ASSERT((vector_length >= kZRegMinSize) &&675(vector_length <= kZRegMaxSize));676VIXL_ASSERT((vector_length % kZRegMinSize) == 0);677vector_length_ = vector_length;678679for (unsigned i = 0; i < kNumberOfZRegisters; i++) {680vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());681}682for (unsigned i = 0; i < kNumberOfPRegisters; i++) {683pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());684}685686ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes());687688ResetVRegisters();689ResetPRegisters();690ResetFFR();691}692693Simulator::~Simulator() {694// The decoder may outlive the simulator.695decoder_->RemoveVisitor(print_disasm_);696delete print_disasm_;697close(placeholder_pipe_fd_[0]);698close(placeholder_pipe_fd_[1]);699}700701702void Simulator::Run() {703// Flush any written registers before executing anything, so that704// manually-set registers are logged _before_ the first instruction.705LogAllWrittenRegisters();706707if (debugger_enabled_) {708// Slow path to check for breakpoints only if the debugger is enabled.709Debugger* debugger = GetDebugger();710while (!IsSimulationFinished()) {711if (debugger->IsAtBreakpoint()) {712fprintf(stream_, "Debugger hit breakpoint, breaking...\n");713debugger->Debug();714} else {715ExecuteInstruction();716}717}718} else {719while (!IsSimulationFinished()) {720ExecuteInstruction();721}722}723}724725726void Simulator::RunFrom(const Instruction* first) {727WritePc(first, NoBranchLog);728Run();729}730731732// clang-format off733const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",734"x6", "x7", "x8", "x9", "x10", "x11",735"x12", "x13", "x14", "x15", "x16", "x17",736"x18", "x19", "x20", "x21", "x22", "x23",737"x24", "x25", "x26", "x27", "x28", "x29",738"lr", "xzr", "sp"};739740const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",741"w6", "w7", "w8", "w9", "w10", "w11",742"w12", "w13", "w14", "w15", "w16", "w17",743"w18", "w19", "w20", "w21", "w22", "w23",744"w24", "w25", "w26", "w27", "w28", "w29",745"w30", "wzr", "wsp"};746747const char* Simulator::breg_names[] = {"b0", "b1", "b2", "b3", "b4", "b5",748"b6", "b7", "b8", "b9", "b10", "b11",749"b12", "b13", "b14", "b15", "b16", "b17",750"b18", "b19", "b20", "b21", "b22", "b23",751"b24", "b25", "b26", "b27", "b28", "b29",752"b30", "b31"};753754const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",755"h6", "h7", "h8", "h9", "h10", "h11",756"h12", "h13", "h14", "h15", "h16", "h17",757"h18", "h19", "h20", "h21", "h22", "h23",758"h24", "h25", "h26", "h27", "h28", "h29",759"h30", "h31"};760761const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",762"s6", "s7", "s8", "s9", "s10", "s11",763"s12", "s13", "s14", "s15", "s16", "s17",764"s18", "s19", "s20", "s21", "s22", "s23",765"s24", "s25", "s26", "s27", "s28", "s29",766"s30", "s31"};767768const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",769"d6", "d7", "d8", "d9", "d10", "d11",770"d12", "d13", "d14", "d15", "d16", "d17",771"d18", "d19", "d20", "d21", "d22", "d23",772"d24", "d25", "d26", "d27", "d28", "d29",773"d30", "d31"};774775const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",776"v6", "v7", "v8", "v9", "v10", "v11",777"v12", "v13", "v14", "v15", "v16", "v17",778"v18", "v19", "v20", "v21", "v22", "v23",779"v24", "v25", "v26", "v27", "v28", "v29",780"v30", "v31"};781782const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",783"z6", "z7", "z8", "z9", "z10", "z11",784"z12", "z13", "z14", "z15", "z16", "z17",785"z18", "z19", "z20", "z21", "z22", "z23",786"z24", "z25", "z26", "z27", "z28", "z29",787"z30", "z31"};788789const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5",790"p6", "p7", "p8", "p9", "p10", "p11",791"p12", "p13", "p14", "p15"};792// clang-format on793794795const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {796// If the code represents the stack pointer, index the name after zr.797if ((code == kSPRegInternalCode) ||798((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {799code = kZeroRegCode + 1;800}801VIXL_ASSERT(code < ArrayLength(wreg_names));802return wreg_names[code];803}804805806const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {807// If the code represents the stack pointer, index the name after zr.808if ((code == kSPRegInternalCode) ||809((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {810code = kZeroRegCode + 1;811}812VIXL_ASSERT(code < ArrayLength(xreg_names));813return xreg_names[code];814}815816817const char* Simulator::BRegNameForCode(unsigned code) {818VIXL_ASSERT(code < kNumberOfVRegisters);819return breg_names[code];820}821822823const char* Simulator::HRegNameForCode(unsigned code) {824VIXL_ASSERT(code < kNumberOfVRegisters);825return hreg_names[code];826}827828829const char* Simulator::SRegNameForCode(unsigned code) {830VIXL_ASSERT(code < kNumberOfVRegisters);831return sreg_names[code];832}833834835const char* Simulator::DRegNameForCode(unsigned code) {836VIXL_ASSERT(code < kNumberOfVRegisters);837return dreg_names[code];838}839840841const char* Simulator::VRegNameForCode(unsigned code) {842VIXL_ASSERT(code < kNumberOfVRegisters);843return vreg_names[code];844}845846847const char* Simulator::ZRegNameForCode(unsigned code) {848VIXL_ASSERT(code < kNumberOfZRegisters);849return zreg_names[code];850}851852853const char* Simulator::PRegNameForCode(unsigned code) {854VIXL_ASSERT(code < kNumberOfPRegisters);855return preg_names[code];856}857858SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) {859SimVRegister ones, result;860dup_immediate(kFormatVnB, ones, 0xff);861mov_zeroing(kFormatVnB, result, pg, ones);862return result;863}864865void Simulator::ExtractFromSimVRegister(VectorFormat vform,866SimPRegister& pd,867SimVRegister vreg) {868SimVRegister zero;869dup_immediate(kFormatVnB, zero, 0);870SVEIntCompareVectorsHelper(ne,871vform,872pd,873GetPTrue(),874vreg,875zero,876false,877LeaveFlags);878}879880#define COLOUR(colour_code) "\033[0;" colour_code "m"881#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"882#define COLOUR_HIGHLIGHT "\033[43m"883#define NORMAL ""884#define GREY "30"885#define RED "31"886#define GREEN "32"887#define YELLOW "33"888#define BLUE "34"889#define MAGENTA "35"890#define CYAN "36"891#define WHITE "37"892void Simulator::SetColouredTrace(bool value) {893coloured_trace_ = value;894895clr_normal = value ? COLOUR(NORMAL) : "";896clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";897clr_flag_value = value ? COLOUR(NORMAL) : "";898clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";899clr_reg_value = value ? COLOUR(CYAN) : "";900clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";901clr_vreg_value = value ? COLOUR(MAGENTA) : "";902clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";903clr_preg_value = value ? COLOUR(GREEN) : "";904clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";905clr_warning = value ? COLOUR_BOLD(YELLOW) : "";906clr_warning_message = value ? COLOUR(YELLOW) : "";907clr_printf = value ? COLOUR(GREEN) : "";908clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";909910if (value) {911print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));912print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));913} else {914print_disasm_->SetCPUFeaturesPrefix("// Needs: ");915print_disasm_->SetCPUFeaturesSuffix("");916}917}918919920void Simulator::SetTraceParameters(int parameters) {921bool disasm_before = trace_parameters_ & LOG_DISASM;922trace_parameters_ = parameters;923bool disasm_after = trace_parameters_ & LOG_DISASM;924925if (disasm_before != disasm_after) {926if (disasm_after) {927decoder_->InsertVisitorBefore(print_disasm_, this);928} else {929decoder_->RemoveVisitor(print_disasm_);930}931}932}933934// Helpers ---------------------------------------------------------------------935uint64_t Simulator::AddWithCarry(unsigned reg_size,936bool set_flags,937uint64_t left,938uint64_t right,939int carry_in) {940std::pair<uint64_t, uint8_t> result_and_flags =941AddWithCarry(reg_size, left, right, carry_in);942if (set_flags) {943uint8_t flags = result_and_flags.second;944ReadNzcv().SetN((flags >> 3) & 1);945ReadNzcv().SetZ((flags >> 2) & 1);946ReadNzcv().SetC((flags >> 1) & 1);947ReadNzcv().SetV((flags >> 0) & 1);948LogSystemRegister(NZCV);949}950return result_and_flags.first;951}952953std::pair<uint64_t, uint8_t> Simulator::AddWithCarry(unsigned reg_size,954uint64_t left,955uint64_t right,956int carry_in) {957VIXL_ASSERT((carry_in == 0) || (carry_in == 1));958VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));959960uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;961uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;962uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;963964left &= reg_mask;965right &= reg_mask;966uint64_t result = (left + right + carry_in) & reg_mask;967968// NZCV bits, ordered N in bit 3 to V in bit 0.969uint8_t nzcv = CalcNFlag(result, reg_size) ? 8 : 0;970nzcv |= CalcZFlag(result) ? 4 : 0;971972// Compute the C flag by comparing the result to the max unsigned integer.973uint64_t max_uint_2op = max_uint - carry_in;974bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);975nzcv |= C ? 2 : 0;976977// Overflow iff the sign bit is the same for the two inputs and different978// for the result.979uint64_t left_sign = left & sign_mask;980uint64_t right_sign = right & sign_mask;981uint64_t result_sign = result & sign_mask;982bool V = (left_sign == right_sign) && (left_sign != result_sign);983nzcv |= V ? 1 : 0;984985return std::make_pair(result, nzcv);986}987988using vixl_uint128_t = std::pair<uint64_t, uint64_t>;989990vixl_uint128_t Simulator::Add128(vixl_uint128_t x, vixl_uint128_t y) {991std::pair<uint64_t, uint8_t> sum_lo =992AddWithCarry(kXRegSize, x.second, y.second, 0);993int carry_in = (sum_lo.second & 0x2) >> 1; // C flag in NZCV result.994std::pair<uint64_t, uint8_t> sum_hi =995AddWithCarry(kXRegSize, x.first, y.first, carry_in);996return std::make_pair(sum_hi.first, sum_lo.first);997}998999vixl_uint128_t Simulator::Lsl128(vixl_uint128_t x, unsigned shift) const {1000VIXL_ASSERT(shift <= 64);1001if (shift == 0) return x;1002if (shift == 64) return std::make_pair(x.second, 0);1003uint64_t lo = x.second << shift;1004uint64_t hi = (x.first << shift) | (x.second >> (64 - shift));1005return std::make_pair(hi, lo);1006}10071008vixl_uint128_t Simulator::Eor128(vixl_uint128_t x, vixl_uint128_t y) const {1009return std::make_pair(x.first ^ y.first, x.second ^ y.second);1010}10111012vixl_uint128_t Simulator::Neg128(vixl_uint128_t x) {1013// Negate the integer value. Throw an assertion when the input is INT128_MIN.1014VIXL_ASSERT((x.first != GetSignMask(64)) || (x.second != 0));1015x.first = ~x.first;1016x.second = ~x.second;1017return Add128(x, {0, 1});1018}10191020vixl_uint128_t Simulator::Mul64(uint64_t x, uint64_t y) {1021bool neg_result = false;1022if ((x >> 63) == 1) {1023x = -x;1024neg_result = !neg_result;1025}1026if ((y >> 63) == 1) {1027y = -y;1028neg_result = !neg_result;1029}10301031uint64_t x_lo = x & 0xffffffff;1032uint64_t x_hi = x >> 32;1033uint64_t y_lo = y & 0xffffffff;1034uint64_t y_hi = y >> 32;10351036uint64_t t1 = x_lo * y_hi;1037uint64_t t2 = x_hi * y_lo;1038vixl_uint128_t a = std::make_pair(0, x_lo * y_lo);1039vixl_uint128_t b = std::make_pair(t1 >> 32, t1 << 32);1040vixl_uint128_t c = std::make_pair(t2 >> 32, t2 << 32);1041vixl_uint128_t d = std::make_pair(x_hi * y_hi, 0);10421043vixl_uint128_t result = Add128(a, b);1044result = Add128(result, c);1045result = Add128(result, d);1046return neg_result ? std::make_pair(-result.first - 1, -result.second)1047: result;1048}10491050vixl_uint128_t Simulator::PolynomialMult128(uint64_t op1,1051uint64_t op2,1052int lane_size_in_bits) const {1053VIXL_ASSERT(static_cast<unsigned>(lane_size_in_bits) <= kDRegSize);1054vixl_uint128_t result = std::make_pair(0, 0);1055vixl_uint128_t op2q = std::make_pair(0, op2);1056for (int i = 0; i < lane_size_in_bits; i++) {1057if ((op1 >> i) & 1) {1058result = Eor128(result, Lsl128(op2q, i));1059}1060}1061return result;1062}10631064int64_t Simulator::ShiftOperand(unsigned reg_size,1065uint64_t uvalue,1066Shift shift_type,1067unsigned amount) const {1068VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||1069(reg_size == kSRegSize) || (reg_size == kDRegSize));1070if (amount > 0) {1071uint64_t mask = GetUintMask(reg_size);1072bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;1073// The behavior is undefined in c++ if the shift amount greater than or1074// equal to the register lane size. Work out the shifted result based on1075// architectural behavior before performing the c++ type shift operations.1076switch (shift_type) {1077case LSL:1078if (amount >= reg_size) {1079return UINT64_C(0);1080}1081uvalue <<= amount;1082break;1083case LSR:1084if (amount >= reg_size) {1085return UINT64_C(0);1086}1087uvalue >>= amount;1088break;1089case ASR:1090if (amount >= reg_size) {1091return is_negative ? ~UINT64_C(0) : UINT64_C(0);1092}1093uvalue >>= amount;1094if (is_negative) {1095// Simulate sign-extension to 64 bits.1096uvalue |= ~UINT64_C(0) << (reg_size - amount);1097}1098break;1099case ROR: {1100uvalue = RotateRight(uvalue, amount, reg_size);1101break;1102}1103default:1104VIXL_UNIMPLEMENTED();1105return 0;1106}1107uvalue &= mask;1108}11091110int64_t result;1111memcpy(&result, &uvalue, sizeof(result));1112return result;1113}111411151116int64_t Simulator::ExtendValue(unsigned reg_size,1117int64_t value,1118Extend extend_type,1119unsigned left_shift) const {1120switch (extend_type) {1121case UXTB:1122value &= kByteMask;1123break;1124case UXTH:1125value &= kHalfWordMask;1126break;1127case UXTW:1128value &= kWordMask;1129break;1130case SXTB:1131value &= kByteMask;1132if ((value & 0x80) != 0) {1133value |= ~UINT64_C(0) << 8;1134}1135break;1136case SXTH:1137value &= kHalfWordMask;1138if ((value & 0x8000) != 0) {1139value |= ~UINT64_C(0) << 16;1140}1141break;1142case SXTW:1143value &= kWordMask;1144if ((value & 0x80000000) != 0) {1145value |= ~UINT64_C(0) << 32;1146}1147break;1148case UXTX:1149case SXTX:1150break;1151default:1152VIXL_UNREACHABLE();1153}1154return ShiftOperand(reg_size, value, LSL, left_shift);1155}115611571158void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {1159AssertSupportedFPCR();11601161// TODO: This assumes that the C++ implementation handles comparisons in the1162// way that we expect (as per AssertSupportedFPCR()).1163bool process_exception = false;1164if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {1165ReadNzcv().SetRawValue(FPUnorderedFlag);1166if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||1167(trap == EnableTrap)) {1168process_exception = true;1169}1170} else if (val0 < val1) {1171ReadNzcv().SetRawValue(FPLessThanFlag);1172} else if (val0 > val1) {1173ReadNzcv().SetRawValue(FPGreaterThanFlag);1174} else if (val0 == val1) {1175ReadNzcv().SetRawValue(FPEqualFlag);1176} else {1177VIXL_UNREACHABLE();1178}1179LogSystemRegister(NZCV);1180if (process_exception) FPProcessException();1181}118211831184uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {1185VIXL_ASSERT(mem_op.IsValid());1186int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());1187if (mem_op.IsImmediateOffset()) {1188return base + mem_op.GetOffset();1189} else {1190VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());1191int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());1192unsigned shift_amount = mem_op.GetShiftAmount();1193if (mem_op.GetShift() != NO_SHIFT) {1194offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);1195}1196if (mem_op.GetExtend() != NO_EXTEND) {1197offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);1198}1199return static_cast<uint64_t>(base + offset);1200}1201}120212031204Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(1205unsigned reg_size, unsigned lane_size) {1206VIXL_ASSERT(reg_size >= lane_size);12071208uint32_t format = 0;1209if (reg_size != lane_size) {1210switch (reg_size) {1211default:1212VIXL_UNREACHABLE();1213break;1214case kQRegSizeInBytes:1215format = kPrintRegAsQVector;1216break;1217case kDRegSizeInBytes:1218format = kPrintRegAsDVector;1219break;1220}1221}12221223switch (lane_size) {1224default:1225VIXL_UNREACHABLE();1226break;1227case kQRegSizeInBytes:1228format |= kPrintReg1Q;1229break;1230case kDRegSizeInBytes:1231format |= kPrintReg1D;1232break;1233case kSRegSizeInBytes:1234format |= kPrintReg1S;1235break;1236case kHRegSizeInBytes:1237format |= kPrintReg1H;1238break;1239case kBRegSizeInBytes:1240format |= kPrintReg1B;1241break;1242}1243// These sizes would be duplicate case labels.1244VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);1245VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);1246VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);1247VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);12481249return static_cast<PrintRegisterFormat>(format);1250}125112521253Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(1254VectorFormat vform) {1255switch (vform) {1256default:1257VIXL_UNREACHABLE();1258return kPrintReg16B;1259case kFormat16B:1260return kPrintReg16B;1261case kFormat8B:1262return kPrintReg8B;1263case kFormat8H:1264return kPrintReg8H;1265case kFormat4H:1266return kPrintReg4H;1267case kFormat4S:1268return kPrintReg4S;1269case kFormat2S:1270return kPrintReg2S;1271case kFormat2D:1272return kPrintReg2D;1273case kFormat1D:1274return kPrintReg1D;12751276case kFormatB:1277return kPrintReg1B;1278case kFormatH:1279return kPrintReg1H;1280case kFormatS:1281return kPrintReg1S;1282case kFormatD:1283return kPrintReg1D;12841285case kFormatVnB:1286return kPrintRegVnB;1287case kFormatVnH:1288return kPrintRegVnH;1289case kFormatVnS:1290return kPrintRegVnS;1291case kFormatVnD:1292return kPrintRegVnD;1293}1294}129512961297Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(1298VectorFormat vform) {1299switch (vform) {1300default:1301VIXL_UNREACHABLE();1302return kPrintReg16B;1303case kFormat8H:1304return kPrintReg8HFP;1305case kFormat4H:1306return kPrintReg4HFP;1307case kFormat4S:1308return kPrintReg4SFP;1309case kFormat2S:1310return kPrintReg2SFP;1311case kFormat2D:1312return kPrintReg2DFP;1313case kFormat1D:1314return kPrintReg1DFP;1315case kFormatH:1316return kPrintReg1HFP;1317case kFormatS:1318return kPrintReg1SFP;1319case kFormatD:1320return kPrintReg1DFP;1321}1322}13231324void Simulator::PrintRegisters() {1325for (unsigned i = 0; i < kNumberOfRegisters; i++) {1326if (i == kSpRegCode) i = kSPRegInternalCode;1327PrintRegister(i);1328}1329}13301331void Simulator::PrintVRegisters() {1332for (unsigned i = 0; i < kNumberOfVRegisters; i++) {1333PrintVRegister(i);1334}1335}13361337void Simulator::PrintZRegisters() {1338for (unsigned i = 0; i < kNumberOfZRegisters; i++) {1339PrintZRegister(i);1340}1341}13421343void Simulator::PrintWrittenRegisters() {1344for (unsigned i = 0; i < kNumberOfRegisters; i++) {1345if (registers_[i].WrittenSinceLastLog()) {1346if (i == kSpRegCode) i = kSPRegInternalCode;1347PrintRegister(i);1348}1349}1350}13511352void Simulator::PrintWrittenVRegisters() {1353bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);1354for (unsigned i = 0; i < kNumberOfVRegisters; i++) {1355if (vregisters_[i].WrittenSinceLastLog()) {1356// Z registers are initialised in the constructor before the user can1357// configure the CPU features, so we must also check for SVE here.1358if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {1359PrintZRegister(i);1360} else {1361PrintVRegister(i);1362}1363}1364}1365}13661367void Simulator::PrintWrittenPRegisters() {1368// P registers are initialised in the constructor before the user can1369// configure the CPU features, so we must check for SVE here.1370if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;1371for (unsigned i = 0; i < kNumberOfPRegisters; i++) {1372if (pregisters_[i].WrittenSinceLastLog()) {1373PrintPRegister(i);1374}1375}1376if (ReadFFR().WrittenSinceLastLog()) PrintFFR();1377}13781379void Simulator::PrintSystemRegisters() {1380PrintSystemRegister(NZCV);1381PrintSystemRegister(FPCR);1382}13831384void Simulator::PrintRegisterValue(const uint8_t* value,1385int value_size,1386PrintRegisterFormat format) {1387int print_width = GetPrintRegSizeInBytes(format);1388VIXL_ASSERT(print_width <= value_size);1389for (int i = value_size - 1; i >= print_width; i--) {1390// Pad with spaces so that values align vertically.1391fprintf(stream_, " ");1392// If we aren't explicitly printing a partial value, ensure that the1393// unprinted bits are zero.1394VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));1395}1396fprintf(stream_, "0x");1397for (int i = print_width - 1; i >= 0; i--) {1398fprintf(stream_, "%02x", value[i]);1399}1400}14011402void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,1403uint16_t lane_mask,1404PrintRegisterFormat format) {1405VIXL_ASSERT((format & kPrintRegAsFP) != 0);1406int lane_size = GetPrintRegLaneSizeInBytes(format);1407fprintf(stream_, " (");1408bool last_inactive = false;1409const char* sep = "";1410for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {1411bool access = (lane_mask & (1 << (i * lane_size))) != 0;1412if (access) {1413// Read the lane as a double, so we can format all FP types in the same1414// way. We squash NaNs, and a double can exactly represent any other value1415// that the smaller types can represent, so this is lossless.1416double element;1417switch (lane_size) {1418case kHRegSizeInBytes: {1419Float16 element_fp16;1420VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);1421memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));1422element = FPToDouble(element_fp16, kUseDefaultNaN);1423break;1424}1425case kSRegSizeInBytes: {1426float element_fp32;1427memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));1428element = static_cast<double>(element_fp32);1429break;1430}1431case kDRegSizeInBytes: {1432memcpy(&element, &value[i * lane_size], sizeof(element));1433break;1434}1435default:1436VIXL_UNREACHABLE();1437fprintf(stream_, "{UnknownFPValue}");1438continue;1439}1440if (IsNaN(element)) {1441// The fprintf behaviour for NaNs is implementation-defined. Always1442// print "nan", so that traces are consistent.1443fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);1444} else {1445fprintf(stream_,1446"%s%s%#.4g%s",1447sep,1448clr_vreg_value,1449element,1450clr_normal);1451}1452last_inactive = false;1453} else if (!last_inactive) {1454// Replace each contiguous sequence of inactive lanes with "...".1455fprintf(stream_, "%s...", sep);1456last_inactive = true;1457}1458}1459fprintf(stream_, ")");1460}14611462void Simulator::PrintRegister(int code,1463PrintRegisterFormat format,1464const char* suffix) {1465VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||1466(static_cast<unsigned>(code) == kSPRegInternalCode));1467VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);1468VIXL_ASSERT((format & kPrintRegAsFP) == 0);14691470SimRegister* reg;1471SimRegister zero;1472if (code == kZeroRegCode) {1473reg = &zero;1474} else {1475// registers_[31] holds the SP.1476VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);1477reg = ®isters_[code % kNumberOfRegisters];1478}14791480// We trace register writes as whole register values, implying that any1481// unprinted bits are all zero:1482// "# x{code}: 0x{-----value----}"1483// "# w{code}: 0x{-value}"1484// Stores trace partial register values, implying nothing about the unprinted1485// bits:1486// "# x{code}<63:0>: 0x{-----value----}"1487// "# x{code}<31:0>: 0x{-value}"1488// "# x{code}<15:0>: 0x{--}"1489// "# x{code}<7:0>: 0x{}"14901491bool is_partial = (format & kPrintRegPartial) != 0;1492unsigned print_reg_size = GetPrintRegSizeInBits(format);1493std::stringstream name;1494if (is_partial) {1495name << XRegNameForCode(code) << GetPartialRegSuffix(format);1496} else {1497// Notify the register that it has been logged, but only if we're printing1498// all of it.1499reg->NotifyRegisterLogged();1500switch (print_reg_size) {1501case kWRegSize:1502name << WRegNameForCode(code);1503break;1504case kXRegSize:1505name << XRegNameForCode(code);1506break;1507default:1508VIXL_UNREACHABLE();1509return;1510}1511}15121513fprintf(stream_,1514"# %s%*s: %s",1515clr_reg_name,1516kPrintRegisterNameFieldWidth,1517name.str().c_str(),1518clr_reg_value);1519PrintRegisterValue(*reg, format);1520fprintf(stream_, "%s%s", clr_normal, suffix);1521}15221523void Simulator::PrintVRegister(int code,1524PrintRegisterFormat format,1525const char* suffix) {1526VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);1527VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||1528((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||1529((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));15301531// We trace register writes as whole register values, implying that any1532// unprinted bits are all zero:1533// "# v{code}: 0x{-------------value------------}"1534// "# d{code}: 0x{-----value----}"1535// "# s{code}: 0x{-value}"1536// "# h{code}: 0x{--}"1537// "# b{code}: 0x{}"1538// Stores trace partial register values, implying nothing about the unprinted1539// bits:1540// "# v{code}<127:0>: 0x{-------------value------------}"1541// "# v{code}<63:0>: 0x{-----value----}"1542// "# v{code}<31:0>: 0x{-value}"1543// "# v{code}<15:0>: 0x{--}"1544// "# v{code}<7:0>: 0x{}"15451546bool is_partial = ((format & kPrintRegPartial) != 0);1547std::stringstream name;1548unsigned print_reg_size = GetPrintRegSizeInBits(format);1549if (is_partial) {1550name << VRegNameForCode(code) << GetPartialRegSuffix(format);1551} else {1552// Notify the register that it has been logged, but only if we're printing1553// all of it.1554vregisters_[code].NotifyRegisterLogged();1555switch (print_reg_size) {1556case kBRegSize:1557name << BRegNameForCode(code);1558break;1559case kHRegSize:1560name << HRegNameForCode(code);1561break;1562case kSRegSize:1563name << SRegNameForCode(code);1564break;1565case kDRegSize:1566name << DRegNameForCode(code);1567break;1568case kQRegSize:1569name << VRegNameForCode(code);1570break;1571default:1572VIXL_UNREACHABLE();1573return;1574}1575}15761577fprintf(stream_,1578"# %s%*s: %s",1579clr_vreg_name,1580kPrintRegisterNameFieldWidth,1581name.str().c_str(),1582clr_vreg_value);1583PrintRegisterValue(vregisters_[code], format);1584fprintf(stream_, "%s", clr_normal);1585if ((format & kPrintRegAsFP) != 0) {1586PrintRegisterValueFPAnnotations(vregisters_[code], format);1587}1588fprintf(stream_, "%s", suffix);1589}15901591void Simulator::PrintVRegistersForStructuredAccess(int rt_code,1592int reg_count,1593uint16_t focus_mask,1594PrintRegisterFormat format) {1595bool print_fp = (format & kPrintRegAsFP) != 0;1596// Suppress FP formatting, so we can specify the lanes we're interested in.1597PrintRegisterFormat format_no_fp =1598static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);15991600for (int r = 0; r < reg_count; r++) {1601int code = (rt_code + r) % kNumberOfVRegisters;1602PrintVRegister(code, format_no_fp, "");1603if (print_fp) {1604PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);1605}1606fprintf(stream_, "\n");1607}1608}16091610void Simulator::PrintZRegistersForStructuredAccess(int rt_code,1611int q_index,1612int reg_count,1613uint16_t focus_mask,1614PrintRegisterFormat format) {1615bool print_fp = (format & kPrintRegAsFP) != 0;1616// Suppress FP formatting, so we can specify the lanes we're interested in.1617PrintRegisterFormat format_no_fp =1618static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);16191620PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);16211622const unsigned size = kQRegSizeInBytes;1623unsigned byte_index = q_index * size;1624const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;1625VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());16261627for (int r = 0; r < reg_count; r++) {1628int code = (rt_code + r) % kNumberOfZRegisters;1629PrintPartialZRegister(code, q_index, format_no_fp, "");1630if (print_fp) {1631PrintRegisterValueFPAnnotations(value, focus_mask, format_q);1632}1633fprintf(stream_, "\n");1634}1635}16361637void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {1638// We're going to print the register in parts, so force a partial format.1639format = GetPrintRegPartial(format);1640VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);1641int vl = GetVectorLengthInBits();1642VIXL_ASSERT((vl % kQRegSize) == 0);1643for (unsigned i = 0; i < (vl / kQRegSize); i++) {1644PrintPartialZRegister(code, i, format);1645}1646vregisters_[code].NotifyRegisterLogged();1647}16481649void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {1650// We're going to print the register in parts, so force a partial format.1651format = GetPrintRegPartial(format);1652VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);1653int vl = GetVectorLengthInBits();1654VIXL_ASSERT((vl % kQRegSize) == 0);1655for (unsigned i = 0; i < (vl / kQRegSize); i++) {1656PrintPartialPRegister(code, i, format);1657}1658pregisters_[code].NotifyRegisterLogged();1659}16601661void Simulator::PrintFFR(PrintRegisterFormat format) {1662// We're going to print the register in parts, so force a partial format.1663format = GetPrintRegPartial(format);1664VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);1665int vl = GetVectorLengthInBits();1666VIXL_ASSERT((vl % kQRegSize) == 0);1667SimPRegister& ffr = ReadFFR();1668for (unsigned i = 0; i < (vl / kQRegSize); i++) {1669PrintPartialPRegister("FFR", ffr, i, format);1670}1671ffr.NotifyRegisterLogged();1672}16731674void Simulator::PrintPartialZRegister(int code,1675int q_index,1676PrintRegisterFormat format,1677const char* suffix) {1678VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);1679VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);1680VIXL_ASSERT((format & kPrintRegPartial) != 0);1681VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());16821683// We _only_ trace partial Z register values in Q-sized chunks, because1684// they're often too large to reasonably fit on a single line. Each line1685// implies nothing about the unprinted bits.1686// "# z{code}<127:0>: 0x{-------------value------------}"16871688format = GetPrintRegAsQChunkOfSVE(format);16891690const unsigned size = kQRegSizeInBytes;1691unsigned byte_index = q_index * size;1692const uint8_t* value = vregisters_[code].GetBytes() + byte_index;1693VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());16941695int lsb = q_index * kQRegSize;1696int msb = lsb + kQRegSize - 1;1697std::stringstream name;1698name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';16991700fprintf(stream_,1701"# %s%*s: %s",1702clr_vreg_name,1703kPrintRegisterNameFieldWidth,1704name.str().c_str(),1705clr_vreg_value);1706PrintRegisterValue(value, size, format);1707fprintf(stream_, "%s", clr_normal);1708if ((format & kPrintRegAsFP) != 0) {1709PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);1710}1711fprintf(stream_, "%s", suffix);1712}17131714void Simulator::PrintPartialPRegister(const char* name,1715const SimPRegister& reg,1716int q_index,1717PrintRegisterFormat format,1718const char* suffix) {1719VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);1720VIXL_ASSERT((format & kPrintRegPartial) != 0);1721VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());17221723// We don't currently use the format for anything here.1724USE(format);17251726// We _only_ trace partial P register values, because they're often too large1727// to reasonably fit on a single line. Each line implies nothing about the1728// unprinted bits.1729//1730// We print values in binary, with spaces between each bit, in order for the1731// bits to align with the Z register bytes that they predicate.1732// "# {name}<15:0>: 0b{-------------value------------}"17331734int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;1735int lsb = q_index * print_size_in_bits;1736int msb = lsb + print_size_in_bits - 1;1737std::stringstream prefix;1738prefix << name << '<' << msb << ':' << lsb << '>';17391740fprintf(stream_,1741"# %s%*s: %s0b",1742clr_preg_name,1743kPrintRegisterNameFieldWidth,1744prefix.str().c_str(),1745clr_preg_value);1746for (int i = msb; i >= lsb; i--) {1747fprintf(stream_, " %c", reg.GetBit(i) ? '1' : '0');1748}1749fprintf(stream_, "%s%s", clr_normal, suffix);1750}17511752void Simulator::PrintPartialPRegister(int code,1753int q_index,1754PrintRegisterFormat format,1755const char* suffix) {1756VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);1757PrintPartialPRegister(PRegNameForCode(code),1758pregisters_[code],1759q_index,1760format,1761suffix);1762}17631764void Simulator::PrintSystemRegister(SystemRegister id) {1765switch (id) {1766case NZCV:1767fprintf(stream_,1768"# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",1769clr_flag_name,1770clr_flag_value,1771ReadNzcv().GetN(),1772ReadNzcv().GetZ(),1773ReadNzcv().GetC(),1774ReadNzcv().GetV(),1775clr_normal);1776break;1777case FPCR: {1778static const char* rmode[] = {"0b00 (Round to Nearest)",1779"0b01 (Round towards Plus Infinity)",1780"0b10 (Round towards Minus Infinity)",1781"0b11 (Round towards Zero)"};1782VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));1783fprintf(stream_,1784"# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",1785clr_flag_name,1786clr_flag_value,1787ReadFpcr().GetAHP(),1788ReadFpcr().GetDN(),1789ReadFpcr().GetFZ(),1790rmode[ReadFpcr().GetRMode()],1791clr_normal);1792break;1793}1794default:1795VIXL_UNREACHABLE();1796}1797}17981799uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,1800uint16_t future_access_mask,1801int struct_element_count,1802int lane_size_in_bytes,1803const char* op,1804uintptr_t address,1805int reg_size_in_bytes) {1806// We want to assume that we'll access at least one lane.1807VIXL_ASSERT(access_mask != 0);1808VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||1809(reg_size_in_bytes == kQRegSizeInBytes));1810bool started_annotation = false;1811// Indent to match the register field, the fixed formatting, and the value1812// prefix ("0x"): "# {name}: 0x"1813fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, "");1814// First, annotate the lanes (byte by byte).1815for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {1816bool access = (access_mask & (1 << lane)) != 0;1817bool future = (future_access_mask & (1 << lane)) != 0;1818if (started_annotation) {1819// If we've started an annotation, draw a horizontal line in addition to1820// any other symbols.1821if (access) {1822fprintf(stream_, "─╨");1823} else if (future) {1824fprintf(stream_, "─║");1825} else {1826fprintf(stream_, "──");1827}1828} else {1829if (access) {1830started_annotation = true;1831fprintf(stream_, " â•™");1832} else if (future) {1833fprintf(stream_, " â•‘");1834} else {1835fprintf(stream_, " ");1836}1837}1838}1839VIXL_ASSERT(started_annotation);1840fprintf(stream_, "─ 0x");1841int lane_size_in_nibbles = lane_size_in_bytes * 2;1842// Print the most-significant struct element first.1843const char* sep = "";1844for (int i = struct_element_count - 1; i >= 0; i--) {1845int offset = lane_size_in_bytes * i;1846auto nibble = MemReadUint(lane_size_in_bytes, address + offset);1847VIXL_ASSERT(nibble);1848fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, *nibble);1849sep = "'";1850}1851fprintf(stream_,1852" %s %s0x%016" PRIxPTR "%s\n",1853op,1854clr_memory_address,1855address,1856clr_normal);1857return future_access_mask & ~access_mask;1858}18591860void Simulator::PrintAccess(int code,1861PrintRegisterFormat format,1862const char* op,1863uintptr_t address) {1864VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);1865VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));1866if ((format & kPrintRegPartial) == 0) {1867if (code != kZeroRegCode) {1868registers_[code].NotifyRegisterLogged();1869}1870}1871// Scalar-format accesses use a simple format:1872// "# {reg}: 0x{value} -> {address}"18731874// Suppress the newline, so the access annotation goes on the same line.1875PrintRegister(code, format, "");1876fprintf(stream_,1877" %s %s0x%016" PRIxPTR "%s\n",1878op,1879clr_memory_address,1880address,1881clr_normal);1882}18831884void Simulator::PrintVAccess(int code,1885PrintRegisterFormat format,1886const char* op,1887uintptr_t address) {1888VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));18891890// Scalar-format accesses use a simple format:1891// "# v{code}: 0x{value} -> {address}"18921893// Suppress the newline, so the access annotation goes on the same line.1894PrintVRegister(code, format, "");1895fprintf(stream_,1896" %s %s0x%016" PRIxPTR "%s\n",1897op,1898clr_memory_address,1899address,1900clr_normal);1901}19021903void Simulator::PrintVStructAccess(int rt_code,1904int reg_count,1905PrintRegisterFormat format,1906const char* op,1907uintptr_t address) {1908VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));19091910// For example:1911// "# v{code}: 0x{value}"1912// "# ...: 0x{value}"1913// "# â•‘ ╙─ {struct_value} -> {lowest_address}"1914// "# ╙───── {struct_value} -> {highest_address}"19151916uint16_t lane_mask = GetPrintRegLaneMask(format);1917PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);19181919int reg_size_in_bytes = GetPrintRegSizeInBytes(format);1920int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);1921for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {1922uint16_t access_mask = 1 << i;1923VIXL_ASSERT((lane_mask & access_mask) != 0);1924lane_mask = PrintPartialAccess(access_mask,1925lane_mask,1926reg_count,1927lane_size_in_bytes,1928op,1929address + (i * reg_count));1930}1931}19321933void Simulator::PrintVSingleStructAccess(int rt_code,1934int reg_count,1935int lane,1936PrintRegisterFormat format,1937const char* op,1938uintptr_t address) {1939VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));19401941// For example:1942// "# v{code}: 0x{value}"1943// "# ...: 0x{value}"1944// "# ╙───── {struct_value} -> {address}"19451946int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);1947uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);1948PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);1949PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);1950}19511952void Simulator::PrintVReplicatingStructAccess(int rt_code,1953int reg_count,1954PrintRegisterFormat format,1955const char* op,1956uintptr_t address) {1957VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));19581959// For example:1960// "# v{code}: 0x{value}"1961// "# ...: 0x{value}"1962// "# ╙─╨─╨─╨─ {struct_value} -> {address}"19631964int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);1965uint16_t lane_mask = GetPrintRegLaneMask(format);1966PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);1967PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);1968}19691970void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {1971VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));19721973// Scalar-format accesses are split into separate chunks, each of which uses a1974// simple format:1975// "# z{code}<127:0>: 0x{value} -> {address}"1976// "# z{code}<255:128>: 0x{value} -> {address + 16}"1977// "# z{code}<383:256>: 0x{value} -> {address + 32}"1978// etc19791980int vl = GetVectorLengthInBits();1981VIXL_ASSERT((vl % kQRegSize) == 0);1982for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {1983// Suppress the newline, so the access annotation goes on the same line.1984PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");1985fprintf(stream_,1986" %s %s0x%016" PRIxPTR "%s\n",1987op,1988clr_memory_address,1989address,1990clr_normal);1991address += kQRegSizeInBytes;1992}1993}19941995void Simulator::PrintZStructAccess(int rt_code,1996int reg_count,1997const LogicPRegister& pg,1998PrintRegisterFormat format,1999int msize_in_bytes,2000const char* op,2001const LogicSVEAddressVector& addr) {2002VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));20032004// For example:2005// "# z{code}<255:128>: 0x{value}"2006// "# ...<255:128>: 0x{value}"2007// "# â•‘ ╙─ {struct_value} -> {first_address}"2008// "# ╙───── {struct_value} -> {last_address}"20092010// We're going to print the register in parts, so force a partial format.2011bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;2012format = GetPrintRegPartial(format);20132014int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);2015int vl = GetVectorLengthInBits();2016VIXL_ASSERT((vl % kQRegSize) == 0);2017int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;2018for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {2019uint16_t pred =2020pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);2021if ((pred == 0) && skip_inactive_chunks) continue;20222023PrintZRegistersForStructuredAccess(rt_code,2024q_index,2025reg_count,2026pred,2027format);2028if (pred == 0) {2029// This register chunk has no active lanes. The loop below would print2030// nothing, so leave a blank line to keep structures grouped together.2031fprintf(stream_, "#\n");2032continue;2033}2034for (int i = 0; i < lanes_per_q; i++) {2035uint16_t access = 1 << (i * esize_in_bytes);2036int lane = (q_index * lanes_per_q) + i;2037// Skip inactive lanes.2038if ((pred & access) == 0) continue;2039pred = PrintPartialAccess(access,2040pred,2041reg_count,2042msize_in_bytes,2043op,2044addr.GetStructAddress(lane));2045}2046}20472048// We print the whole register, even for stores.2049for (int i = 0; i < reg_count; i++) {2050vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();2051}2052}20532054void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {2055VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));20562057// Scalar-format accesses are split into separate chunks, each of which uses a2058// simple format:2059// "# p{code}<15:0>: 0b{value} -> {address}"2060// "# p{code}<31:16>: 0b{value} -> {address + 2}"2061// "# p{code}<47:32>: 0b{value} -> {address + 4}"2062// etc20632064int vl = GetVectorLengthInBits();2065VIXL_ASSERT((vl % kQRegSize) == 0);2066for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {2067// Suppress the newline, so the access annotation goes on the same line.2068PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");2069fprintf(stream_,2070" %s %s0x%016" PRIxPTR "%s\n",2071op,2072clr_memory_address,2073address,2074clr_normal);2075address += kQRegSizeInBytes;2076}2077}20782079void Simulator::PrintMemTransfer(uintptr_t dst, uintptr_t src, uint8_t value) {2080fprintf(stream_,2081"# %s: %s0x%016" PRIxPTR " %s<- %s0x%02x%s",2082clr_reg_name,2083clr_memory_address,2084dst,2085clr_normal,2086clr_reg_value,2087value,2088clr_normal);20892090fprintf(stream_,2091" <- %s0x%016" PRIxPTR "%s\n",2092clr_memory_address,2093src,2094clr_normal);2095}20962097void Simulator::PrintRead(int rt_code,2098PrintRegisterFormat format,2099uintptr_t address) {2100VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);2101if (rt_code != kZeroRegCode) {2102registers_[rt_code].NotifyRegisterLogged();2103}2104PrintAccess(rt_code, format, "<-", address);2105}21062107void Simulator::PrintExtendingRead(int rt_code,2108PrintRegisterFormat format,2109int access_size_in_bytes,2110uintptr_t address) {2111int reg_size_in_bytes = GetPrintRegSizeInBytes(format);2112if (access_size_in_bytes == reg_size_in_bytes) {2113// There is no extension here, so print a simple load.2114PrintRead(rt_code, format, address);2115return;2116}2117VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);21182119// For sign- and zero-extension, make it clear that the resulting register2120// value is different from what is loaded from memory.2121VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);2122if (rt_code != kZeroRegCode) {2123registers_[rt_code].NotifyRegisterLogged();2124}2125PrintRegister(rt_code, format);2126PrintPartialAccess(1,21270,21281,2129access_size_in_bytes,2130"<-",2131address,2132kXRegSizeInBytes);2133}21342135void Simulator::PrintVRead(int rt_code,2136PrintRegisterFormat format,2137uintptr_t address) {2138VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);2139vregisters_[rt_code].NotifyRegisterLogged();2140PrintVAccess(rt_code, format, "<-", address);2141}21422143void Simulator::PrintWrite(int rt_code,2144PrintRegisterFormat format,2145uintptr_t address) {2146// Because this trace doesn't represent a change to the source register's2147// value, only print the relevant part of the value.2148format = GetPrintRegPartial(format);2149VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);2150if (rt_code != kZeroRegCode) {2151registers_[rt_code].NotifyRegisterLogged();2152}2153PrintAccess(rt_code, format, "->", address);2154}21552156void Simulator::PrintVWrite(int rt_code,2157PrintRegisterFormat format,2158uintptr_t address) {2159// Because this trace doesn't represent a change to the source register's2160// value, only print the relevant part of the value.2161format = GetPrintRegPartial(format);2162// It only makes sense to write scalar values here. Vectors are handled by2163// PrintVStructAccess.2164VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);2165PrintVAccess(rt_code, format, "->", address);2166}21672168void Simulator::PrintTakenBranch(const Instruction* target) {2169fprintf(stream_,2170"# %sBranch%s to 0x%016" PRIx64 ".\n",2171clr_branch_marker,2172clr_normal,2173reinterpret_cast<uint64_t>(target));2174}21752176// Visitors---------------------------------------------------------------------217721782179void Simulator::Visit(Metadata* metadata, const Instruction* instr) {2180VIXL_ASSERT(metadata->count("form") > 0);2181std::string form = (*metadata)["form"];2182form_hash_ = Hash(form.c_str());2183const FormToVisitorFnMap* fv = Simulator::GetFormToVisitorFnMap();2184FormToVisitorFnMap::const_iterator it = fv->find(form_hash_);2185if (it == fv->end()) {2186VisitUnimplemented(instr);2187} else {2188(it->second)(this, instr);2189}2190}21912192void Simulator::Simulate_PdT_PgZ_ZnT_ZmT(const Instruction* instr) {2193VectorFormat vform = instr->GetSVEVectorFormat();2194SimPRegister& pd = ReadPRegister(instr->GetPd());2195SimPRegister& pg = ReadPRegister(instr->GetPgLow8());2196SimVRegister& zm = ReadVRegister(instr->GetRm());2197SimVRegister& zn = ReadVRegister(instr->GetRn());21982199switch (form_hash_) {2200case "match_p_p_zz"_h:2201match(vform, pd, zn, zm, /* negate_match = */ false);2202break;2203case "nmatch_p_p_zz"_h:2204match(vform, pd, zn, zm, /* negate_match = */ true);2205break;2206default:2207VIXL_UNIMPLEMENTED();2208}2209mov_zeroing(pd, pg, pd);2210PredTest(vform, pg, pd);2211}22122213void Simulator::Simulate_PdT_Xn_Xm(const Instruction* instr) {2214VectorFormat vform = instr->GetSVEVectorFormat();2215SimPRegister& pd = ReadPRegister(instr->GetPd());2216uint64_t src1 = ReadXRegister(instr->GetRn());2217uint64_t src2 = ReadXRegister(instr->GetRm());22182219uint64_t absdiff = (src1 > src2) ? (src1 - src2) : (src2 - src1);2220absdiff >>= LaneSizeInBytesLog2FromFormat(vform);22212222bool no_conflict = false;2223switch (form_hash_) {2224case "whilerw_p_rr"_h:2225no_conflict = (absdiff == 0);2226break;2227case "whilewr_p_rr"_h:2228no_conflict = (absdiff == 0) || (src2 <= src1);2229break;2230default:2231VIXL_UNIMPLEMENTED();2232}22332234LogicPRegister dst(pd);2235for (int i = 0; i < LaneCountFromFormat(vform); i++) {2236dst.SetActive(vform,2237i,2238no_conflict || (static_cast<uint64_t>(i) < absdiff));2239}22402241PredTest(vform, GetPTrue(), pd);2242}22432244void Simulator::Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction* instr) {2245VIXL_ASSERT(form_hash_ == "ext_z_zi_con"_h);22462247SimVRegister& zd = ReadVRegister(instr->GetRd());2248SimVRegister& zn = ReadVRegister(instr->GetRn());2249SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);22502251int index = instr->GetSVEExtractImmediate();2252int vl = GetVectorLengthInBytes();2253index = (index >= vl) ? 0 : index;22542255ext(kFormatVnB, zd, zn, zn2, index);2256}22572258void Simulator::Simulate_ZdB_ZnB_ZmB(const Instruction* instr) {2259SimVRegister& zd = ReadVRegister(instr->GetRd());2260SimVRegister& zm = ReadVRegister(instr->GetRm());2261SimVRegister& zn = ReadVRegister(instr->GetRn());22622263switch (form_hash_) {2264case "histseg_z_zz"_h:2265if (instr->GetSVEVectorFormat() == kFormatVnB) {2266histogram(kFormatVnB,2267zd,2268GetPTrue(),2269zn,2270zm,2271/* do_segmented = */ true);2272} else {2273VIXL_UNIMPLEMENTED();2274}2275break;2276case "pmul_z_zz"_h:2277pmul(kFormatVnB, zd, zn, zm);2278break;2279default:2280VIXL_UNIMPLEMENTED();2281}2282}22832284void Simulator::SimulateSVEMulIndex(const Instruction* instr) {2285VectorFormat vform = instr->GetSVEVectorFormat();2286SimVRegister& zd = ReadVRegister(instr->GetRd());2287SimVRegister& zn = ReadVRegister(instr->GetRn());22882289// The encoding for B and H-sized lanes are redefined to encode the most2290// significant bit of index for H-sized lanes. B-sized lanes are not2291// supported.2292if (vform == kFormatVnB) vform = kFormatVnH;22932294VIXL_ASSERT((form_hash_ == "mul_z_zzi_d"_h) ||2295(form_hash_ == "mul_z_zzi_h"_h) ||2296(form_hash_ == "mul_z_zzi_s"_h));22972298SimVRegister temp;2299dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());2300mul(vform, zd, zn, temp);2301}23022303void Simulator::SimulateSVEMlaMlsIndex(const Instruction* instr) {2304VectorFormat vform = instr->GetSVEVectorFormat();2305SimVRegister& zda = ReadVRegister(instr->GetRd());2306SimVRegister& zn = ReadVRegister(instr->GetRn());23072308// The encoding for B and H-sized lanes are redefined to encode the most2309// significant bit of index for H-sized lanes. B-sized lanes are not2310// supported.2311if (vform == kFormatVnB) vform = kFormatVnH;23122313VIXL_ASSERT(2314(form_hash_ == "mla_z_zzzi_d"_h) || (form_hash_ == "mla_z_zzzi_h"_h) ||2315(form_hash_ == "mla_z_zzzi_s"_h) || (form_hash_ == "mls_z_zzzi_d"_h) ||2316(form_hash_ == "mls_z_zzzi_h"_h) || (form_hash_ == "mls_z_zzzi_s"_h));23172318SimVRegister temp;2319dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());2320if (instr->ExtractBit(10) == 0) {2321mla(vform, zda, zda, zn, temp);2322} else {2323mls(vform, zda, zda, zn, temp);2324}2325}23262327void Simulator::SimulateSVESaturatingMulHighIndex(const Instruction* instr) {2328VectorFormat vform = instr->GetSVEVectorFormat();2329SimVRegister& zd = ReadVRegister(instr->GetRd());2330SimVRegister& zn = ReadVRegister(instr->GetRn());23312332// The encoding for B and H-sized lanes are redefined to encode the most2333// significant bit of index for H-sized lanes. B-sized lanes are not2334// supported.2335if (vform == kFormatVnB) {2336vform = kFormatVnH;2337}23382339SimVRegister temp;2340dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());2341switch (form_hash_) {2342case "sqdmulh_z_zzi_h"_h:2343case "sqdmulh_z_zzi_s"_h:2344case "sqdmulh_z_zzi_d"_h:2345sqdmulh(vform, zd, zn, temp);2346break;2347case "sqrdmulh_z_zzi_h"_h:2348case "sqrdmulh_z_zzi_s"_h:2349case "sqrdmulh_z_zzi_d"_h:2350sqrdmulh(vform, zd, zn, temp);2351break;2352default:2353VIXL_UNIMPLEMENTED();2354}2355}23562357void Simulator::SimulateSVESaturatingIntMulLongIdx(const Instruction* instr) {2358VectorFormat vform = instr->GetSVEVectorFormat();2359SimVRegister& zd = ReadVRegister(instr->GetRd());2360SimVRegister& zn = ReadVRegister(instr->GetRn());23612362SimVRegister temp, zm_idx, zn_b, zn_t;2363// Instead of calling the indexed form of the instruction logic, we call the2364// vector form, which can reuse existing function logic without modification.2365// Select the specified elements based on the index input and than pack them2366// to the corresponding position.2367VectorFormat vform_half = VectorFormatHalfWidth(vform);2368dup_elements_to_segments(vform_half, temp, instr->GetSVEMulLongZmAndIndex());2369pack_even_elements(vform_half, zm_idx, temp);23702371pack_even_elements(vform_half, zn_b, zn);2372pack_odd_elements(vform_half, zn_t, zn);23732374switch (form_hash_) {2375case "smullb_z_zzi_s"_h:2376case "smullb_z_zzi_d"_h:2377smull(vform, zd, zn_b, zm_idx);2378break;2379case "smullt_z_zzi_s"_h:2380case "smullt_z_zzi_d"_h:2381smull(vform, zd, zn_t, zm_idx);2382break;2383case "sqdmullb_z_zzi_d"_h:2384sqdmull(vform, zd, zn_b, zm_idx);2385break;2386case "sqdmullt_z_zzi_d"_h:2387sqdmull(vform, zd, zn_t, zm_idx);2388break;2389case "umullb_z_zzi_s"_h:2390case "umullb_z_zzi_d"_h:2391umull(vform, zd, zn_b, zm_idx);2392break;2393case "umullt_z_zzi_s"_h:2394case "umullt_z_zzi_d"_h:2395umull(vform, zd, zn_t, zm_idx);2396break;2397case "sqdmullb_z_zzi_s"_h:2398sqdmull(vform, zd, zn_b, zm_idx);2399break;2400case "sqdmullt_z_zzi_s"_h:2401sqdmull(vform, zd, zn_t, zm_idx);2402break;2403case "smlalb_z_zzzi_s"_h:2404case "smlalb_z_zzzi_d"_h:2405smlal(vform, zd, zn_b, zm_idx);2406break;2407case "smlalt_z_zzzi_s"_h:2408case "smlalt_z_zzzi_d"_h:2409smlal(vform, zd, zn_t, zm_idx);2410break;2411case "smlslb_z_zzzi_s"_h:2412case "smlslb_z_zzzi_d"_h:2413smlsl(vform, zd, zn_b, zm_idx);2414break;2415case "smlslt_z_zzzi_s"_h:2416case "smlslt_z_zzzi_d"_h:2417smlsl(vform, zd, zn_t, zm_idx);2418break;2419case "umlalb_z_zzzi_s"_h:2420case "umlalb_z_zzzi_d"_h:2421umlal(vform, zd, zn_b, zm_idx);2422break;2423case "umlalt_z_zzzi_s"_h:2424case "umlalt_z_zzzi_d"_h:2425umlal(vform, zd, zn_t, zm_idx);2426break;2427case "umlslb_z_zzzi_s"_h:2428case "umlslb_z_zzzi_d"_h:2429umlsl(vform, zd, zn_b, zm_idx);2430break;2431case "umlslt_z_zzzi_s"_h:2432case "umlslt_z_zzzi_d"_h:2433umlsl(vform, zd, zn_t, zm_idx);2434break;2435default:2436VIXL_UNIMPLEMENTED();2437}2438}24392440void Simulator::Simulate_ZdH_PgM_ZnS(const Instruction* instr) {2441SimPRegister& pg = ReadPRegister(instr->GetPgLow8());2442SimVRegister& zd = ReadVRegister(instr->GetRd());2443SimVRegister& zn = ReadVRegister(instr->GetRn());2444SimVRegister result, zd_b;24452446pack_even_elements(kFormatVnH, zd_b, zd);24472448switch (form_hash_) {2449case "fcvtnt_z_p_z_s2h"_h:2450fcvt(kFormatVnH, kFormatVnS, result, pg, zn);2451pack_even_elements(kFormatVnH, result, result);2452zip1(kFormatVnH, result, zd_b, result);2453break;2454default:2455VIXL_UNIMPLEMENTED();2456}2457mov_merging(kFormatVnS, zd, pg, result);2458}24592460void Simulator::Simulate_ZdS_PgM_ZnD(const Instruction* instr) {2461SimPRegister& pg = ReadPRegister(instr->GetPgLow8());2462SimVRegister& zd = ReadVRegister(instr->GetRd());2463SimVRegister& zn = ReadVRegister(instr->GetRn());2464SimVRegister result, zero, zd_b;24652466zero.Clear();2467pack_even_elements(kFormatVnS, zd_b, zd);24682469switch (form_hash_) {2470case "fcvtnt_z_p_z_d2s"_h:2471fcvt(kFormatVnS, kFormatVnD, result, pg, zn);2472pack_even_elements(kFormatVnS, result, result);2473zip1(kFormatVnS, result, zd_b, result);2474break;2475case "fcvtx_z_p_z_d2s"_h:2476fcvtxn(kFormatVnS, result, zn);2477zip1(kFormatVnS, result, result, zero);2478break;2479case "fcvtxnt_z_p_z_d2s"_h:2480fcvtxn(kFormatVnS, result, zn);2481zip1(kFormatVnS, result, zd_b, result);2482break;2483default:2484VIXL_UNIMPLEMENTED();2485}2486mov_merging(kFormatVnD, zd, pg, result);2487}24882489void Simulator::SimulateSVEFPConvertLong(const Instruction* instr) {2490SimPRegister& pg = ReadPRegister(instr->GetPgLow8());2491SimVRegister& zd = ReadVRegister(instr->GetRd());2492SimVRegister& zn = ReadVRegister(instr->GetRn());2493SimVRegister result;24942495switch (form_hash_) {2496case "fcvtlt_z_p_z_h2s"_h:2497ext(kFormatVnB, result, zn, zn, kHRegSizeInBytes);2498fcvt(kFormatVnS, kFormatVnH, zd, pg, result);2499break;2500case "fcvtlt_z_p_z_s2d"_h:2501ext(kFormatVnB, result, zn, zn, kSRegSizeInBytes);2502fcvt(kFormatVnD, kFormatVnS, zd, pg, result);2503break;2504default:2505VIXL_UNIMPLEMENTED();2506}2507}25082509void Simulator::Simulate_ZdS_PgM_ZnS(const Instruction* instr) {2510VectorFormat vform = instr->GetSVEVectorFormat();2511SimPRegister& pg = ReadPRegister(instr->GetPgLow8());2512SimVRegister& zd = ReadVRegister(instr->GetRd());2513SimVRegister& zn = ReadVRegister(instr->GetRn());2514SimVRegister result;25152516if (vform != kFormatVnS) {2517VIXL_UNIMPLEMENTED();2518}25192520switch (form_hash_) {2521case "urecpe_z_p_z"_h:2522urecpe(vform, result, zn);2523break;2524case "ursqrte_z_p_z"_h:2525ursqrte(vform, result, zn);2526break;2527default:2528VIXL_UNIMPLEMENTED();2529}2530mov_merging(vform, zd, pg, result);2531}25322533void Simulator::Simulate_ZdT_PgM_ZnT(const Instruction* instr) {2534VectorFormat vform = instr->GetSVEVectorFormat();2535SimPRegister& pg = ReadPRegister(instr->GetPgLow8());2536SimVRegister& zd = ReadVRegister(instr->GetRd());2537SimVRegister& zn = ReadVRegister(instr->GetRn());2538SimVRegister result;25392540switch (form_hash_) {2541case "flogb_z_p_z"_h:2542vform = instr->GetSVEVectorFormat(17);2543flogb(vform, result, zn);2544break;2545case "sqabs_z_p_z"_h:2546abs(vform, result, zn).SignedSaturate(vform);2547break;2548case "sqneg_z_p_z"_h:2549neg(vform, result, zn).SignedSaturate(vform);2550break;2551default:2552VIXL_UNIMPLEMENTED();2553}2554mov_merging(vform, zd, pg, result);2555}25562557void Simulator::Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr) {2558VectorFormat vform = instr->GetSVEVectorFormat();2559SimPRegister& pg = ReadPRegister(instr->GetPgLow8());2560SimVRegister& zd = ReadVRegister(instr->GetRd());2561SimVRegister& zm = ReadVRegister(instr->GetRm());2562SimVRegister& zn = ReadVRegister(instr->GetRn());2563SimVRegister result;25642565VIXL_ASSERT(form_hash_ == "histcnt_z_p_zz"_h);2566if ((vform == kFormatVnS) || (vform == kFormatVnD)) {2567histogram(vform, result, pg, zn, zm);2568mov_zeroing(vform, zd, pg, result);2569} else {2570VIXL_UNIMPLEMENTED();2571}2572}25732574void Simulator::Simulate_ZdT_ZnT_ZmT(const Instruction* instr) {2575VectorFormat vform = instr->GetSVEVectorFormat();2576SimVRegister& zd = ReadVRegister(instr->GetRd());2577SimVRegister& zm = ReadVRegister(instr->GetRm());2578SimVRegister& zn = ReadVRegister(instr->GetRn());2579SimVRegister result;2580bool do_bext = false;25812582switch (form_hash_) {2583case "bdep_z_zz"_h:2584bdep(vform, zd, zn, zm);2585break;2586case "bext_z_zz"_h:2587do_bext = true;2588VIXL_FALLTHROUGH();2589case "bgrp_z_zz"_h:2590bgrp(vform, zd, zn, zm, do_bext);2591break;2592case "eorbt_z_zz"_h:2593rotate_elements_right(vform, result, zm, 1);2594SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);2595mov_alternating(vform, zd, result, 0);2596break;2597case "eortb_z_zz"_h:2598rotate_elements_right(vform, result, zm, -1);2599SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);2600mov_alternating(vform, zd, result, 1);2601break;2602case "mul_z_zz"_h:2603mul(vform, zd, zn, zm);2604break;2605case "smulh_z_zz"_h:2606smulh(vform, zd, zn, zm);2607break;2608case "sqdmulh_z_zz"_h:2609sqdmulh(vform, zd, zn, zm);2610break;2611case "sqrdmulh_z_zz"_h:2612sqrdmulh(vform, zd, zn, zm);2613break;2614case "umulh_z_zz"_h:2615umulh(vform, zd, zn, zm);2616break;2617default:2618VIXL_UNIMPLEMENTED();2619}2620}26212622void Simulator::Simulate_ZdT_ZnT_ZmTb(const Instruction* instr) {2623VectorFormat vform = instr->GetSVEVectorFormat();2624SimVRegister& zd = ReadVRegister(instr->GetRd());2625SimVRegister& zm = ReadVRegister(instr->GetRm());2626SimVRegister& zn = ReadVRegister(instr->GetRn());26272628SimVRegister zm_b, zm_t;2629VectorFormat vform_half = VectorFormatHalfWidth(vform);2630pack_even_elements(vform_half, zm_b, zm);2631pack_odd_elements(vform_half, zm_t, zm);26322633switch (form_hash_) {2634case "saddwb_z_zz"_h:2635saddw(vform, zd, zn, zm_b);2636break;2637case "saddwt_z_zz"_h:2638saddw(vform, zd, zn, zm_t);2639break;2640case "ssubwb_z_zz"_h:2641ssubw(vform, zd, zn, zm_b);2642break;2643case "ssubwt_z_zz"_h:2644ssubw(vform, zd, zn, zm_t);2645break;2646case "uaddwb_z_zz"_h:2647uaddw(vform, zd, zn, zm_b);2648break;2649case "uaddwt_z_zz"_h:2650uaddw(vform, zd, zn, zm_t);2651break;2652case "usubwb_z_zz"_h:2653usubw(vform, zd, zn, zm_b);2654break;2655case "usubwt_z_zz"_h:2656usubw(vform, zd, zn, zm_t);2657break;2658default:2659VIXL_UNIMPLEMENTED();2660}2661}26622663void Simulator::Simulate_ZdT_ZnT_const(const Instruction* instr) {2664SimVRegister& zd = ReadVRegister(instr->GetRd());2665SimVRegister& zn = ReadVRegister(instr->GetRn());26662667std::pair<int, int> shift_and_lane_size =2668instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);2669int lane_size = shift_and_lane_size.second;2670VIXL_ASSERT((lane_size >= 0) &&2671(static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));2672VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);2673int shift_dist = shift_and_lane_size.first;26742675switch (form_hash_) {2676case "sli_z_zzi"_h:2677// Shift distance is computed differently for left shifts. Convert the2678// result.2679shift_dist = (8 << lane_size) - shift_dist;2680sli(vform, zd, zn, shift_dist);2681break;2682case "sri_z_zzi"_h:2683sri(vform, zd, zn, shift_dist);2684break;2685default:2686VIXL_UNIMPLEMENTED();2687}2688}26892690void Simulator::SimulateSVENarrow(const Instruction* instr) {2691SimVRegister& zd = ReadVRegister(instr->GetRd());2692SimVRegister& zn = ReadVRegister(instr->GetRn());2693SimVRegister result;26942695std::pair<int, int> shift_and_lane_size =2696instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);2697int lane_size = shift_and_lane_size.second;2698VIXL_ASSERT((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&2699(lane_size <= static_cast<int>(kSRegSizeInBytesLog2)));2700VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);2701int right_shift_dist = shift_and_lane_size.first;2702bool top = false;27032704switch (form_hash_) {2705case "sqxtnt_z_zz"_h:2706top = true;2707VIXL_FALLTHROUGH();2708case "sqxtnb_z_zz"_h:2709sqxtn(vform, result, zn);2710break;2711case "sqxtunt_z_zz"_h:2712top = true;2713VIXL_FALLTHROUGH();2714case "sqxtunb_z_zz"_h:2715sqxtun(vform, result, zn);2716break;2717case "uqxtnt_z_zz"_h:2718top = true;2719VIXL_FALLTHROUGH();2720case "uqxtnb_z_zz"_h:2721uqxtn(vform, result, zn);2722break;2723case "rshrnt_z_zi"_h:2724top = true;2725VIXL_FALLTHROUGH();2726case "rshrnb_z_zi"_h:2727rshrn(vform, result, zn, right_shift_dist);2728break;2729case "shrnt_z_zi"_h:2730top = true;2731VIXL_FALLTHROUGH();2732case "shrnb_z_zi"_h:2733shrn(vform, result, zn, right_shift_dist);2734break;2735case "sqrshrnt_z_zi"_h:2736top = true;2737VIXL_FALLTHROUGH();2738case "sqrshrnb_z_zi"_h:2739sqrshrn(vform, result, zn, right_shift_dist);2740break;2741case "sqrshrunt_z_zi"_h:2742top = true;2743VIXL_FALLTHROUGH();2744case "sqrshrunb_z_zi"_h:2745sqrshrun(vform, result, zn, right_shift_dist);2746break;2747case "sqshrnt_z_zi"_h:2748top = true;2749VIXL_FALLTHROUGH();2750case "sqshrnb_z_zi"_h:2751sqshrn(vform, result, zn, right_shift_dist);2752break;2753case "sqshrunt_z_zi"_h:2754top = true;2755VIXL_FALLTHROUGH();2756case "sqshrunb_z_zi"_h:2757sqshrun(vform, result, zn, right_shift_dist);2758break;2759case "uqrshrnt_z_zi"_h:2760top = true;2761VIXL_FALLTHROUGH();2762case "uqrshrnb_z_zi"_h:2763uqrshrn(vform, result, zn, right_shift_dist);2764break;2765case "uqshrnt_z_zi"_h:2766top = true;2767VIXL_FALLTHROUGH();2768case "uqshrnb_z_zi"_h:2769uqshrn(vform, result, zn, right_shift_dist);2770break;2771default:2772VIXL_UNIMPLEMENTED();2773}27742775if (top) {2776// Keep even elements, replace odd elements with the results.2777xtn(vform, zd, zd);2778zip1(vform, zd, zd, result);2779} else {2780// Zero odd elements, replace even elements with the results.2781SimVRegister zero;2782zero.Clear();2783zip1(vform, zd, result, zero);2784}2785}27862787void Simulator::SimulateSVEInterleavedArithLong(const Instruction* instr) {2788VectorFormat vform = instr->GetSVEVectorFormat();2789SimVRegister& zd = ReadVRegister(instr->GetRd());2790SimVRegister& zm = ReadVRegister(instr->GetRm());2791SimVRegister& zn = ReadVRegister(instr->GetRn());2792SimVRegister temp, zn_b, zm_b, zn_t, zm_t;27932794// Construct temporary registers containing the even (bottom) and odd (top)2795// elements.2796VectorFormat vform_half = VectorFormatHalfWidth(vform);2797pack_even_elements(vform_half, zn_b, zn);2798pack_even_elements(vform_half, zm_b, zm);2799pack_odd_elements(vform_half, zn_t, zn);2800pack_odd_elements(vform_half, zm_t, zm);28012802switch (form_hash_) {2803case "sabdlb_z_zz"_h:2804sabdl(vform, zd, zn_b, zm_b);2805break;2806case "sabdlt_z_zz"_h:2807sabdl(vform, zd, zn_t, zm_t);2808break;2809case "saddlb_z_zz"_h:2810saddl(vform, zd, zn_b, zm_b);2811break;2812case "saddlbt_z_zz"_h:2813saddl(vform, zd, zn_b, zm_t);2814break;2815case "saddlt_z_zz"_h:2816saddl(vform, zd, zn_t, zm_t);2817break;2818case "ssublb_z_zz"_h:2819ssubl(vform, zd, zn_b, zm_b);2820break;2821case "ssublbt_z_zz"_h:2822ssubl(vform, zd, zn_b, zm_t);2823break;2824case "ssublt_z_zz"_h:2825ssubl(vform, zd, zn_t, zm_t);2826break;2827case "ssubltb_z_zz"_h:2828ssubl(vform, zd, zn_t, zm_b);2829break;2830case "uabdlb_z_zz"_h:2831uabdl(vform, zd, zn_b, zm_b);2832break;2833case "uabdlt_z_zz"_h:2834uabdl(vform, zd, zn_t, zm_t);2835break;2836case "uaddlb_z_zz"_h:2837uaddl(vform, zd, zn_b, zm_b);2838break;2839case "uaddlt_z_zz"_h:2840uaddl(vform, zd, zn_t, zm_t);2841break;2842case "usublb_z_zz"_h:2843usubl(vform, zd, zn_b, zm_b);2844break;2845case "usublt_z_zz"_h:2846usubl(vform, zd, zn_t, zm_t);2847break;2848case "sabalb_z_zzz"_h:2849sabal(vform, zd, zn_b, zm_b);2850break;2851case "sabalt_z_zzz"_h:2852sabal(vform, zd, zn_t, zm_t);2853break;2854case "uabalb_z_zzz"_h:2855uabal(vform, zd, zn_b, zm_b);2856break;2857case "uabalt_z_zzz"_h:2858uabal(vform, zd, zn_t, zm_t);2859break;2860default:2861VIXL_UNIMPLEMENTED();2862}2863}28642865void Simulator::SimulateSVEIntMulLongVec(const Instruction* instr) {2866VectorFormat vform = instr->GetSVEVectorFormat();2867SimVRegister& zd = ReadVRegister(instr->GetRd());2868SimVRegister& zm = ReadVRegister(instr->GetRm());2869SimVRegister& zn = ReadVRegister(instr->GetRn());2870SimVRegister temp, zn_b, zm_b, zn_t, zm_t;2871VectorFormat vform_half = VectorFormatHalfWidth(vform);2872pack_even_elements(vform_half, zn_b, zn);2873pack_even_elements(vform_half, zm_b, zm);2874pack_odd_elements(vform_half, zn_t, zn);2875pack_odd_elements(vform_half, zm_t, zm);28762877switch (form_hash_) {2878case "pmullb_z_zz"_h:2879// '00' is reserved for Q-sized lane.2880if (vform == kFormatVnB) {2881VIXL_UNIMPLEMENTED();2882}2883pmull(vform, zd, zn_b, zm_b);2884break;2885case "pmullt_z_zz"_h:2886// '00' is reserved for Q-sized lane.2887if (vform == kFormatVnB) {2888VIXL_UNIMPLEMENTED();2889}2890pmull(vform, zd, zn_t, zm_t);2891break;2892case "smullb_z_zz"_h:2893smull(vform, zd, zn_b, zm_b);2894break;2895case "smullt_z_zz"_h:2896smull(vform, zd, zn_t, zm_t);2897break;2898case "sqdmullb_z_zz"_h:2899sqdmull(vform, zd, zn_b, zm_b);2900break;2901case "sqdmullt_z_zz"_h:2902sqdmull(vform, zd, zn_t, zm_t);2903break;2904case "umullb_z_zz"_h:2905umull(vform, zd, zn_b, zm_b);2906break;2907case "umullt_z_zz"_h:2908umull(vform, zd, zn_t, zm_t);2909break;2910default:2911VIXL_UNIMPLEMENTED();2912}2913}29142915void Simulator::SimulateSVEAddSubHigh(const Instruction* instr) {2916SimVRegister& zd = ReadVRegister(instr->GetRd());2917SimVRegister& zm = ReadVRegister(instr->GetRm());2918SimVRegister& zn = ReadVRegister(instr->GetRn());2919SimVRegister result;2920bool top = false;29212922VectorFormat vform_src = instr->GetSVEVectorFormat();2923if (vform_src == kFormatVnB) {2924VIXL_UNIMPLEMENTED();2925}2926VectorFormat vform = VectorFormatHalfWidth(vform_src);29272928switch (form_hash_) {2929case "addhnt_z_zz"_h:2930top = true;2931VIXL_FALLTHROUGH();2932case "addhnb_z_zz"_h:2933addhn(vform, result, zn, zm);2934break;2935case "raddhnt_z_zz"_h:2936top = true;2937VIXL_FALLTHROUGH();2938case "raddhnb_z_zz"_h:2939raddhn(vform, result, zn, zm);2940break;2941case "rsubhnt_z_zz"_h:2942top = true;2943VIXL_FALLTHROUGH();2944case "rsubhnb_z_zz"_h:2945rsubhn(vform, result, zn, zm);2946break;2947case "subhnt_z_zz"_h:2948top = true;2949VIXL_FALLTHROUGH();2950case "subhnb_z_zz"_h:2951subhn(vform, result, zn, zm);2952break;2953default:2954VIXL_UNIMPLEMENTED();2955}29562957if (top) {2958// Keep even elements, replace odd elements with the results.2959xtn(vform, zd, zd);2960zip1(vform, zd, zd, result);2961} else {2962// Zero odd elements, replace even elements with the results.2963SimVRegister zero;2964zero.Clear();2965zip1(vform, zd, result, zero);2966}2967}29682969void Simulator::SimulateSVEShiftLeftImm(const Instruction* instr) {2970SimVRegister& zd = ReadVRegister(instr->GetRd());2971SimVRegister& zn = ReadVRegister(instr->GetRn());2972SimVRegister zn_b, zn_t;29732974std::pair<int, int> shift_and_lane_size =2975instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);2976int lane_size = shift_and_lane_size.second;2977VIXL_ASSERT((lane_size >= 0) &&2978(static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));2979VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size + 1);2980int right_shift_dist = shift_and_lane_size.first;2981int left_shift_dist = (8 << lane_size) - right_shift_dist;29822983// Construct temporary registers containing the even (bottom) and odd (top)2984// elements.2985VectorFormat vform_half = VectorFormatHalfWidth(vform);2986pack_even_elements(vform_half, zn_b, zn);2987pack_odd_elements(vform_half, zn_t, zn);29882989switch (form_hash_) {2990case "sshllb_z_zi"_h:2991sshll(vform, zd, zn_b, left_shift_dist);2992break;2993case "sshllt_z_zi"_h:2994sshll(vform, zd, zn_t, left_shift_dist);2995break;2996case "ushllb_z_zi"_h:2997ushll(vform, zd, zn_b, left_shift_dist);2998break;2999case "ushllt_z_zi"_h:3000ushll(vform, zd, zn_t, left_shift_dist);3001break;3002default:3003VIXL_UNIMPLEMENTED();3004}3005}30063007void Simulator::SimulateSVESaturatingMulAddHigh(const Instruction* instr) {3008VectorFormat vform = instr->GetSVEVectorFormat();3009SimVRegister& zda = ReadVRegister(instr->GetRd());3010SimVRegister& zn = ReadVRegister(instr->GetRn());3011unsigned zm_code = instr->GetRm();3012int index = -1;3013bool is_mla = false;30143015switch (form_hash_) {3016case "sqrdmlah_z_zzz"_h:3017is_mla = true;3018VIXL_FALLTHROUGH();3019case "sqrdmlsh_z_zzz"_h:3020// Nothing to do.3021break;3022case "sqrdmlah_z_zzzi_h"_h:3023is_mla = true;3024VIXL_FALLTHROUGH();3025case "sqrdmlsh_z_zzzi_h"_h:3026vform = kFormatVnH;3027index = (instr->ExtractBit(22) << 2) | instr->ExtractBits(20, 19);3028zm_code = instr->ExtractBits(18, 16);3029break;3030case "sqrdmlah_z_zzzi_s"_h:3031is_mla = true;3032VIXL_FALLTHROUGH();3033case "sqrdmlsh_z_zzzi_s"_h:3034vform = kFormatVnS;3035index = instr->ExtractBits(20, 19);3036zm_code = instr->ExtractBits(18, 16);3037break;3038case "sqrdmlah_z_zzzi_d"_h:3039is_mla = true;3040VIXL_FALLTHROUGH();3041case "sqrdmlsh_z_zzzi_d"_h:3042vform = kFormatVnD;3043index = instr->ExtractBit(20);3044zm_code = instr->ExtractBits(19, 16);3045break;3046default:3047VIXL_UNIMPLEMENTED();3048}30493050SimVRegister& zm = ReadVRegister(zm_code);3051SimVRegister zm_idx;3052if (index >= 0) {3053dup_elements_to_segments(vform, zm_idx, zm, index);3054}30553056if (is_mla) {3057sqrdmlah(vform, zda, zn, (index >= 0) ? zm_idx : zm);3058} else {3059sqrdmlsh(vform, zda, zn, (index >= 0) ? zm_idx : zm);3060}3061}30623063void Simulator::Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr) {3064SimVRegister& zda = ReadVRegister(instr->GetRd());3065SimVRegister& zn = ReadVRegister(instr->GetRn());3066SimVRegister& zm = ReadVRegister(instr->ExtractBits(19, 16));30673068SimVRegister temp, zm_idx, zn_b, zn_t;3069Instr index = (instr->ExtractBit(20) << 1) | instr->ExtractBit(11);3070dup_elements_to_segments(kFormatVnS, temp, zm, index);3071pack_even_elements(kFormatVnS, zm_idx, temp);3072pack_even_elements(kFormatVnS, zn_b, zn);3073pack_odd_elements(kFormatVnS, zn_t, zn);30743075switch (form_hash_) {3076case "sqdmlalb_z_zzzi_d"_h:3077sqdmlal(kFormatVnD, zda, zn_b, zm_idx);3078break;3079case "sqdmlalt_z_zzzi_d"_h:3080sqdmlal(kFormatVnD, zda, zn_t, zm_idx);3081break;3082case "sqdmlslb_z_zzzi_d"_h:3083sqdmlsl(kFormatVnD, zda, zn_b, zm_idx);3084break;3085case "sqdmlslt_z_zzzi_d"_h:3086sqdmlsl(kFormatVnD, zda, zn_t, zm_idx);3087break;3088default:3089VIXL_UNIMPLEMENTED();3090}3091}30923093void Simulator::Simulate_ZdaS_ZnH_ZmH(const Instruction* instr) {3094SimVRegister& zda = ReadVRegister(instr->GetRd());3095SimVRegister& zm = ReadVRegister(instr->GetRm());3096SimVRegister& zn = ReadVRegister(instr->GetRn());30973098SimVRegister temp, zn_b, zm_b, zn_t, zm_t;3099pack_even_elements(kFormatVnH, zn_b, zn);3100pack_even_elements(kFormatVnH, zm_b, zm);3101pack_odd_elements(kFormatVnH, zn_t, zn);3102pack_odd_elements(kFormatVnH, zm_t, zm);31033104switch (form_hash_) {3105case "fmlalb_z_zzz"_h:3106fmlal(kFormatVnS, zda, zn_b, zm_b);3107break;3108case "fmlalt_z_zzz"_h:3109fmlal(kFormatVnS, zda, zn_t, zm_t);3110break;3111case "fmlslb_z_zzz"_h:3112fmlsl(kFormatVnS, zda, zn_b, zm_b);3113break;3114case "fmlslt_z_zzz"_h:3115fmlsl(kFormatVnS, zda, zn_t, zm_t);3116break;3117default:3118VIXL_UNIMPLEMENTED();3119}3120}31213122void Simulator::Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr) {3123SimVRegister& zda = ReadVRegister(instr->GetRd());3124SimVRegister& zn = ReadVRegister(instr->GetRn());3125SimVRegister& zm = ReadVRegister(instr->ExtractBits(18, 16));31263127SimVRegister temp, zm_idx, zn_b, zn_t;3128Instr index = (instr->ExtractBits(20, 19) << 1) | instr->ExtractBit(11);3129dup_elements_to_segments(kFormatVnH, temp, zm, index);3130pack_even_elements(kFormatVnH, zm_idx, temp);3131pack_even_elements(kFormatVnH, zn_b, zn);3132pack_odd_elements(kFormatVnH, zn_t, zn);31333134switch (form_hash_) {3135case "fmlalb_z_zzzi_s"_h:3136fmlal(kFormatVnS, zda, zn_b, zm_idx);3137break;3138case "fmlalt_z_zzzi_s"_h:3139fmlal(kFormatVnS, zda, zn_t, zm_idx);3140break;3141case "fmlslb_z_zzzi_s"_h:3142fmlsl(kFormatVnS, zda, zn_b, zm_idx);3143break;3144case "fmlslt_z_zzzi_s"_h:3145fmlsl(kFormatVnS, zda, zn_t, zm_idx);3146break;3147case "sqdmlalb_z_zzzi_s"_h:3148sqdmlal(kFormatVnS, zda, zn_b, zm_idx);3149break;3150case "sqdmlalt_z_zzzi_s"_h:3151sqdmlal(kFormatVnS, zda, zn_t, zm_idx);3152break;3153case "sqdmlslb_z_zzzi_s"_h:3154sqdmlsl(kFormatVnS, zda, zn_b, zm_idx);3155break;3156case "sqdmlslt_z_zzzi_s"_h:3157sqdmlsl(kFormatVnS, zda, zn_t, zm_idx);3158break;3159default:3160VIXL_UNIMPLEMENTED();3161}3162}31633164void Simulator::Simulate_ZdaT_PgM_ZnTb(const Instruction* instr) {3165VectorFormat vform = instr->GetSVEVectorFormat();3166SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3167SimVRegister& zda = ReadVRegister(instr->GetRd());3168SimVRegister& zn = ReadVRegister(instr->GetRn());3169SimVRegister result;31703171switch (form_hash_) {3172case "sadalp_z_p_z"_h:3173sadalp(vform, result, zn);3174break;3175case "uadalp_z_p_z"_h:3176uadalp(vform, result, zn);3177break;3178default:3179VIXL_UNIMPLEMENTED();3180}3181mov_merging(vform, zda, pg, result);3182}31833184void Simulator::SimulateSVEAddSubCarry(const Instruction* instr) {3185VectorFormat vform = (instr->ExtractBit(22) == 0) ? kFormatVnS : kFormatVnD;3186SimVRegister& zda = ReadVRegister(instr->GetRd());3187SimVRegister& zm = ReadVRegister(instr->GetRm());3188SimVRegister& zn = ReadVRegister(instr->GetRn());31893190SimVRegister not_zn;3191not_(vform, not_zn, zn);31923193switch (form_hash_) {3194case "adclb_z_zzz"_h:3195adcl(vform, zda, zn, zm, /* top = */ false);3196break;3197case "adclt_z_zzz"_h:3198adcl(vform, zda, zn, zm, /* top = */ true);3199break;3200case "sbclb_z_zzz"_h:3201adcl(vform, zda, not_zn, zm, /* top = */ false);3202break;3203case "sbclt_z_zzz"_h:3204adcl(vform, zda, not_zn, zm, /* top = */ true);3205break;3206default:3207VIXL_UNIMPLEMENTED();3208}3209}32103211void Simulator::Simulate_ZdaT_ZnT_ZmT(const Instruction* instr) {3212VectorFormat vform = instr->GetSVEVectorFormat();3213SimVRegister& zda = ReadVRegister(instr->GetRd());3214SimVRegister& zm = ReadVRegister(instr->GetRm());3215SimVRegister& zn = ReadVRegister(instr->GetRn());32163217switch (form_hash_) {3218case "saba_z_zzz"_h:3219saba(vform, zda, zn, zm);3220break;3221case "uaba_z_zzz"_h:3222uaba(vform, zda, zn, zm);3223break;3224default:3225VIXL_UNIMPLEMENTED();3226}3227}32283229void Simulator::SimulateSVEComplexIntMulAdd(const Instruction* instr) {3230SimVRegister& zda = ReadVRegister(instr->GetRd());3231SimVRegister& zn = ReadVRegister(instr->GetRn());3232int rot = instr->ExtractBits(11, 10) * 90;3233// vform and zm are only valid for the vector form of instruction.3234VectorFormat vform = instr->GetSVEVectorFormat();3235SimVRegister& zm = ReadVRegister(instr->GetRm());32363237// Inputs for indexed form of instruction.3238SimVRegister& zm_h = ReadVRegister(instr->ExtractBits(18, 16));3239SimVRegister& zm_s = ReadVRegister(instr->ExtractBits(19, 16));3240int idx_h = instr->ExtractBits(20, 19);3241int idx_s = instr->ExtractBit(20);32423243switch (form_hash_) {3244case "cmla_z_zzz"_h:3245cmla(vform, zda, zda, zn, zm, rot);3246break;3247case "cmla_z_zzzi_h"_h:3248cmla(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot);3249break;3250case "cmla_z_zzzi_s"_h:3251cmla(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot);3252break;3253case "sqrdcmlah_z_zzz"_h:3254sqrdcmlah(vform, zda, zda, zn, zm, rot);3255break;3256case "sqrdcmlah_z_zzzi_h"_h:3257sqrdcmlah(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot);3258break;3259case "sqrdcmlah_z_zzzi_s"_h:3260sqrdcmlah(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot);3261break;3262default:3263VIXL_UNIMPLEMENTED();3264}3265}32663267void Simulator::Simulate_ZdaT_ZnT_const(const Instruction* instr) {3268SimVRegister& zd = ReadVRegister(instr->GetRd());3269SimVRegister& zn = ReadVRegister(instr->GetRn());32703271std::pair<int, int> shift_and_lane_size =3272instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);3273int lane_size = shift_and_lane_size.second;3274VIXL_ASSERT((lane_size >= 0) &&3275(static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));3276VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);3277int shift_dist = shift_and_lane_size.first;32783279switch (form_hash_) {3280case "srsra_z_zi"_h:3281srsra(vform, zd, zn, shift_dist);3282break;3283case "ssra_z_zi"_h:3284ssra(vform, zd, zn, shift_dist);3285break;3286case "ursra_z_zi"_h:3287ursra(vform, zd, zn, shift_dist);3288break;3289case "usra_z_zi"_h:3290usra(vform, zd, zn, shift_dist);3291break;3292default:3293VIXL_UNIMPLEMENTED();3294}3295}32963297void Simulator::Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr) {3298VectorFormat vform = instr->GetSVEVectorFormat();3299SimVRegister& zda = ReadVRegister(instr->GetRd());3300SimVRegister& zm = ReadVRegister(instr->GetRm());3301SimVRegister& zn = ReadVRegister(instr->GetRn());33023303SimVRegister zero, zn_b, zm_b, zn_t, zm_t;3304zero.Clear();33053306VectorFormat vform_half = VectorFormatHalfWidth(vform);3307uzp1(vform_half, zn_b, zn, zero);3308uzp1(vform_half, zm_b, zm, zero);3309uzp2(vform_half, zn_t, zn, zero);3310uzp2(vform_half, zm_t, zm, zero);33113312switch (form_hash_) {3313case "smlalb_z_zzz"_h:3314smlal(vform, zda, zn_b, zm_b);3315break;3316case "smlalt_z_zzz"_h:3317smlal(vform, zda, zn_t, zm_t);3318break;3319case "smlslb_z_zzz"_h:3320smlsl(vform, zda, zn_b, zm_b);3321break;3322case "smlslt_z_zzz"_h:3323smlsl(vform, zda, zn_t, zm_t);3324break;3325case "sqdmlalb_z_zzz"_h:3326sqdmlal(vform, zda, zn_b, zm_b);3327break;3328case "sqdmlalbt_z_zzz"_h:3329sqdmlal(vform, zda, zn_b, zm_t);3330break;3331case "sqdmlalt_z_zzz"_h:3332sqdmlal(vform, zda, zn_t, zm_t);3333break;3334case "sqdmlslb_z_zzz"_h:3335sqdmlsl(vform, zda, zn_b, zm_b);3336break;3337case "sqdmlslbt_z_zzz"_h:3338sqdmlsl(vform, zda, zn_b, zm_t);3339break;3340case "sqdmlslt_z_zzz"_h:3341sqdmlsl(vform, zda, zn_t, zm_t);3342break;3343case "umlalb_z_zzz"_h:3344umlal(vform, zda, zn_b, zm_b);3345break;3346case "umlalt_z_zzz"_h:3347umlal(vform, zda, zn_t, zm_t);3348break;3349case "umlslb_z_zzz"_h:3350umlsl(vform, zda, zn_b, zm_b);3351break;3352case "umlslt_z_zzz"_h:3353umlsl(vform, zda, zn_t, zm_t);3354break;3355default:3356VIXL_UNIMPLEMENTED();3357}3358}33593360void Simulator::SimulateSVEComplexDotProduct(const Instruction* instr) {3361VectorFormat vform = instr->GetSVEVectorFormat();3362SimVRegister& zda = ReadVRegister(instr->GetRd());3363SimVRegister& zn = ReadVRegister(instr->GetRn());3364int rot = instr->ExtractBits(11, 10) * 90;3365unsigned zm_code = instr->GetRm();3366int index = -1;33673368switch (form_hash_) {3369case "cdot_z_zzz"_h:3370// Nothing to do.3371break;3372case "cdot_z_zzzi_s"_h:3373index = zm_code >> 3;3374zm_code &= 0x7;3375break;3376case "cdot_z_zzzi_d"_h:3377index = zm_code >> 4;3378zm_code &= 0xf;3379break;3380default:3381VIXL_UNIMPLEMENTED();3382}33833384SimVRegister temp;3385SimVRegister& zm = ReadVRegister(zm_code);3386if (index >= 0) dup_elements_to_segments(vform, temp, zm, index);3387cdot(vform, zda, zda, zn, (index >= 0) ? temp : zm, rot);3388}33893390void Simulator::SimulateSVEBitwiseTernary(const Instruction* instr) {3391VectorFormat vform = kFormatVnD;3392SimVRegister& zdn = ReadVRegister(instr->GetRd());3393SimVRegister& zm = ReadVRegister(instr->GetRm());3394SimVRegister& zk = ReadVRegister(instr->GetRn());3395SimVRegister temp;33963397switch (form_hash_) {3398case "bcax_z_zzz"_h:3399bic(vform, temp, zm, zk);3400eor(vform, zdn, temp, zdn);3401break;3402case "bsl1n_z_zzz"_h:3403not_(vform, temp, zdn);3404bsl(vform, zdn, zk, temp, zm);3405break;3406case "bsl2n_z_zzz"_h:3407not_(vform, temp, zm);3408bsl(vform, zdn, zk, zdn, temp);3409break;3410case "bsl_z_zzz"_h:3411bsl(vform, zdn, zk, zdn, zm);3412break;3413case "eor3_z_zzz"_h:3414eor(vform, temp, zdn, zm);3415eor(vform, zdn, temp, zk);3416break;3417case "nbsl_z_zzz"_h:3418bsl(vform, zdn, zk, zdn, zm);3419not_(vform, zdn, zdn);3420break;3421default:3422VIXL_UNIMPLEMENTED();3423}3424}34253426void Simulator::SimulateSVEHalvingAddSub(const Instruction* instr) {3427VectorFormat vform = instr->GetSVEVectorFormat();3428SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3429SimVRegister& zdn = ReadVRegister(instr->GetRd());3430SimVRegister& zm = ReadVRegister(instr->GetRn());3431SimVRegister result;34323433switch (form_hash_) {3434case "shadd_z_p_zz"_h:3435add(vform, result, zdn, zm).Halve(vform);3436break;3437case "shsub_z_p_zz"_h:3438sub(vform, result, zdn, zm).Halve(vform);3439break;3440case "shsubr_z_p_zz"_h:3441sub(vform, result, zm, zdn).Halve(vform);3442break;3443case "srhadd_z_p_zz"_h:3444add(vform, result, zdn, zm).Halve(vform).Round(vform);3445break;3446case "uhadd_z_p_zz"_h:3447add(vform, result, zdn, zm).Uhalve(vform);3448break;3449case "uhsub_z_p_zz"_h:3450sub(vform, result, zdn, zm).Uhalve(vform);3451break;3452case "uhsubr_z_p_zz"_h:3453sub(vform, result, zm, zdn).Uhalve(vform);3454break;3455case "urhadd_z_p_zz"_h:3456add(vform, result, zdn, zm).Uhalve(vform).Round(vform);3457break;3458default:3459VIXL_UNIMPLEMENTED();3460break;3461}3462mov_merging(vform, zdn, pg, result);3463}34643465void Simulator::SimulateSVESaturatingArithmetic(const Instruction* instr) {3466VectorFormat vform = instr->GetSVEVectorFormat();3467SimVRegister& zdn = ReadVRegister(instr->GetRd());3468SimVRegister& zm = ReadVRegister(instr->GetRn());3469SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3470SimVRegister result;34713472switch (form_hash_) {3473case "sqadd_z_p_zz"_h:3474add(vform, result, zdn, zm).SignedSaturate(vform);3475break;3476case "sqsub_z_p_zz"_h:3477sub(vform, result, zdn, zm).SignedSaturate(vform);3478break;3479case "sqsubr_z_p_zz"_h:3480sub(vform, result, zm, zdn).SignedSaturate(vform);3481break;3482case "suqadd_z_p_zz"_h:3483suqadd(vform, result, zdn, zm);3484break;3485case "uqadd_z_p_zz"_h:3486add(vform, result, zdn, zm).UnsignedSaturate(vform);3487break;3488case "uqsub_z_p_zz"_h:3489sub(vform, result, zdn, zm).UnsignedSaturate(vform);3490break;3491case "uqsubr_z_p_zz"_h:3492sub(vform, result, zm, zdn).UnsignedSaturate(vform);3493break;3494case "usqadd_z_p_zz"_h:3495usqadd(vform, result, zdn, zm);3496break;3497default:3498VIXL_UNIMPLEMENTED();3499break;3500}3501mov_merging(vform, zdn, pg, result);3502}35033504void Simulator::SimulateSVEIntArithPair(const Instruction* instr) {3505VectorFormat vform = instr->GetSVEVectorFormat();3506SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3507SimVRegister& zdn = ReadVRegister(instr->GetRd());3508SimVRegister& zm = ReadVRegister(instr->GetRn());3509SimVRegister result;35103511switch (form_hash_) {3512case "addp_z_p_zz"_h:3513addp(vform, result, zdn, zm);3514break;3515case "smaxp_z_p_zz"_h:3516smaxp(vform, result, zdn, zm);3517break;3518case "sminp_z_p_zz"_h:3519sminp(vform, result, zdn, zm);3520break;3521case "umaxp_z_p_zz"_h:3522umaxp(vform, result, zdn, zm);3523break;3524case "uminp_z_p_zz"_h:3525uminp(vform, result, zdn, zm);3526break;3527default:3528VIXL_UNIMPLEMENTED();3529break;3530}3531mov_merging(vform, zdn, pg, result);3532}35333534void Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr) {3535VectorFormat vform = instr->GetSVEVectorFormat();3536SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3537SimVRegister& zdn = ReadVRegister(instr->GetRd());3538SimVRegister& zm = ReadVRegister(instr->GetRn());3539SimVRegister result;35403541switch (form_hash_) {3542case "faddp_z_p_zz"_h:3543faddp(vform, result, zdn, zm);3544break;3545case "fmaxnmp_z_p_zz"_h:3546fmaxnmp(vform, result, zdn, zm);3547break;3548case "fmaxp_z_p_zz"_h:3549fmaxp(vform, result, zdn, zm);3550break;3551case "fminnmp_z_p_zz"_h:3552fminnmp(vform, result, zdn, zm);3553break;3554case "fminp_z_p_zz"_h:3555fminp(vform, result, zdn, zm);3556break;3557default:3558VIXL_UNIMPLEMENTED();3559}3560mov_merging(vform, zdn, pg, result);3561}35623563void Simulator::Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr) {3564SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3565SimVRegister& zdn = ReadVRegister(instr->GetRd());35663567std::pair<int, int> shift_and_lane_size =3568instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);3569unsigned lane_size = shift_and_lane_size.second;3570VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);3571int right_shift_dist = shift_and_lane_size.first;3572int left_shift_dist = (8 << lane_size) - right_shift_dist;3573SimVRegister result;35743575switch (form_hash_) {3576case "sqshl_z_p_zi"_h:3577sqshl(vform, result, zdn, left_shift_dist);3578break;3579case "sqshlu_z_p_zi"_h:3580sqshlu(vform, result, zdn, left_shift_dist);3581break;3582case "srshr_z_p_zi"_h:3583sshr(vform, result, zdn, right_shift_dist).Round(vform);3584break;3585case "uqshl_z_p_zi"_h:3586uqshl(vform, result, zdn, left_shift_dist);3587break;3588case "urshr_z_p_zi"_h:3589ushr(vform, result, zdn, right_shift_dist).Round(vform);3590break;3591default:3592VIXL_UNIMPLEMENTED();3593}3594mov_merging(vform, zdn, pg, result);3595}35963597void Simulator::SimulateSVEExclusiveOrRotate(const Instruction* instr) {3598VIXL_ASSERT(form_hash_ == "xar_z_zzi"_h);35993600SimVRegister& zdn = ReadVRegister(instr->GetRd());3601SimVRegister& zm = ReadVRegister(instr->GetRn());36023603std::pair<int, int> shift_and_lane_size =3604instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);3605unsigned lane_size = shift_and_lane_size.second;3606VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);3607VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);3608int shift_dist = shift_and_lane_size.first;3609eor(vform, zdn, zdn, zm);3610ror(vform, zdn, zdn, shift_dist);3611}36123613void Simulator::Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr) {3614VectorFormat vform = instr->GetSVEVectorFormat();3615SimVRegister& zdn = ReadVRegister(instr->GetRd());3616SimVRegister& zm = ReadVRegister(instr->GetRn());3617int rot = (instr->ExtractBit(10) == 0) ? 90 : 270;36183619switch (form_hash_) {3620case "cadd_z_zz"_h:3621cadd(vform, zdn, zdn, zm, rot);3622break;3623case "sqcadd_z_zz"_h:3624cadd(vform, zdn, zdn, zm, rot, /* saturate = */ true);3625break;3626default:3627VIXL_UNIMPLEMENTED();3628}3629}36303631void Simulator::Simulate_ZtD_PgZ_ZnD_Xm(const Instruction* instr) {3632SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3633SimVRegister& zn = ReadVRegister(instr->GetRn());3634uint64_t xm = ReadXRegister(instr->GetRm());36353636LogicSVEAddressVector addr(xm, &zn, kFormatVnD);3637int msize = -1;3638bool is_signed = false;36393640switch (form_hash_) {3641case "ldnt1b_z_p_ar_d_64_unscaled"_h:3642msize = 0;3643break;3644case "ldnt1d_z_p_ar_d_64_unscaled"_h:3645msize = 3;3646break;3647case "ldnt1h_z_p_ar_d_64_unscaled"_h:3648msize = 1;3649break;3650case "ldnt1sb_z_p_ar_d_64_unscaled"_h:3651msize = 0;3652is_signed = true;3653break;3654case "ldnt1sh_z_p_ar_d_64_unscaled"_h:3655msize = 1;3656is_signed = true;3657break;3658case "ldnt1sw_z_p_ar_d_64_unscaled"_h:3659msize = 2;3660is_signed = true;3661break;3662case "ldnt1w_z_p_ar_d_64_unscaled"_h:3663msize = 2;3664break;3665default:3666VIXL_UNIMPLEMENTED();3667}3668addr.SetMsizeInBytesLog2(msize);3669SVEStructuredLoadHelper(kFormatVnD, pg, instr->GetRt(), addr, is_signed);3670}36713672void Simulator::Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr) {3673SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3674SimVRegister& zn = ReadVRegister(instr->GetRn());3675uint64_t xm = ReadXRegister(instr->GetRm());36763677LogicSVEAddressVector addr(xm, &zn, kFormatVnD);3678VIXL_ASSERT((form_hash_ == "stnt1b_z_p_ar_d_64_unscaled"_h) ||3679(form_hash_ == "stnt1d_z_p_ar_d_64_unscaled"_h) ||3680(form_hash_ == "stnt1h_z_p_ar_d_64_unscaled"_h) ||3681(form_hash_ == "stnt1w_z_p_ar_d_64_unscaled"_h));36823683addr.SetMsizeInBytesLog2(3684instr->GetSVEMsizeFromDtype(/* is_signed = */ false));3685SVEStructuredStoreHelper(kFormatVnD, pg, instr->GetRt(), addr);3686}36873688void Simulator::Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr) {3689SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3690SimVRegister& zn = ReadVRegister(instr->GetRn());3691uint64_t xm = ReadXRegister(instr->GetRm());36923693LogicSVEAddressVector addr(xm, &zn, kFormatVnS);3694int msize = -1;3695bool is_signed = false;36963697switch (form_hash_) {3698case "ldnt1b_z_p_ar_s_x32_unscaled"_h:3699msize = 0;3700break;3701case "ldnt1h_z_p_ar_s_x32_unscaled"_h:3702msize = 1;3703break;3704case "ldnt1sb_z_p_ar_s_x32_unscaled"_h:3705msize = 0;3706is_signed = true;3707break;3708case "ldnt1sh_z_p_ar_s_x32_unscaled"_h:3709msize = 1;3710is_signed = true;3711break;3712case "ldnt1w_z_p_ar_s_x32_unscaled"_h:3713msize = 2;3714break;3715default:3716VIXL_UNIMPLEMENTED();3717}3718addr.SetMsizeInBytesLog2(msize);3719SVEStructuredLoadHelper(kFormatVnS, pg, instr->GetRt(), addr, is_signed);3720}37213722void Simulator::Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr) {3723SimPRegister& pg = ReadPRegister(instr->GetPgLow8());3724SimVRegister& zn = ReadVRegister(instr->GetRn());3725uint64_t xm = ReadXRegister(instr->GetRm());37263727LogicSVEAddressVector addr(xm, &zn, kFormatVnS);3728VIXL_ASSERT((form_hash_ == "stnt1b_z_p_ar_s_x32_unscaled"_h) ||3729(form_hash_ == "stnt1h_z_p_ar_s_x32_unscaled"_h) ||3730(form_hash_ == "stnt1w_z_p_ar_s_x32_unscaled"_h));37313732addr.SetMsizeInBytesLog2(3733instr->GetSVEMsizeFromDtype(/* is_signed = */ false));3734SVEStructuredStoreHelper(kFormatVnS, pg, instr->GetRt(), addr);3735}37363737void Simulator::VisitReserved(const Instruction* instr) {3738// UDF is the only instruction in this group, and the Decoder is precise here.3739VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);37403741printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",3742reinterpret_cast<const void*>(instr),3743instr->GetInstructionBits());3744VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");3745}374637473748void Simulator::VisitUnimplemented(const Instruction* instr) {3749printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",3750reinterpret_cast<const void*>(instr),3751instr->GetInstructionBits());3752VIXL_UNIMPLEMENTED();3753}375437553756void Simulator::VisitUnallocated(const Instruction* instr) {3757printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",3758reinterpret_cast<const void*>(instr),3759instr->GetInstructionBits());3760VIXL_UNIMPLEMENTED();3761}376237633764void Simulator::VisitPCRelAddressing(const Instruction* instr) {3765VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||3766(instr->Mask(PCRelAddressingMask) == ADRP));37673768WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());3769}377037713772void Simulator::VisitUnconditionalBranch(const Instruction* instr) {3773switch (instr->Mask(UnconditionalBranchMask)) {3774case BL:3775WriteLr(instr->GetNextInstruction());3776VIXL_FALLTHROUGH();3777case B:3778WritePc(instr->GetImmPCOffsetTarget());3779break;3780default:3781VIXL_UNREACHABLE();3782}3783}378437853786void Simulator::VisitConditionalBranch(const Instruction* instr) {3787VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);3788if (ConditionPassed(instr->GetConditionBranch())) {3789WritePc(instr->GetImmPCOffsetTarget());3790}3791}37923793BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {3794switch (instr->Mask(UnconditionalBranchToRegisterMask)) {3795case BLR:3796case BLRAA:3797case BLRAB:3798case BLRAAZ:3799case BLRABZ:3800return BranchAndLink;3801case BR:3802case BRAA:3803case BRAB:3804case BRAAZ:3805case BRABZ:3806if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||3807!PcIsInGuardedPage()) {3808return BranchFromUnguardedOrToIP;3809}3810return BranchFromGuardedNotToIP;3811}3812return DefaultBType;3813}38143815void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {3816bool authenticate = false;3817bool link = false;3818bool ret = false;3819uint64_t addr = ReadXRegister(instr->GetRn());3820uint64_t context = 0;38213822switch (instr->Mask(UnconditionalBranchToRegisterMask)) {3823case BLR:3824link = true;3825VIXL_FALLTHROUGH();3826case BR:3827break;38283829case BLRAAZ:3830case BLRABZ:3831link = true;3832VIXL_FALLTHROUGH();3833case BRAAZ:3834case BRABZ:3835authenticate = true;3836break;38373838case BLRAA:3839case BLRAB:3840link = true;3841VIXL_FALLTHROUGH();3842case BRAA:3843case BRAB:3844authenticate = true;3845context = ReadXRegister(instr->GetRd());3846break;38473848case RETAA:3849case RETAB:3850authenticate = true;3851addr = ReadXRegister(kLinkRegCode);3852context = ReadXRegister(31, Reg31IsStackPointer);3853VIXL_FALLTHROUGH();3854case RET:3855ret = true;3856break;3857default:3858VIXL_UNREACHABLE();3859}38603861if (link) {3862WriteLr(instr->GetNextInstruction());3863}38643865if (authenticate) {3866PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;3867addr = AuthPAC(addr, context, key, kInstructionPointer);38683869int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;3870if (((addr >> error_lsb) & 0x3) != 0x0) {3871VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");3872}3873}38743875if (!ret) {3876// Check for interceptions to the target address, if one is found, call it.3877MetaDataDepot::BranchInterceptionAbstract* interception =3878meta_data_.FindBranchInterception(addr);38793880if (interception != nullptr) {3881// Instead of writing the address of the function to the PC, call the3882// function's interception directly. We change the address that will be3883// branched to so that afterwards we continue execution from3884// the address in the LR. Note: the interception may modify the LR so3885// store it before calling the interception.3886addr = ReadRegister<uint64_t>(kLinkRegCode);3887(*interception)(this);3888}3889}38903891WriteNextBType(GetBTypeFromInstruction(instr));3892WritePc(Instruction::Cast(addr));3893}389438953896void Simulator::VisitTestBranch(const Instruction* instr) {3897unsigned bit_pos =3898(instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();3899bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;3900bool take_branch = false;3901switch (instr->Mask(TestBranchMask)) {3902case TBZ:3903take_branch = bit_zero;3904break;3905case TBNZ:3906take_branch = !bit_zero;3907break;3908default:3909VIXL_UNIMPLEMENTED();3910}3911if (take_branch) {3912WritePc(instr->GetImmPCOffsetTarget());3913}3914}391539163917void Simulator::VisitCompareBranch(const Instruction* instr) {3918unsigned rt = instr->GetRt();3919bool take_branch = false;3920switch (instr->Mask(CompareBranchMask)) {3921case CBZ_w:3922take_branch = (ReadWRegister(rt) == 0);3923break;3924case CBZ_x:3925take_branch = (ReadXRegister(rt) == 0);3926break;3927case CBNZ_w:3928take_branch = (ReadWRegister(rt) != 0);3929break;3930case CBNZ_x:3931take_branch = (ReadXRegister(rt) != 0);3932break;3933default:3934VIXL_UNIMPLEMENTED();3935}3936if (take_branch) {3937WritePc(instr->GetImmPCOffsetTarget());3938}3939}394039413942void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {3943unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;3944bool set_flags = instr->GetFlagsUpdate();3945int64_t new_val = 0;3946Instr operation = instr->Mask(AddSubOpMask);39473948switch (operation) {3949case ADD:3950case ADDS: {3951new_val = AddWithCarry(reg_size,3952set_flags,3953ReadRegister(reg_size,3954instr->GetRn(),3955instr->GetRnMode()),3956op2);3957break;3958}3959case SUB:3960case SUBS: {3961new_val = AddWithCarry(reg_size,3962set_flags,3963ReadRegister(reg_size,3964instr->GetRn(),3965instr->GetRnMode()),3966~op2,39671);3968break;3969}3970default:3971VIXL_UNREACHABLE();3972}39733974WriteRegister(reg_size,3975instr->GetRd(),3976new_val,3977LogRegWrites,3978instr->GetRdMode());3979}398039813982void Simulator::VisitAddSubShifted(const Instruction* instr) {3983// Add/sub/adds/subs don't allow ROR as a shift mode.3984VIXL_ASSERT(instr->GetShiftDP() != ROR);39853986unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;3987int64_t op2 = ShiftOperand(reg_size,3988ReadRegister(reg_size, instr->GetRm()),3989static_cast<Shift>(instr->GetShiftDP()),3990instr->GetImmDPShift());3991AddSubHelper(instr, op2);3992}399339943995void Simulator::VisitAddSubImmediate(const Instruction* instr) {3996int64_t op2 = instr->GetImmAddSub()3997<< ((instr->GetImmAddSubShift() == 1) ? 12 : 0);3998AddSubHelper(instr, op2);3999}400040014002void Simulator::VisitAddSubExtended(const Instruction* instr) {4003unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;4004int64_t op2 = ExtendValue(reg_size,4005ReadRegister(reg_size, instr->GetRm()),4006static_cast<Extend>(instr->GetExtendMode()),4007instr->GetImmExtendShift());4008AddSubHelper(instr, op2);4009}401040114012void Simulator::VisitAddSubWithCarry(const Instruction* instr) {4013unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;4014int64_t op2 = ReadRegister(reg_size, instr->GetRm());4015int64_t new_val;40164017if ((instr->Mask(AddSubOpMask) == SUB) ||4018(instr->Mask(AddSubOpMask) == SUBS)) {4019op2 = ~op2;4020}40214022new_val = AddWithCarry(reg_size,4023instr->GetFlagsUpdate(),4024ReadRegister(reg_size, instr->GetRn()),4025op2,4026ReadC());40274028WriteRegister(reg_size, instr->GetRd(), new_val);4029}403040314032void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {4033switch (instr->Mask(RotateRightIntoFlagsMask)) {4034case RMIF: {4035uint64_t value = ReadRegister<uint64_t>(instr->GetRn());4036unsigned shift = instr->GetImmRMIFRotation();4037unsigned mask = instr->GetNzcv();4038uint64_t rotated = RotateRight(value, shift, kXRegSize);40394040ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));4041break;4042}4043}4044}404540464047void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {4048uint32_t value = ReadRegister<uint32_t>(instr->GetRn());4049unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;40504051unsigned sign_bit = (value >> msb) & 1;4052unsigned overflow_bit = (value >> (msb + 1)) & 1;4053ReadNzcv().SetN(sign_bit);4054ReadNzcv().SetZ((value << (31 - msb)) == 0);4055ReadNzcv().SetV(sign_bit ^ overflow_bit);4056}405740584059void Simulator::VisitLogicalShifted(const Instruction* instr) {4060unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;4061Shift shift_type = static_cast<Shift>(instr->GetShiftDP());4062unsigned shift_amount = instr->GetImmDPShift();4063int64_t op2 = ShiftOperand(reg_size,4064ReadRegister(reg_size, instr->GetRm()),4065shift_type,4066shift_amount);4067if (instr->Mask(NOT) == NOT) {4068op2 = ~op2;4069}4070LogicalHelper(instr, op2);4071}407240734074void Simulator::VisitLogicalImmediate(const Instruction* instr) {4075if (instr->GetImmLogical() == 0) {4076VIXL_UNIMPLEMENTED();4077} else {4078LogicalHelper(instr, instr->GetImmLogical());4079}4080}408140824083void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {4084unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;4085int64_t op1 = ReadRegister(reg_size, instr->GetRn());4086int64_t result = 0;4087bool update_flags = false;40884089// Switch on the logical operation, stripping out the NOT bit, as it has a4090// different meaning for logical immediate instructions.4091switch (instr->Mask(LogicalOpMask & ~NOT)) {4092case ANDS:4093update_flags = true;4094VIXL_FALLTHROUGH();4095case AND:4096result = op1 & op2;4097break;4098case ORR:4099result = op1 | op2;4100break;4101case EOR:4102result = op1 ^ op2;4103break;4104default:4105VIXL_UNIMPLEMENTED();4106}41074108if (update_flags) {4109ReadNzcv().SetN(CalcNFlag(result, reg_size));4110ReadNzcv().SetZ(CalcZFlag(result));4111ReadNzcv().SetC(0);4112ReadNzcv().SetV(0);4113LogSystemRegister(NZCV);4114}41154116WriteRegister(reg_size,4117instr->GetRd(),4118result,4119LogRegWrites,4120instr->GetRdMode());4121}412241234124void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {4125unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;4126ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));4127}412841294130void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {4131ConditionalCompareHelper(instr, instr->GetImmCondCmp());4132}413341344135void Simulator::ConditionalCompareHelper(const Instruction* instr,4136int64_t op2) {4137unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;4138int64_t op1 = ReadRegister(reg_size, instr->GetRn());41394140if (ConditionPassed(instr->GetCondition())) {4141// If the condition passes, set the status flags to the result of comparing4142// the operands.4143if (instr->Mask(ConditionalCompareMask) == CCMP) {4144AddWithCarry(reg_size, true, op1, ~op2, 1);4145} else {4146VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);4147AddWithCarry(reg_size, true, op1, op2, 0);4148}4149} else {4150// If the condition fails, set the status flags to the nzcv immediate.4151ReadNzcv().SetFlags(instr->GetNzcv());4152LogSystemRegister(NZCV);4153}4154}415541564157void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {4158int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();4159LoadStoreHelper(instr, offset, Offset);4160}416141624163void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {4164LoadStoreHelper(instr, instr->GetImmLS(), Offset);4165}416641674168void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {4169LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);4170}417141724173void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {4174LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);4175}417641774178template <typename T1, typename T2>4179void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {4180unsigned rt = instr->GetRt();4181unsigned rn = instr->GetRn();41824183unsigned element_size = sizeof(T2);4184uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);4185int offset = instr->GetImmLS();4186address += offset;41874188// Verify that the address is available to the host.4189VIXL_ASSERT(address == static_cast<uintptr_t>(address));41904191// Check the alignment of `address`.4192if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {4193VIXL_ALIGNMENT_EXCEPTION();4194}41954196VIXL_DEFINE_OR_RETURN(value, MemRead<T2>(address));41974198WriteRegister<T1>(rt, static_cast<T1>(value));41994200// Approximate load-acquire by issuing a full barrier after the load.4201__sync_synchronize();42024203LogRead(rt, GetPrintRegisterFormat(element_size), address);4204}420542064207template <typename T>4208void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {4209unsigned rt = instr->GetRt();4210unsigned rn = instr->GetRn();42114212unsigned element_size = sizeof(T);4213uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);4214int offset = instr->GetImmLS();4215address += offset;42164217// Verify that the address is available to the host.4218VIXL_ASSERT(address == static_cast<uintptr_t>(address));42194220// Check the alignment of `address`.4221if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {4222VIXL_ALIGNMENT_EXCEPTION();4223}42244225// Approximate store-release by issuing a full barrier after the load.4226__sync_synchronize();42274228if (!MemWrite<T>(address, ReadRegister<T>(rt))) return;42294230LogWrite(rt, GetPrintRegisterFormat(element_size), address);4231}423242334234void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {4235switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {4236case LDAPURB:4237LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);4238break;4239case LDAPURH:4240LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);4241break;4242case LDAPUR_w:4243LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);4244break;4245case LDAPUR_x:4246LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);4247break;4248case LDAPURSB_w:4249LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);4250break;4251case LDAPURSB_x:4252LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);4253break;4254case LDAPURSH_w:4255LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);4256break;4257case LDAPURSH_x:4258LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);4259break;4260case LDAPURSW:4261LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);4262break;4263case STLURB:4264StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);4265break;4266case STLURH:4267StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);4268break;4269case STLUR_w:4270StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);4271break;4272case STLUR_x:4273StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);4274break;4275}4276}427742784279void Simulator::VisitLoadStorePAC(const Instruction* instr) {4280unsigned dst = instr->GetRt();4281unsigned addr_reg = instr->GetRn();42824283uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);42844285PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;4286address = AuthPAC(address, 0, key, kDataPointer);42874288int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;4289if (((address >> error_lsb) & 0x3) != 0x0) {4290VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");4291}429242934294if ((addr_reg == 31) && ((address % 16) != 0)) {4295// When the base register is SP the stack pointer is required to be4296// quadword aligned prior to the address calculation and write-backs.4297// Misalignment will cause a stack alignment fault.4298VIXL_ALIGNMENT_EXCEPTION();4299}43004301int64_t offset = instr->GetImmLSPAC();4302address += offset;43034304if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {4305// Pre-index mode.4306VIXL_ASSERT(offset != 0);4307WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);4308}43094310uintptr_t addr_ptr = static_cast<uintptr_t>(address);43114312// Verify that the calculated address is available to the host.4313VIXL_ASSERT(address == addr_ptr);43144315VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(addr_ptr));43164317WriteXRegister(dst, value, NoRegLog);4318unsigned access_size = 1 << 3;4319LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);4320}432143224323void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {4324Extend ext = static_cast<Extend>(instr->GetExtendMode());4325VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));4326unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();43274328int64_t offset =4329ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);4330LoadStoreHelper(instr, offset, Offset);4331}433243334334void Simulator::LoadStoreHelper(const Instruction* instr,4335int64_t offset,4336AddrMode addrmode) {4337unsigned srcdst = instr->GetRt();4338uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);43394340bool rt_is_vreg = false;4341int extend_to_size = 0;4342LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));4343switch (op) {4344case LDRB_w: {4345VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address));4346WriteWRegister(srcdst, value, NoRegLog);4347extend_to_size = kWRegSizeInBytes;4348break;4349}4350case LDRH_w: {4351VIXL_DEFINE_OR_RETURN(value, MemRead<uint16_t>(address));4352WriteWRegister(srcdst, value, NoRegLog);4353extend_to_size = kWRegSizeInBytes;4354break;4355}4356case LDR_w: {4357VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));4358WriteWRegister(srcdst, value, NoRegLog);4359extend_to_size = kWRegSizeInBytes;4360break;4361}4362case LDR_x: {4363VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));4364WriteXRegister(srcdst, value, NoRegLog);4365extend_to_size = kXRegSizeInBytes;4366break;4367}4368case LDRSB_w: {4369VIXL_DEFINE_OR_RETURN(value, MemRead<int8_t>(address));4370WriteWRegister(srcdst, value, NoRegLog);4371extend_to_size = kWRegSizeInBytes;4372break;4373}4374case LDRSH_w: {4375VIXL_DEFINE_OR_RETURN(value, MemRead<int16_t>(address));4376WriteWRegister(srcdst, value, NoRegLog);4377extend_to_size = kWRegSizeInBytes;4378break;4379}4380case LDRSB_x: {4381VIXL_DEFINE_OR_RETURN(value, MemRead<int8_t>(address));4382WriteXRegister(srcdst, value, NoRegLog);4383extend_to_size = kXRegSizeInBytes;4384break;4385}4386case LDRSH_x: {4387VIXL_DEFINE_OR_RETURN(value, MemRead<int16_t>(address));4388WriteXRegister(srcdst, value, NoRegLog);4389extend_to_size = kXRegSizeInBytes;4390break;4391}4392case LDRSW_x: {4393VIXL_DEFINE_OR_RETURN(value, MemRead<int32_t>(address));4394WriteXRegister(srcdst, value, NoRegLog);4395extend_to_size = kXRegSizeInBytes;4396break;4397}4398case LDR_b: {4399VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address));4400WriteBRegister(srcdst, value, NoRegLog);4401rt_is_vreg = true;4402break;4403}4404case LDR_h: {4405VIXL_DEFINE_OR_RETURN(value, MemRead<uint16_t>(address));4406WriteHRegister(srcdst, value, NoRegLog);4407rt_is_vreg = true;4408break;4409}4410case LDR_s: {4411VIXL_DEFINE_OR_RETURN(value, MemRead<float>(address));4412WriteSRegister(srcdst, value, NoRegLog);4413rt_is_vreg = true;4414break;4415}4416case LDR_d: {4417VIXL_DEFINE_OR_RETURN(value, MemRead<double>(address));4418WriteDRegister(srcdst, value, NoRegLog);4419rt_is_vreg = true;4420break;4421}4422case LDR_q: {4423VIXL_DEFINE_OR_RETURN(value, MemRead<qreg_t>(address));4424WriteQRegister(srcdst, value, NoRegLog);4425rt_is_vreg = true;4426break;4427}44284429case STRB_w:4430if (!MemWrite<uint8_t>(address, ReadWRegister(srcdst))) return;4431break;4432case STRH_w:4433if (!MemWrite<uint16_t>(address, ReadWRegister(srcdst))) return;4434break;4435case STR_w:4436if (!MemWrite<uint32_t>(address, ReadWRegister(srcdst))) return;4437break;4438case STR_x:4439if (!MemWrite<uint64_t>(address, ReadXRegister(srcdst))) return;4440break;4441case STR_b:4442if (!MemWrite<uint8_t>(address, ReadBRegister(srcdst))) return;4443rt_is_vreg = true;4444break;4445case STR_h:4446if (!MemWrite<uint16_t>(address, ReadHRegisterBits(srcdst))) return;4447rt_is_vreg = true;4448break;4449case STR_s:4450if (!MemWrite<float>(address, ReadSRegister(srcdst))) return;4451rt_is_vreg = true;4452break;4453case STR_d:4454if (!MemWrite<double>(address, ReadDRegister(srcdst))) return;4455rt_is_vreg = true;4456break;4457case STR_q:4458if (!MemWrite<qreg_t>(address, ReadQRegister(srcdst))) return;4459rt_is_vreg = true;4460break;44614462// Ignore prfm hint instructions.4463case PRFM:4464break;44654466default:4467VIXL_UNIMPLEMENTED();4468}44694470// Print a detailed trace (including the memory address).4471bool extend = (extend_to_size != 0);4472unsigned access_size = 1 << instr->GetSizeLS();4473unsigned result_size = extend ? extend_to_size : access_size;4474PrintRegisterFormat print_format =4475rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)4476: GetPrintRegisterFormatForSize(result_size);44774478if (instr->IsLoad()) {4479if (rt_is_vreg) {4480LogVRead(srcdst, print_format, address);4481} else {4482LogExtendingRead(srcdst, print_format, access_size, address);4483}4484} else if (instr->IsStore()) {4485if (rt_is_vreg) {4486LogVWrite(srcdst, print_format, address);4487} else {4488LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);4489}4490} else {4491VIXL_ASSERT(op == PRFM);4492}44934494local_monitor_.MaybeClear();4495}449644974498void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {4499LoadStorePairHelper(instr, Offset);4500}450145024503void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {4504LoadStorePairHelper(instr, PreIndex);4505}450645074508void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {4509LoadStorePairHelper(instr, PostIndex);4510}451145124513void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {4514LoadStorePairHelper(instr, Offset);4515}451645174518void Simulator::LoadStorePairHelper(const Instruction* instr,4519AddrMode addrmode) {4520unsigned rt = instr->GetRt();4521unsigned rt2 = instr->GetRt2();4522int element_size = 1 << instr->GetSizeLSPair();4523int64_t offset = instr->GetImmLSPair() * element_size;4524uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);4525uintptr_t address2 = address + element_size;45264527LoadStorePairOp op =4528static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));45294530// 'rt' and 'rt2' can only be aliased for stores.4531VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));45324533bool rt_is_vreg = false;4534bool sign_extend = false;4535switch (op) {4536// Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We4537// will print a more detailed log.4538case LDP_w: {4539VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));4540VIXL_DEFINE_OR_RETURN(value2, MemRead<uint32_t>(address2));4541WriteWRegister(rt, value, NoRegLog);4542WriteWRegister(rt2, value2, NoRegLog);4543break;4544}4545case LDP_s: {4546VIXL_DEFINE_OR_RETURN(value, MemRead<float>(address));4547VIXL_DEFINE_OR_RETURN(value2, MemRead<float>(address2));4548WriteSRegister(rt, value, NoRegLog);4549WriteSRegister(rt2, value2, NoRegLog);4550rt_is_vreg = true;4551break;4552}4553case LDP_x: {4554VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));4555VIXL_DEFINE_OR_RETURN(value2, MemRead<uint64_t>(address2));4556WriteXRegister(rt, value, NoRegLog);4557WriteXRegister(rt2, value2, NoRegLog);4558break;4559}4560case LDP_d: {4561VIXL_DEFINE_OR_RETURN(value, MemRead<double>(address));4562VIXL_DEFINE_OR_RETURN(value2, MemRead<double>(address2));4563WriteDRegister(rt, value, NoRegLog);4564WriteDRegister(rt2, value2, NoRegLog);4565rt_is_vreg = true;4566break;4567}4568case LDP_q: {4569VIXL_DEFINE_OR_RETURN(value, MemRead<qreg_t>(address));4570VIXL_DEFINE_OR_RETURN(value2, MemRead<qreg_t>(address2));4571WriteQRegister(rt, value, NoRegLog);4572WriteQRegister(rt2, value2, NoRegLog);4573rt_is_vreg = true;4574break;4575}4576case LDPSW_x: {4577VIXL_DEFINE_OR_RETURN(value, MemRead<int32_t>(address));4578VIXL_DEFINE_OR_RETURN(value2, MemRead<int32_t>(address2));4579WriteXRegister(rt, value, NoRegLog);4580WriteXRegister(rt2, value2, NoRegLog);4581sign_extend = true;4582break;4583}4584case STP_w: {4585if (!MemWrite<uint32_t>(address, ReadWRegister(rt))) return;4586if (!MemWrite<uint32_t>(address2, ReadWRegister(rt2))) return;4587break;4588}4589case STP_s: {4590if (!MemWrite<float>(address, ReadSRegister(rt))) return;4591if (!MemWrite<float>(address2, ReadSRegister(rt2))) return;4592rt_is_vreg = true;4593break;4594}4595case STP_x: {4596if (!MemWrite<uint64_t>(address, ReadXRegister(rt))) return;4597if (!MemWrite<uint64_t>(address2, ReadXRegister(rt2))) return;4598break;4599}4600case STP_d: {4601if (!MemWrite<double>(address, ReadDRegister(rt))) return;4602if (!MemWrite<double>(address2, ReadDRegister(rt2))) return;4603rt_is_vreg = true;4604break;4605}4606case STP_q: {4607if (!MemWrite<qreg_t>(address, ReadQRegister(rt))) return;4608if (!MemWrite<qreg_t>(address2, ReadQRegister(rt2))) return;4609rt_is_vreg = true;4610break;4611}4612default:4613VIXL_UNREACHABLE();4614}46154616// Print a detailed trace (including the memory address).4617unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;4618PrintRegisterFormat print_format =4619rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)4620: GetPrintRegisterFormatForSize(result_size);46214622if (instr->IsLoad()) {4623if (rt_is_vreg) {4624LogVRead(rt, print_format, address);4625LogVRead(rt2, print_format, address2);4626} else if (sign_extend) {4627LogExtendingRead(rt, print_format, element_size, address);4628LogExtendingRead(rt2, print_format, element_size, address2);4629} else {4630LogRead(rt, print_format, address);4631LogRead(rt2, print_format, address2);4632}4633} else {4634if (rt_is_vreg) {4635LogVWrite(rt, print_format, address);4636LogVWrite(rt2, print_format, address2);4637} else {4638LogWrite(rt, print_format, address);4639LogWrite(rt2, print_format, address2);4640}4641}46424643local_monitor_.MaybeClear();4644}464546464647template <typename T>4648void Simulator::CompareAndSwapHelper(const Instruction* instr) {4649unsigned rs = instr->GetRs();4650unsigned rt = instr->GetRt();4651unsigned rn = instr->GetRn();46524653unsigned element_size = sizeof(T);4654uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);46554656CheckIsValidUnalignedAtomicAccess(rn, address, element_size);46574658bool is_acquire = instr->ExtractBit(22) == 1;4659bool is_release = instr->ExtractBit(15) == 1;46604661T comparevalue = ReadRegister<T>(rs);4662T newvalue = ReadRegister<T>(rt);46634664// The architecture permits that the data read clears any exclusive monitors4665// associated with that location, even if the compare subsequently fails.4666local_monitor_.Clear();46674668VIXL_DEFINE_OR_RETURN(data, MemRead<T>(address));46694670if (is_acquire) {4671// Approximate load-acquire by issuing a full barrier after the load.4672__sync_synchronize();4673}46744675if (data == comparevalue) {4676if (is_release) {4677// Approximate store-release by issuing a full barrier before the store.4678__sync_synchronize();4679}4680if (!MemWrite<T>(address, newvalue)) return;4681LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);4682}4683WriteRegister<T>(rs, data, NoRegLog);4684LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);4685}468646874688template <typename T>4689void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {4690VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));4691unsigned rs = instr->GetRs();4692unsigned rt = instr->GetRt();4693unsigned rn = instr->GetRn();46944695VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));46964697unsigned element_size = sizeof(T);4698uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);46994700CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);47014702uint64_t address2 = address + element_size;47034704bool is_acquire = instr->ExtractBit(22) == 1;4705bool is_release = instr->ExtractBit(15) == 1;47064707T comparevalue_high = ReadRegister<T>(rs + 1);4708T comparevalue_low = ReadRegister<T>(rs);4709T newvalue_high = ReadRegister<T>(rt + 1);4710T newvalue_low = ReadRegister<T>(rt);47114712// The architecture permits that the data read clears any exclusive monitors4713// associated with that location, even if the compare subsequently fails.4714local_monitor_.Clear();47154716VIXL_DEFINE_OR_RETURN(data_low, MemRead<T>(address));4717VIXL_DEFINE_OR_RETURN(data_high, MemRead<T>(address2));47184719if (is_acquire) {4720// Approximate load-acquire by issuing a full barrier after the load.4721__sync_synchronize();4722}47234724bool same =4725(data_high == comparevalue_high) && (data_low == comparevalue_low);4726if (same) {4727if (is_release) {4728// Approximate store-release by issuing a full barrier before the store.4729__sync_synchronize();4730}47314732if (!MemWrite<T>(address, newvalue_low)) return;4733if (!MemWrite<T>(address2, newvalue_high)) return;4734}47354736WriteRegister<T>(rs + 1, data_high, NoRegLog);4737WriteRegister<T>(rs, data_low, NoRegLog);47384739PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);4740LogRead(rs, format, address);4741LogRead(rs + 1, format, address2);47424743if (same) {4744LogWrite(rt, format, address);4745LogWrite(rt + 1, format, address2);4746}4747}47484749bool Simulator::CanReadMemory(uintptr_t address, size_t size) {4750// To simulate fault-tolerant loads, we need to know what host addresses we4751// can access without generating a real fault. One way to do that is to4752// attempt to `write()` the memory to a placeholder pipe[1]. This is more4753// portable and less intrusive than using (global) signal handlers.4754//4755// [1]: https://stackoverflow.com/questions/713459047564757size_t written = 0;4758bool can_read = true;4759// `write` will normally return after one invocation, but it is allowed to4760// handle only part of the operation, so wrap it in a loop.4761while (can_read && (written < size)) {4762ssize_t result = write(placeholder_pipe_fd_[1],4763reinterpret_cast<void*>(address + written),4764size - written);4765if (result > 0) {4766written += result;4767} else {4768switch (result) {4769case -EPERM:4770case -EFAULT:4771// The address range is not accessible.4772// `write` is supposed to return -EFAULT in this case, but in practice4773// it seems to return -EPERM, so we accept that too.4774can_read = false;4775break;4776case -EINTR:4777// The call was interrupted by a signal. Just try again.4778break;4779default:4780// Any other error is fatal.4781VIXL_ABORT();4782}4783}4784}4785// Drain the read side of the pipe. If we don't do this, we'll leak memory as4786// the placeholder data is buffered. As before, we expect to drain the whole4787// write in one invocation, but cannot guarantee that, so we wrap it in a4788// loop. This function is primarily intended to implement SVE fault-tolerant4789// loads, so the maximum Z register size is a good default buffer size.4790char buffer[kZRegMaxSizeInBytes];4791while (written > 0) {4792ssize_t result = read(placeholder_pipe_fd_[0],4793reinterpret_cast<void*>(buffer),4794sizeof(buffer));4795// `read` blocks, and returns 0 only at EOF. We should not hit EOF until4796// we've read everything that was written, so treat 0 as an error.4797if (result > 0) {4798VIXL_ASSERT(static_cast<size_t>(result) <= written);4799written -= result;4800} else {4801// For -EINTR, just try again. We can't handle any other error.4802VIXL_CHECK(result == -EINTR);4803}4804}48054806return can_read;4807}48084809void Simulator::PrintExclusiveAccessWarning() {4810if (print_exclusive_access_warning_) {4811fprintf(stderr,4812"%sWARNING:%s VIXL simulator support for "4813"load-/store-/clear-exclusive "4814"instructions is limited. Refer to the README for details.%s\n",4815clr_warning,4816clr_warning_message,4817clr_normal);4818print_exclusive_access_warning_ = false;4819}4820}48214822void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {4823LoadStoreExclusive op =4824static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));48254826switch (op) {4827case CAS_w:4828case CASA_w:4829case CASL_w:4830case CASAL_w:4831CompareAndSwapHelper<uint32_t>(instr);4832break;4833case CAS_x:4834case CASA_x:4835case CASL_x:4836case CASAL_x:4837CompareAndSwapHelper<uint64_t>(instr);4838break;4839case CASB:4840case CASAB:4841case CASLB:4842case CASALB:4843CompareAndSwapHelper<uint8_t>(instr);4844break;4845case CASH:4846case CASAH:4847case CASLH:4848case CASALH:4849CompareAndSwapHelper<uint16_t>(instr);4850break;4851case CASP_w:4852case CASPA_w:4853case CASPL_w:4854case CASPAL_w:4855CompareAndSwapPairHelper<uint32_t>(instr);4856break;4857case CASP_x:4858case CASPA_x:4859case CASPL_x:4860case CASPAL_x:4861CompareAndSwapPairHelper<uint64_t>(instr);4862break;4863default:4864PrintExclusiveAccessWarning();48654866unsigned rs = instr->GetRs();4867unsigned rt = instr->GetRt();4868unsigned rt2 = instr->GetRt2();4869unsigned rn = instr->GetRn();48704871bool is_exclusive = !instr->GetLdStXNotExclusive();4872bool is_acquire_release =4873!is_exclusive || instr->GetLdStXAcquireRelease();4874bool is_load = instr->GetLdStXLoad();4875bool is_pair = instr->GetLdStXPair();48764877unsigned element_size = 1 << instr->GetLdStXSizeLog2();4878unsigned access_size = is_pair ? element_size * 2 : element_size;4879uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);48804881CheckIsValidUnalignedAtomicAccess(rn, address, access_size);48824883if (is_load) {4884if (is_exclusive) {4885local_monitor_.MarkExclusive(address, access_size);4886} else {4887// Any non-exclusive load can clear the local monitor as a side4888// effect. We don't need to do this, but it is useful to stress the4889// simulated code.4890local_monitor_.Clear();4891}48924893// Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).4894// We will print a more detailed log.4895unsigned reg_size = 0;4896switch (op) {4897case LDXRB_w:4898case LDAXRB_w:4899case LDARB_w:4900case LDLARB: {4901VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address));4902WriteWRegister(rt, value, NoRegLog);4903reg_size = kWRegSizeInBytes;4904break;4905}4906case LDXRH_w:4907case LDAXRH_w:4908case LDARH_w:4909case LDLARH: {4910VIXL_DEFINE_OR_RETURN(value, MemRead<uint16_t>(address));4911WriteWRegister(rt, value, NoRegLog);4912reg_size = kWRegSizeInBytes;4913break;4914}4915case LDXR_w:4916case LDAXR_w:4917case LDAR_w:4918case LDLAR_w: {4919VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));4920WriteWRegister(rt, value, NoRegLog);4921reg_size = kWRegSizeInBytes;4922break;4923}4924case LDXR_x:4925case LDAXR_x:4926case LDAR_x:4927case LDLAR_x: {4928VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));4929WriteXRegister(rt, value, NoRegLog);4930reg_size = kXRegSizeInBytes;4931break;4932}4933case LDXP_w:4934case LDAXP_w: {4935VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));4936VIXL_DEFINE_OR_RETURN(value2,4937MemRead<uint32_t>(address + element_size));4938WriteWRegister(rt, value, NoRegLog);4939WriteWRegister(rt2, value2, NoRegLog);4940reg_size = kWRegSizeInBytes;4941break;4942}4943case LDXP_x:4944case LDAXP_x: {4945VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));4946VIXL_DEFINE_OR_RETURN(value2,4947MemRead<uint64_t>(address + element_size));4948WriteXRegister(rt, value, NoRegLog);4949WriteXRegister(rt2, value2, NoRegLog);4950reg_size = kXRegSizeInBytes;4951break;4952}4953default:4954VIXL_UNREACHABLE();4955}49564957if (is_acquire_release) {4958// Approximate load-acquire by issuing a full barrier after the load.4959__sync_synchronize();4960}49614962PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);4963LogExtendingRead(rt, format, element_size, address);4964if (is_pair) {4965LogExtendingRead(rt2, format, element_size, address + element_size);4966}4967} else {4968if (is_acquire_release) {4969// Approximate store-release by issuing a full barrier before the4970// store.4971__sync_synchronize();4972}49734974bool do_store = true;4975if (is_exclusive) {4976do_store = local_monitor_.IsExclusive(address, access_size) &&4977global_monitor_.IsExclusive(address, access_size);4978WriteWRegister(rs, do_store ? 0 : 1);49794980// - All exclusive stores explicitly clear the local monitor.4981local_monitor_.Clear();4982} else {4983// - Any other store can clear the local monitor as a side effect.4984local_monitor_.MaybeClear();4985}49864987if (do_store) {4988switch (op) {4989case STXRB_w:4990case STLXRB_w:4991case STLRB_w:4992case STLLRB:4993if (!MemWrite<uint8_t>(address, ReadWRegister(rt))) return;4994break;4995case STXRH_w:4996case STLXRH_w:4997case STLRH_w:4998case STLLRH:4999if (!MemWrite<uint16_t>(address, ReadWRegister(rt))) return;5000break;5001case STXR_w:5002case STLXR_w:5003case STLR_w:5004case STLLR_w:5005if (!MemWrite<uint32_t>(address, ReadWRegister(rt))) return;5006break;5007case STXR_x:5008case STLXR_x:5009case STLR_x:5010case STLLR_x:5011if (!MemWrite<uint64_t>(address, ReadXRegister(rt))) return;5012break;5013case STXP_w:5014case STLXP_w:5015if (!MemWrite<uint32_t>(address, ReadWRegister(rt))) return;5016if (!MemWrite<uint32_t>(address + element_size,5017ReadWRegister(rt2))) {5018return;5019}5020break;5021case STXP_x:5022case STLXP_x:5023if (!MemWrite<uint64_t>(address, ReadXRegister(rt))) return;5024if (!MemWrite<uint64_t>(address + element_size,5025ReadXRegister(rt2))) {5026return;5027}5028break;5029default:5030VIXL_UNREACHABLE();5031}50325033PrintRegisterFormat format =5034GetPrintRegisterFormatForSize(element_size);5035LogWrite(rt, format, address);5036if (is_pair) {5037LogWrite(rt2, format, address + element_size);5038}5039}5040}5041}5042}50435044template <typename T>5045void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {5046unsigned rs = instr->GetRs();5047unsigned rt = instr->GetRt();5048unsigned rn = instr->GetRn();50495050bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);5051bool is_release = instr->ExtractBit(22) == 1;50525053unsigned element_size = sizeof(T);5054uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);50555056CheckIsValidUnalignedAtomicAccess(rn, address, element_size);50575058T value = ReadRegister<T>(rs);50595060VIXL_DEFINE_OR_RETURN(data, MemRead<T>(address));50615062if (is_acquire) {5063// Approximate load-acquire by issuing a full barrier after the load.5064__sync_synchronize();5065}50665067T result = 0;5068switch (instr->Mask(AtomicMemorySimpleOpMask)) {5069case LDADDOp:5070result = data + value;5071break;5072case LDCLROp:5073VIXL_ASSERT(!std::numeric_limits<T>::is_signed);5074result = data & ~value;5075break;5076case LDEOROp:5077VIXL_ASSERT(!std::numeric_limits<T>::is_signed);5078result = data ^ value;5079break;5080case LDSETOp:5081VIXL_ASSERT(!std::numeric_limits<T>::is_signed);5082result = data | value;5083break;50845085// Signed/Unsigned difference is done via the templated type T.5086case LDSMAXOp:5087case LDUMAXOp:5088result = (data > value) ? data : value;5089break;5090case LDSMINOp:5091case LDUMINOp:5092result = (data > value) ? value : data;5093break;5094}50955096if (is_release) {5097// Approximate store-release by issuing a full barrier before the store.5098__sync_synchronize();5099}51005101WriteRegister<T>(rt, data, NoRegLog);51025103unsigned register_size = element_size;5104if (element_size < kXRegSizeInBytes) {5105register_size = kWRegSizeInBytes;5106}5107PrintRegisterFormat format = GetPrintRegisterFormatForSize(register_size);5108LogExtendingRead(rt, format, element_size, address);51095110if (!MemWrite<T>(address, result)) return;5111format = GetPrintRegisterFormatForSize(element_size);5112LogWrite(rs, format, address);5113}51145115template <typename T>5116void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {5117unsigned rs = instr->GetRs();5118unsigned rt = instr->GetRt();5119unsigned rn = instr->GetRn();51205121bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);5122bool is_release = instr->ExtractBit(22) == 1;51235124unsigned element_size = sizeof(T);5125uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);51265127CheckIsValidUnalignedAtomicAccess(rn, address, element_size);51285129VIXL_DEFINE_OR_RETURN(data, MemRead<T>(address));51305131if (is_acquire) {5132// Approximate load-acquire by issuing a full barrier after the load.5133__sync_synchronize();5134}51355136if (is_release) {5137// Approximate store-release by issuing a full barrier before the store.5138__sync_synchronize();5139}5140if (!MemWrite<T>(address, ReadRegister<T>(rs))) return;51415142WriteRegister<T>(rt, data);51435144PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);5145LogRead(rt, format, address);5146LogWrite(rs, format, address);5147}51485149template <typename T>5150void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {5151unsigned rt = instr->GetRt();5152unsigned rn = instr->GetRn();51535154unsigned element_size = sizeof(T);5155uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);51565157CheckIsValidUnalignedAtomicAccess(rn, address, element_size);51585159VIXL_DEFINE_OR_RETURN(value, MemRead<T>(address));51605161WriteRegister<T>(rt, value);51625163// Approximate load-acquire by issuing a full barrier after the load.5164__sync_synchronize();51655166LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);5167}51685169#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \5170V(LDADD) \5171V(LDCLR) \5172V(LDEOR) \5173V(LDSET) \5174V(LDUMAX) \5175V(LDUMIN)51765177#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \5178V(LDSMAX) \5179V(LDSMIN)51805181void Simulator::VisitAtomicMemory(const Instruction* instr) {5182switch (instr->Mask(AtomicMemoryMask)) {5183// clang-format off5184#define SIM_FUNC_B(A) \5185case A##B: \5186case A##AB: \5187case A##LB: \5188case A##ALB:5189#define SIM_FUNC_H(A) \5190case A##H: \5191case A##AH: \5192case A##LH: \5193case A##ALH:5194#define SIM_FUNC_w(A) \5195case A##_w: \5196case A##A_w: \5197case A##L_w: \5198case A##AL_w:5199#define SIM_FUNC_x(A) \5200case A##_x: \5201case A##A_x: \5202case A##L_x: \5203case A##AL_x:52045205ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)5206AtomicMemorySimpleHelper<uint8_t>(instr);5207break;5208ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)5209AtomicMemorySimpleHelper<int8_t>(instr);5210break;5211ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)5212AtomicMemorySimpleHelper<uint16_t>(instr);5213break;5214ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)5215AtomicMemorySimpleHelper<int16_t>(instr);5216break;5217ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)5218AtomicMemorySimpleHelper<uint32_t>(instr);5219break;5220ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)5221AtomicMemorySimpleHelper<int32_t>(instr);5222break;5223ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)5224AtomicMemorySimpleHelper<uint64_t>(instr);5225break;5226ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)5227AtomicMemorySimpleHelper<int64_t>(instr);5228break;5229// clang-format on52305231case SWPB:5232case SWPAB:5233case SWPLB:5234case SWPALB:5235AtomicMemorySwapHelper<uint8_t>(instr);5236break;5237case SWPH:5238case SWPAH:5239case SWPLH:5240case SWPALH:5241AtomicMemorySwapHelper<uint16_t>(instr);5242break;5243case SWP_w:5244case SWPA_w:5245case SWPL_w:5246case SWPAL_w:5247AtomicMemorySwapHelper<uint32_t>(instr);5248break;5249case SWP_x:5250case SWPA_x:5251case SWPL_x:5252case SWPAL_x:5253AtomicMemorySwapHelper<uint64_t>(instr);5254break;5255case LDAPRB:5256LoadAcquireRCpcHelper<uint8_t>(instr);5257break;5258case LDAPRH:5259LoadAcquireRCpcHelper<uint16_t>(instr);5260break;5261case LDAPR_w:5262LoadAcquireRCpcHelper<uint32_t>(instr);5263break;5264case LDAPR_x:5265LoadAcquireRCpcHelper<uint64_t>(instr);5266break;5267}5268}526952705271void Simulator::VisitLoadLiteral(const Instruction* instr) {5272unsigned rt = instr->GetRt();5273uint64_t address = instr->GetLiteralAddress<uint64_t>();52745275// Verify that the calculated address is available to the host.5276VIXL_ASSERT(address == static_cast<uintptr_t>(address));52775278switch (instr->Mask(LoadLiteralMask)) {5279// Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then5280// print a more detailed log.5281case LDR_w_lit: {5282VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));5283WriteWRegister(rt, value, NoRegLog);5284LogRead(rt, kPrintWReg, address);5285break;5286}5287case LDR_x_lit: {5288VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));5289WriteXRegister(rt, value, NoRegLog);5290LogRead(rt, kPrintXReg, address);5291break;5292}5293case LDR_s_lit: {5294VIXL_DEFINE_OR_RETURN(value, MemRead<float>(address));5295WriteSRegister(rt, value, NoRegLog);5296LogVRead(rt, kPrintSRegFP, address);5297break;5298}5299case LDR_d_lit: {5300VIXL_DEFINE_OR_RETURN(value, MemRead<double>(address));5301WriteDRegister(rt, value, NoRegLog);5302LogVRead(rt, kPrintDRegFP, address);5303break;5304}5305case LDR_q_lit: {5306VIXL_DEFINE_OR_RETURN(value, MemRead<qreg_t>(address));5307WriteQRegister(rt, value, NoRegLog);5308LogVRead(rt, kPrintReg1Q, address);5309break;5310}5311case LDRSW_x_lit: {5312VIXL_DEFINE_OR_RETURN(value, MemRead<int32_t>(address));5313WriteXRegister(rt, value, NoRegLog);5314LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);5315break;5316}53175318// Ignore prfm hint instructions.5319case PRFM_lit:5320break;53215322default:5323VIXL_UNREACHABLE();5324}53255326local_monitor_.MaybeClear();5327}532853295330uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,5331int64_t offset,5332AddrMode addrmode) {5333uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);53345335if ((addr_reg == 31) && ((address % 16) != 0)) {5336// When the base register is SP the stack pointer is required to be5337// quadword aligned prior to the address calculation and write-backs.5338// Misalignment will cause a stack alignment fault.5339VIXL_ALIGNMENT_EXCEPTION();5340}53415342if ((addrmode == PreIndex) || (addrmode == PostIndex)) {5343VIXL_ASSERT(offset != 0);5344// Only preindex should log the register update here. For Postindex, the5345// update will be printed automatically by LogWrittenRegisters _after_ the5346// memory access itself is logged.5347RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;5348WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);5349}53505351if ((addrmode == Offset) || (addrmode == PreIndex)) {5352address += offset;5353}53545355// Verify that the calculated address is available to the host.5356VIXL_ASSERT(address == static_cast<uintptr_t>(address));53575358return static_cast<uintptr_t>(address);5359}536053615362void Simulator::VisitMoveWideImmediate(const Instruction* instr) {5363MoveWideImmediateOp mov_op =5364static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));5365int64_t new_xn_val = 0;53665367bool is_64_bits = instr->GetSixtyFourBits() == 1;5368// Shift is limited for W operations.5369VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));53705371// Get the shifted immediate.5372int64_t shift = instr->GetShiftMoveWide() * 16;5373int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())5374<< shift;53755376// Compute the new value.5377switch (mov_op) {5378case MOVN_w:5379case MOVN_x: {5380new_xn_val = ~shifted_imm16;5381if (!is_64_bits) new_xn_val &= kWRegMask;5382break;5383}5384case MOVK_w:5385case MOVK_x: {5386unsigned reg_code = instr->GetRd();5387int64_t prev_xn_val =5388is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);5389new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;5390break;5391}5392case MOVZ_w:5393case MOVZ_x: {5394new_xn_val = shifted_imm16;5395break;5396}5397default:5398VIXL_UNREACHABLE();5399}54005401// Update the destination register.5402WriteXRegister(instr->GetRd(), new_xn_val);5403}540454055406void Simulator::VisitConditionalSelect(const Instruction* instr) {5407uint64_t new_val = ReadXRegister(instr->GetRn());54085409if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {5410new_val = ReadXRegister(instr->GetRm());5411switch (instr->Mask(ConditionalSelectMask)) {5412case CSEL_w:5413case CSEL_x:5414break;5415case CSINC_w:5416case CSINC_x:5417new_val++;5418break;5419case CSINV_w:5420case CSINV_x:5421new_val = ~new_val;5422break;5423case CSNEG_w:5424case CSNEG_x:5425new_val = -new_val;5426break;5427default:5428VIXL_UNIMPLEMENTED();5429}5430}5431unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;5432WriteRegister(reg_size, instr->GetRd(), new_val);5433}543454355436#define PAUTH_MODES_REGISTER_CONTEXT(V) \5437V(i, a, kPACKeyIA, kInstructionPointer) \5438V(i, b, kPACKeyIB, kInstructionPointer) \5439V(d, a, kPACKeyDA, kDataPointer) \5440V(d, b, kPACKeyDB, kDataPointer)54415442void Simulator::VisitDataProcessing1Source(const Instruction* instr) {5443unsigned dst = instr->GetRd();5444unsigned src = instr->GetRn();5445Reg31Mode r31_pac = Reg31IsStackPointer;54465447switch (form_hash_) {5448#define DEFINE_PAUTH_FUNCS(SUF0, SUF1, KEY, D) \5449case "pac" #SUF0 "z" #SUF1 "_64z_dp_1src"_h: \5450VIXL_ASSERT(src == kZeroRegCode); \5451r31_pac = Reg31IsZeroRegister; \5452VIXL_FALLTHROUGH(); \5453case "pac" #SUF0 #SUF1 "_64p_dp_1src"_h: { \5454uint64_t mod = ReadXRegister(src, r31_pac); \5455uint64_t ptr = ReadXRegister(dst); \5456WriteXRegister(dst, AddPAC(ptr, mod, KEY, D)); \5457break; \5458} \5459case "aut" #SUF0 "z" #SUF1 "_64z_dp_1src"_h: \5460VIXL_ASSERT(src == kZeroRegCode); \5461r31_pac = Reg31IsZeroRegister; \5462VIXL_FALLTHROUGH(); \5463case "aut" #SUF0 #SUF1 "_64p_dp_1src"_h: { \5464uint64_t mod = ReadXRegister(src, r31_pac); \5465uint64_t ptr = ReadXRegister(dst); \5466WriteXRegister(dst, AuthPAC(ptr, mod, KEY, D)); \5467break; \5468}5469PAUTH_MODES_REGISTER_CONTEXT(DEFINE_PAUTH_FUNCS)5470#undef DEFINE_PAUTH_FUNCS54715472case "xpaci_64z_dp_1src"_h:5473WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));5474break;5475case "xpacd_64z_dp_1src"_h:5476WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));5477break;5478case "rbit_32_dp_1src"_h:5479WriteWRegister(dst, ReverseBits(ReadWRegister(src)));5480break;5481case "rbit_64_dp_1src"_h:5482WriteXRegister(dst, ReverseBits(ReadXRegister(src)));5483break;5484case "rev16_32_dp_1src"_h:5485WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));5486break;5487case "rev16_64_dp_1src"_h:5488WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));5489break;5490case "rev_32_dp_1src"_h:5491WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));5492break;5493case "rev32_64_dp_1src"_h:5494WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));5495break;5496case "rev_64_dp_1src"_h:5497WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));5498break;5499case "clz_32_dp_1src"_h:5500WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));5501break;5502case "clz_64_dp_1src"_h:5503WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));5504break;5505case "cls_32_dp_1src"_h:5506WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));5507break;5508case "cls_64_dp_1src"_h:5509WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));5510break;5511case "abs_32_dp_1src"_h:5512WriteWRegister(dst, Abs(ReadWRegister(src)));5513break;5514case "abs_64_dp_1src"_h:5515WriteXRegister(dst, Abs(ReadXRegister(src)));5516break;5517case "cnt_32_dp_1src"_h:5518WriteWRegister(dst, CountSetBits(ReadWRegister(src)));5519break;5520case "cnt_64_dp_1src"_h:5521WriteXRegister(dst, CountSetBits(ReadXRegister(src)));5522break;5523case "ctz_32_dp_1src"_h:5524WriteWRegister(dst, CountTrailingZeros(ReadWRegister(src)));5525break;5526case "ctz_64_dp_1src"_h:5527WriteXRegister(dst, CountTrailingZeros(ReadXRegister(src)));5528break;5529}5530}55315532uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {5533VIXL_ASSERT((n > 32) && (n <= 64));5534for (unsigned i = (n - 1); i >= 32; i--) {5535if (((data >> i) & 1) != 0) {5536uint64_t polysh32 = (uint64_t)poly << (i - 32);5537uint64_t mask = (UINT64_C(1) << i) - 1;5538data = ((data & mask) ^ polysh32);5539}5540}5541return data & 0xffffffff;5542}554355445545template <typename T>5546uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {5547unsigned size = sizeof(val) * 8; // Number of bits in type T.5548VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));5549uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;5550uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;5551return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));5552}555355545555uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {5556// Poly32Mod2 cannot handle inputs with more than 32 bits, so compute5557// the CRC of each 32-bit word sequentially.5558acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);5559return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);5560}556155625563void Simulator::VisitDataProcessing2Source(const Instruction* instr) {5564Shift shift_op = NO_SHIFT;5565int64_t result = 0;5566unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;55675568switch (instr->Mask(DataProcessing2SourceMask)) {5569case SDIV_w: {5570int32_t rn = ReadWRegister(instr->GetRn());5571int32_t rm = ReadWRegister(instr->GetRm());5572if ((rn == kWMinInt) && (rm == -1)) {5573result = kWMinInt;5574} else if (rm == 0) {5575// Division by zero can be trapped, but not on A-class processors.5576result = 0;5577} else {5578result = rn / rm;5579}5580break;5581}5582case SDIV_x: {5583int64_t rn = ReadXRegister(instr->GetRn());5584int64_t rm = ReadXRegister(instr->GetRm());5585if ((rn == kXMinInt) && (rm == -1)) {5586result = kXMinInt;5587} else if (rm == 0) {5588// Division by zero can be trapped, but not on A-class processors.5589result = 0;5590} else {5591result = rn / rm;5592}5593break;5594}5595case UDIV_w: {5596uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));5597uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));5598if (rm == 0) {5599// Division by zero can be trapped, but not on A-class processors.5600result = 0;5601} else {5602result = rn / rm;5603}5604break;5605}5606case UDIV_x: {5607uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));5608uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));5609if (rm == 0) {5610// Division by zero can be trapped, but not on A-class processors.5611result = 0;5612} else {5613result = rn / rm;5614}5615break;5616}5617case LSLV_w:5618case LSLV_x:5619shift_op = LSL;5620break;5621case LSRV_w:5622case LSRV_x:5623shift_op = LSR;5624break;5625case ASRV_w:5626case ASRV_x:5627shift_op = ASR;5628break;5629case RORV_w:5630case RORV_x:5631shift_op = ROR;5632break;5633case PACGA: {5634uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));5635uint64_t src = static_cast<uint64_t>(5636ReadXRegister(instr->GetRm(), Reg31IsStackPointer));5637uint64_t code = ComputePAC(dst, src, kPACKeyGA);5638result = code & 0xffffffff00000000;5639break;5640}5641case CRC32B: {5642uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());5643uint8_t val = ReadRegister<uint8_t>(instr->GetRm());5644result = Crc32Checksum(acc, val, CRC32_POLY);5645break;5646}5647case CRC32H: {5648uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());5649uint16_t val = ReadRegister<uint16_t>(instr->GetRm());5650result = Crc32Checksum(acc, val, CRC32_POLY);5651break;5652}5653case CRC32W: {5654uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());5655uint32_t val = ReadRegister<uint32_t>(instr->GetRm());5656result = Crc32Checksum(acc, val, CRC32_POLY);5657break;5658}5659case CRC32X: {5660uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());5661uint64_t val = ReadRegister<uint64_t>(instr->GetRm());5662result = Crc32Checksum(acc, val, CRC32_POLY);5663reg_size = kWRegSize;5664break;5665}5666case CRC32CB: {5667uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());5668uint8_t val = ReadRegister<uint8_t>(instr->GetRm());5669result = Crc32Checksum(acc, val, CRC32C_POLY);5670break;5671}5672case CRC32CH: {5673uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());5674uint16_t val = ReadRegister<uint16_t>(instr->GetRm());5675result = Crc32Checksum(acc, val, CRC32C_POLY);5676break;5677}5678case CRC32CW: {5679uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());5680uint32_t val = ReadRegister<uint32_t>(instr->GetRm());5681result = Crc32Checksum(acc, val, CRC32C_POLY);5682break;5683}5684case CRC32CX: {5685uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());5686uint64_t val = ReadRegister<uint64_t>(instr->GetRm());5687result = Crc32Checksum(acc, val, CRC32C_POLY);5688reg_size = kWRegSize;5689break;5690}5691default:5692VIXL_UNIMPLEMENTED();5693}56945695if (shift_op != NO_SHIFT) {5696// Shift distance encoded in the least-significant five/six bits of the5697// register.5698int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;5699unsigned shift = ReadWRegister(instr->GetRm()) & mask;5700result = ShiftOperand(reg_size,5701ReadRegister(reg_size, instr->GetRn()),5702shift_op,5703shift);5704}5705WriteRegister(reg_size, instr->GetRd(), result);5706}57075708void Simulator::SimulateSignedMinMax(const Instruction* instr) {5709int32_t wn = ReadWRegister(instr->GetRn());5710int32_t wm = ReadWRegister(instr->GetRm());5711int64_t xn = ReadXRegister(instr->GetRn());5712int64_t xm = ReadXRegister(instr->GetRm());5713int32_t imm = instr->ExtractSignedBits(17, 10);5714int dst = instr->GetRd();57155716switch (form_hash_) {5717case "smax_64_minmax_imm"_h:5718case "smin_64_minmax_imm"_h:5719xm = imm;5720break;5721case "smax_32_minmax_imm"_h:5722case "smin_32_minmax_imm"_h:5723wm = imm;5724break;5725}57265727switch (form_hash_) {5728case "smax_32_minmax_imm"_h:5729case "smax_32_dp_2src"_h:5730WriteWRegister(dst, std::max(wn, wm));5731break;5732case "smax_64_minmax_imm"_h:5733case "smax_64_dp_2src"_h:5734WriteXRegister(dst, std::max(xn, xm));5735break;5736case "smin_32_minmax_imm"_h:5737case "smin_32_dp_2src"_h:5738WriteWRegister(dst, std::min(wn, wm));5739break;5740case "smin_64_minmax_imm"_h:5741case "smin_64_dp_2src"_h:5742WriteXRegister(dst, std::min(xn, xm));5743break;5744}5745}57465747void Simulator::SimulateUnsignedMinMax(const Instruction* instr) {5748uint64_t xn = ReadXRegister(instr->GetRn());5749uint64_t xm = ReadXRegister(instr->GetRm());5750uint32_t imm = instr->ExtractBits(17, 10);5751int dst = instr->GetRd();57525753switch (form_hash_) {5754case "umax_64u_minmax_imm"_h:5755case "umax_32u_minmax_imm"_h:5756case "umin_64u_minmax_imm"_h:5757case "umin_32u_minmax_imm"_h:5758xm = imm;5759break;5760}57615762switch (form_hash_) {5763case "umax_32u_minmax_imm"_h:5764case "umax_32_dp_2src"_h:5765xn &= 0xffff'ffff;5766xm &= 0xffff'ffff;5767VIXL_FALLTHROUGH();5768case "umax_64u_minmax_imm"_h:5769case "umax_64_dp_2src"_h:5770WriteXRegister(dst, std::max(xn, xm));5771break;5772case "umin_32u_minmax_imm"_h:5773case "umin_32_dp_2src"_h:5774xn &= 0xffff'ffff;5775xm &= 0xffff'ffff;5776VIXL_FALLTHROUGH();5777case "umin_64u_minmax_imm"_h:5778case "umin_64_dp_2src"_h:5779WriteXRegister(dst, std::min(xn, xm));5780break;5781}5782}57835784void Simulator::VisitDataProcessing3Source(const Instruction* instr) {5785unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;57865787uint64_t result = 0;5788// Extract and sign- or zero-extend 32-bit arguments for widening operations.5789uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());5790uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());5791int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());5792int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());5793uint64_t rn_u64 = ReadXRegister(instr->GetRn());5794uint64_t rm_u64 = ReadXRegister(instr->GetRm());5795switch (instr->Mask(DataProcessing3SourceMask)) {5796case MADD_w:5797case MADD_x:5798result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);5799break;5800case MSUB_w:5801case MSUB_x:5802result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);5803break;5804case SMADDL_x:5805result = ReadXRegister(instr->GetRa()) +5806static_cast<uint64_t>(rn_s32 * rm_s32);5807break;5808case SMSUBL_x:5809result = ReadXRegister(instr->GetRa()) -5810static_cast<uint64_t>(rn_s32 * rm_s32);5811break;5812case UMADDL_x:5813result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);5814break;5815case UMSUBL_x:5816result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);5817break;5818case UMULH_x:5819result =5820internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),5821ReadRegister<uint64_t>(instr->GetRm()));5822break;5823case SMULH_x:5824result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),5825ReadXRegister(instr->GetRm()));5826break;5827default:5828VIXL_UNIMPLEMENTED();5829}5830WriteRegister(reg_size, instr->GetRd(), result);5831}583258335834void Simulator::VisitBitfield(const Instruction* instr) {5835unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;5836int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;5837int R = instr->GetImmR();5838int S = instr->GetImmS();58395840if (instr->GetSixtyFourBits() != instr->GetBitN()) {5841VisitUnallocated(instr);5842}58435844if ((instr->GetSixtyFourBits() == 0) && ((S > 31) || (R > 31))) {5845VisitUnallocated(instr);5846}58475848int diff = S - R;5849uint64_t mask;5850if (diff >= 0) {5851mask = ~UINT64_C(0) >> (64 - (diff + 1));5852mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;5853} else {5854mask = ~UINT64_C(0) >> (64 - (S + 1));5855mask = RotateRight(mask, R, reg_size);5856diff += reg_size;5857}58585859// inzero indicates if the extracted bitfield is inserted into the5860// destination register value or in zero.5861// If extend is true, extend the sign of the extracted bitfield.5862bool inzero = false;5863bool extend = false;5864switch (instr->Mask(BitfieldMask)) {5865case BFM_x:5866case BFM_w:5867break;5868case SBFM_x:5869case SBFM_w:5870inzero = true;5871extend = true;5872break;5873case UBFM_x:5874case UBFM_w:5875inzero = true;5876break;5877default:5878VIXL_UNIMPLEMENTED();5879}58805881uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());5882uint64_t src = ReadRegister(reg_size, instr->GetRn());5883// Rotate source bitfield into place.5884uint64_t result = RotateRight(src, R, reg_size);5885// Determine the sign extension.5886uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));5887uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;58885889// Merge sign extension, dest/zero and bitfield.5890result = signbits | (result & mask) | (dst & ~mask);58915892WriteRegister(reg_size, instr->GetRd(), result);5893}589458955896void Simulator::VisitExtract(const Instruction* instr) {5897unsigned lsb = instr->GetImmS();5898unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;5899uint64_t low_res =5900static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;5901uint64_t high_res = (lsb == 0)5902? 05903: ReadRegister<uint64_t>(reg_size, instr->GetRn())5904<< (reg_size - lsb);5905WriteRegister(reg_size, instr->GetRd(), low_res | high_res);5906}590759085909void Simulator::VisitFPImmediate(const Instruction* instr) {5910AssertSupportedFPCR();5911unsigned dest = instr->GetRd();5912switch (instr->Mask(FPImmediateMask)) {5913case FMOV_h_imm:5914WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));5915break;5916case FMOV_s_imm:5917WriteSRegister(dest, instr->GetImmFP32());5918break;5919case FMOV_d_imm:5920WriteDRegister(dest, instr->GetImmFP64());5921break;5922default:5923VIXL_UNREACHABLE();5924}5925}592659275928void Simulator::VisitFPIntegerConvert(const Instruction* instr) {5929AssertSupportedFPCR();59305931unsigned dst = instr->GetRd();5932unsigned src = instr->GetRn();59335934FPRounding round = ReadRMode();59355936switch (instr->Mask(FPIntegerConvertMask)) {5937case FCVTAS_wh:5938WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));5939break;5940case FCVTAS_xh:5941WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));5942break;5943case FCVTAS_ws:5944WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));5945break;5946case FCVTAS_xs:5947WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));5948break;5949case FCVTAS_wd:5950WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));5951break;5952case FCVTAS_xd:5953WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));5954break;5955case FCVTAU_wh:5956WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));5957break;5958case FCVTAU_xh:5959WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));5960break;5961case FCVTAU_ws:5962WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));5963break;5964case FCVTAU_xs:5965WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));5966break;5967case FCVTAU_wd:5968WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));5969break;5970case FCVTAU_xd:5971WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));5972break;5973case FCVTMS_wh:5974WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));5975break;5976case FCVTMS_xh:5977WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));5978break;5979case FCVTMS_ws:5980WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));5981break;5982case FCVTMS_xs:5983WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));5984break;5985case FCVTMS_wd:5986WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));5987break;5988case FCVTMS_xd:5989WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));5990break;5991case FCVTMU_wh:5992WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));5993break;5994case FCVTMU_xh:5995WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));5996break;5997case FCVTMU_ws:5998WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));5999break;6000case FCVTMU_xs:6001WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));6002break;6003case FCVTMU_wd:6004WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));6005break;6006case FCVTMU_xd:6007WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));6008break;6009case FCVTPS_wh:6010WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));6011break;6012case FCVTPS_xh:6013WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));6014break;6015case FCVTPS_ws:6016WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));6017break;6018case FCVTPS_xs:6019WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));6020break;6021case FCVTPS_wd:6022WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));6023break;6024case FCVTPS_xd:6025WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));6026break;6027case FCVTPU_wh:6028WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));6029break;6030case FCVTPU_xh:6031WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));6032break;6033case FCVTPU_ws:6034WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));6035break;6036case FCVTPU_xs:6037WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));6038break;6039case FCVTPU_wd:6040WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));6041break;6042case FCVTPU_xd:6043WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));6044break;6045case FCVTNS_wh:6046WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));6047break;6048case FCVTNS_xh:6049WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));6050break;6051case FCVTNS_ws:6052WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));6053break;6054case FCVTNS_xs:6055WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));6056break;6057case FCVTNS_wd:6058WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));6059break;6060case FCVTNS_xd:6061WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));6062break;6063case FCVTNU_wh:6064WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));6065break;6066case FCVTNU_xh:6067WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));6068break;6069case FCVTNU_ws:6070WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));6071break;6072case FCVTNU_xs:6073WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));6074break;6075case FCVTNU_wd:6076WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));6077break;6078case FCVTNU_xd:6079WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));6080break;6081case FCVTZS_wh:6082WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));6083break;6084case FCVTZS_xh:6085WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));6086break;6087case FCVTZS_ws:6088WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));6089break;6090case FCVTZS_xs:6091WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));6092break;6093case FCVTZS_wd:6094WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));6095break;6096case FCVTZS_xd:6097WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));6098break;6099case FCVTZU_wh:6100WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));6101break;6102case FCVTZU_xh:6103WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));6104break;6105case FCVTZU_ws:6106WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));6107break;6108case FCVTZU_xs:6109WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));6110break;6111case FCVTZU_wd:6112WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));6113break;6114case FCVTZU_xd:6115WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));6116break;6117case FJCVTZS:6118WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));6119break;6120case FMOV_hw:6121WriteHRegister(dst, ReadWRegister(src) & kHRegMask);6122break;6123case FMOV_wh:6124WriteWRegister(dst, ReadHRegisterBits(src));6125break;6126case FMOV_xh:6127WriteXRegister(dst, ReadHRegisterBits(src));6128break;6129case FMOV_hx:6130WriteHRegister(dst, ReadXRegister(src) & kHRegMask);6131break;6132case FMOV_ws:6133WriteWRegister(dst, ReadSRegisterBits(src));6134break;6135case FMOV_xd:6136WriteXRegister(dst, ReadDRegisterBits(src));6137break;6138case FMOV_sw:6139WriteSRegisterBits(dst, ReadWRegister(src));6140break;6141case FMOV_dx:6142WriteDRegisterBits(dst, ReadXRegister(src));6143break;6144case FMOV_d1_x:6145// Zero bits beyond the MSB of a Q register.6146mov(kFormat16B, ReadVRegister(dst), ReadVRegister(dst));6147LogicVRegister(ReadVRegister(dst))6148.SetUint(kFormatD, 1, ReadXRegister(src));6149break;6150case FMOV_x_d1:6151WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));6152break;61536154// A 32-bit input can be handled in the same way as a 64-bit input, since6155// the sign- or zero-extension will not affect the conversion.6156case SCVTF_dx:6157WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));6158break;6159case SCVTF_dw:6160WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));6161break;6162case UCVTF_dx:6163WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));6164break;6165case UCVTF_dw: {6166WriteDRegister(dst,6167UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));6168break;6169}6170case SCVTF_sx:6171WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));6172break;6173case SCVTF_sw:6174WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));6175break;6176case UCVTF_sx:6177WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));6178break;6179case UCVTF_sw: {6180WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));6181break;6182}6183case SCVTF_hx:6184WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));6185break;6186case SCVTF_hw:6187WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));6188break;6189case UCVTF_hx:6190WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));6191break;6192case UCVTF_hw: {6193WriteHRegister(dst,6194UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));6195break;6196}61976198default:6199VIXL_UNREACHABLE();6200}6201}620262036204void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {6205AssertSupportedFPCR();62066207unsigned dst = instr->GetRd();6208unsigned src = instr->GetRn();6209int fbits = 64 - instr->GetFPScale();62106211FPRounding round = ReadRMode();62126213switch (instr->Mask(FPFixedPointConvertMask)) {6214// A 32-bit input can be handled in the same way as a 64-bit input, since6215// the sign- or zero-extension will not affect the conversion.6216case SCVTF_dx_fixed:6217WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));6218break;6219case SCVTF_dw_fixed:6220WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));6221break;6222case UCVTF_dx_fixed:6223WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));6224break;6225case UCVTF_dw_fixed: {6226WriteDRegister(dst,6227UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));6228break;6229}6230case SCVTF_sx_fixed:6231WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));6232break;6233case SCVTF_sw_fixed:6234WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));6235break;6236case UCVTF_sx_fixed:6237WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));6238break;6239case UCVTF_sw_fixed: {6240WriteSRegister(dst,6241UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));6242break;6243}6244case SCVTF_hx_fixed:6245WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));6246break;6247case SCVTF_hw_fixed:6248WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));6249break;6250case UCVTF_hx_fixed:6251WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));6252break;6253case UCVTF_hw_fixed: {6254WriteHRegister(dst,6255UFixedToFloat16(ReadRegister<uint32_t>(src),6256fbits,6257round));6258break;6259}6260case FCVTZS_xd_fixed:6261WriteXRegister(dst,6262FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),6263FPZero));6264break;6265case FCVTZS_wd_fixed:6266WriteWRegister(dst,6267FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),6268FPZero));6269break;6270case FCVTZU_xd_fixed:6271WriteXRegister(dst,6272FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),6273FPZero));6274break;6275case FCVTZU_wd_fixed:6276WriteWRegister(dst,6277FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),6278FPZero));6279break;6280case FCVTZS_xs_fixed:6281WriteXRegister(dst,6282FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),6283FPZero));6284break;6285case FCVTZS_ws_fixed:6286WriteWRegister(dst,6287FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),6288FPZero));6289break;6290case FCVTZU_xs_fixed:6291WriteXRegister(dst,6292FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),6293FPZero));6294break;6295case FCVTZU_ws_fixed:6296WriteWRegister(dst,6297FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),6298FPZero));6299break;6300case FCVTZS_xh_fixed: {6301double output =6302static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);6303WriteXRegister(dst, FPToInt64(output, FPZero));6304break;6305}6306case FCVTZS_wh_fixed: {6307double output =6308static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);6309WriteWRegister(dst, FPToInt32(output, FPZero));6310break;6311}6312case FCVTZU_xh_fixed: {6313double output =6314static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);6315WriteXRegister(dst, FPToUInt64(output, FPZero));6316break;6317}6318case FCVTZU_wh_fixed: {6319double output =6320static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);6321WriteWRegister(dst, FPToUInt32(output, FPZero));6322break;6323}6324default:6325VIXL_UNREACHABLE();6326}6327}632863296330void Simulator::VisitFPCompare(const Instruction* instr) {6331AssertSupportedFPCR();63326333FPTrapFlags trap = DisableTrap;6334switch (instr->Mask(FPCompareMask)) {6335case FCMPE_h:6336trap = EnableTrap;6337VIXL_FALLTHROUGH();6338case FCMP_h:6339FPCompare(ReadHRegister(instr->GetRn()),6340ReadHRegister(instr->GetRm()),6341trap);6342break;6343case FCMPE_s:6344trap = EnableTrap;6345VIXL_FALLTHROUGH();6346case FCMP_s:6347FPCompare(ReadSRegister(instr->GetRn()),6348ReadSRegister(instr->GetRm()),6349trap);6350break;6351case FCMPE_d:6352trap = EnableTrap;6353VIXL_FALLTHROUGH();6354case FCMP_d:6355FPCompare(ReadDRegister(instr->GetRn()),6356ReadDRegister(instr->GetRm()),6357trap);6358break;6359case FCMPE_h_zero:6360trap = EnableTrap;6361VIXL_FALLTHROUGH();6362case FCMP_h_zero:6363FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);6364break;6365case FCMPE_s_zero:6366trap = EnableTrap;6367VIXL_FALLTHROUGH();6368case FCMP_s_zero:6369FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);6370break;6371case FCMPE_d_zero:6372trap = EnableTrap;6373VIXL_FALLTHROUGH();6374case FCMP_d_zero:6375FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);6376break;6377default:6378VIXL_UNIMPLEMENTED();6379}6380}638163826383void Simulator::VisitFPConditionalCompare(const Instruction* instr) {6384AssertSupportedFPCR();63856386FPTrapFlags trap = DisableTrap;6387switch (instr->Mask(FPConditionalCompareMask)) {6388case FCCMPE_h:6389trap = EnableTrap;6390VIXL_FALLTHROUGH();6391case FCCMP_h:6392if (ConditionPassed(instr->GetCondition())) {6393FPCompare(ReadHRegister(instr->GetRn()),6394ReadHRegister(instr->GetRm()),6395trap);6396} else {6397ReadNzcv().SetFlags(instr->GetNzcv());6398LogSystemRegister(NZCV);6399}6400break;6401case FCCMPE_s:6402trap = EnableTrap;6403VIXL_FALLTHROUGH();6404case FCCMP_s:6405if (ConditionPassed(instr->GetCondition())) {6406FPCompare(ReadSRegister(instr->GetRn()),6407ReadSRegister(instr->GetRm()),6408trap);6409} else {6410ReadNzcv().SetFlags(instr->GetNzcv());6411LogSystemRegister(NZCV);6412}6413break;6414case FCCMPE_d:6415trap = EnableTrap;6416VIXL_FALLTHROUGH();6417case FCCMP_d:6418if (ConditionPassed(instr->GetCondition())) {6419FPCompare(ReadDRegister(instr->GetRn()),6420ReadDRegister(instr->GetRm()),6421trap);6422} else {6423ReadNzcv().SetFlags(instr->GetNzcv());6424LogSystemRegister(NZCV);6425}6426break;6427default:6428VIXL_UNIMPLEMENTED();6429}6430}643164326433void Simulator::VisitFPConditionalSelect(const Instruction* instr) {6434AssertSupportedFPCR();64356436Instr selected;6437if (ConditionPassed(instr->GetCondition())) {6438selected = instr->GetRn();6439} else {6440selected = instr->GetRm();6441}64426443switch (instr->Mask(FPConditionalSelectMask)) {6444case FCSEL_h:6445WriteHRegister(instr->GetRd(), ReadHRegister(selected));6446break;6447case FCSEL_s:6448WriteSRegister(instr->GetRd(), ReadSRegister(selected));6449break;6450case FCSEL_d:6451WriteDRegister(instr->GetRd(), ReadDRegister(selected));6452break;6453default:6454VIXL_UNIMPLEMENTED();6455}6456}645764586459void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {6460AssertSupportedFPCR();64616462FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());6463VectorFormat vform;6464switch (instr->Mask(FPTypeMask)) {6465default:6466VIXL_UNREACHABLE_OR_FALLTHROUGH();6467case FP64:6468vform = kFormatD;6469break;6470case FP32:6471vform = kFormatS;6472break;6473case FP16:6474vform = kFormatH;6475break;6476}64776478SimVRegister& rd = ReadVRegister(instr->GetRd());6479SimVRegister& rn = ReadVRegister(instr->GetRn());6480bool inexact_exception = false;6481FrintMode frint_mode = kFrintToInteger;64826483unsigned fd = instr->GetRd();6484unsigned fn = instr->GetRn();64856486switch (instr->Mask(FPDataProcessing1SourceMask)) {6487case FMOV_h:6488WriteHRegister(fd, ReadHRegister(fn));6489return;6490case FMOV_s:6491WriteSRegister(fd, ReadSRegister(fn));6492return;6493case FMOV_d:6494WriteDRegister(fd, ReadDRegister(fn));6495return;6496case FABS_h:6497case FABS_s:6498case FABS_d:6499fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));6500// Explicitly log the register update whilst we have type information.6501LogVRegister(fd, GetPrintRegisterFormatFP(vform));6502return;6503case FNEG_h:6504case FNEG_s:6505case FNEG_d:6506fneg(vform, ReadVRegister(fd), ReadVRegister(fn));6507// Explicitly log the register update whilst we have type information.6508LogVRegister(fd, GetPrintRegisterFormatFP(vform));6509return;6510case FCVT_ds:6511WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));6512return;6513case FCVT_sd:6514WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));6515return;6516case FCVT_hs:6517WriteHRegister(fd,6518Float16ToRawbits(6519FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));6520return;6521case FCVT_sh:6522WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));6523return;6524case FCVT_dh:6525WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));6526return;6527case FCVT_hd:6528WriteHRegister(fd,6529Float16ToRawbits(6530FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));6531return;6532case FSQRT_h:6533case FSQRT_s:6534case FSQRT_d:6535fsqrt(vform, rd, rn);6536// Explicitly log the register update whilst we have type information.6537LogVRegister(fd, GetPrintRegisterFormatFP(vform));6538return;6539case FRINT32X_s:6540case FRINT32X_d:6541inexact_exception = true;6542frint_mode = kFrintToInt32;6543break; // Use FPCR rounding mode.6544case FRINT64X_s:6545case FRINT64X_d:6546inexact_exception = true;6547frint_mode = kFrintToInt64;6548break; // Use FPCR rounding mode.6549case FRINT32Z_s:6550case FRINT32Z_d:6551inexact_exception = true;6552frint_mode = kFrintToInt32;6553fpcr_rounding = FPZero;6554break;6555case FRINT64Z_s:6556case FRINT64Z_d:6557inexact_exception = true;6558frint_mode = kFrintToInt64;6559fpcr_rounding = FPZero;6560break;6561case FRINTI_h:6562case FRINTI_s:6563case FRINTI_d:6564break; // Use FPCR rounding mode.6565case FRINTX_h:6566case FRINTX_s:6567case FRINTX_d:6568inexact_exception = true;6569break;6570case FRINTA_h:6571case FRINTA_s:6572case FRINTA_d:6573fpcr_rounding = FPTieAway;6574break;6575case FRINTM_h:6576case FRINTM_s:6577case FRINTM_d:6578fpcr_rounding = FPNegativeInfinity;6579break;6580case FRINTN_h:6581case FRINTN_s:6582case FRINTN_d:6583fpcr_rounding = FPTieEven;6584break;6585case FRINTP_h:6586case FRINTP_s:6587case FRINTP_d:6588fpcr_rounding = FPPositiveInfinity;6589break;6590case FRINTZ_h:6591case FRINTZ_s:6592case FRINTZ_d:6593fpcr_rounding = FPZero;6594break;6595default:6596VIXL_UNIMPLEMENTED();6597}65986599// Only FRINT* instructions fall through the switch above.6600frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);6601// Explicitly log the register update whilst we have type information.6602LogVRegister(fd, GetPrintRegisterFormatFP(vform));6603}660466056606void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {6607AssertSupportedFPCR();66086609VectorFormat vform;6610switch (instr->Mask(FPTypeMask)) {6611default:6612VIXL_UNREACHABLE_OR_FALLTHROUGH();6613case FP64:6614vform = kFormatD;6615break;6616case FP32:6617vform = kFormatS;6618break;6619case FP16:6620vform = kFormatH;6621break;6622}6623SimVRegister& rd = ReadVRegister(instr->GetRd());6624SimVRegister& rn = ReadVRegister(instr->GetRn());6625SimVRegister& rm = ReadVRegister(instr->GetRm());66266627switch (instr->Mask(FPDataProcessing2SourceMask)) {6628case FADD_h:6629case FADD_s:6630case FADD_d:6631fadd(vform, rd, rn, rm);6632break;6633case FSUB_h:6634case FSUB_s:6635case FSUB_d:6636fsub(vform, rd, rn, rm);6637break;6638case FMUL_h:6639case FMUL_s:6640case FMUL_d:6641fmul(vform, rd, rn, rm);6642break;6643case FNMUL_h:6644case FNMUL_s:6645case FNMUL_d:6646fnmul(vform, rd, rn, rm);6647break;6648case FDIV_h:6649case FDIV_s:6650case FDIV_d:6651fdiv(vform, rd, rn, rm);6652break;6653case FMAX_h:6654case FMAX_s:6655case FMAX_d:6656fmax(vform, rd, rn, rm);6657break;6658case FMIN_h:6659case FMIN_s:6660case FMIN_d:6661fmin(vform, rd, rn, rm);6662break;6663case FMAXNM_h:6664case FMAXNM_s:6665case FMAXNM_d:6666fmaxnm(vform, rd, rn, rm);6667break;6668case FMINNM_h:6669case FMINNM_s:6670case FMINNM_d:6671fminnm(vform, rd, rn, rm);6672break;6673default:6674VIXL_UNREACHABLE();6675}6676// Explicitly log the register update whilst we have type information.6677LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));6678}667966806681void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {6682AssertSupportedFPCR();66836684unsigned fd = instr->GetRd();6685unsigned fn = instr->GetRn();6686unsigned fm = instr->GetRm();6687unsigned fa = instr->GetRa();66886689switch (instr->Mask(FPDataProcessing3SourceMask)) {6690// fd = fa +/- (fn * fm)6691case FMADD_h:6692WriteHRegister(fd,6693FPMulAdd(ReadHRegister(fa),6694ReadHRegister(fn),6695ReadHRegister(fm)));6696break;6697case FMSUB_h:6698WriteHRegister(fd,6699FPMulAdd(ReadHRegister(fa),6700-ReadHRegister(fn),6701ReadHRegister(fm)));6702break;6703case FMADD_s:6704WriteSRegister(fd,6705FPMulAdd(ReadSRegister(fa),6706ReadSRegister(fn),6707ReadSRegister(fm)));6708break;6709case FMSUB_s:6710WriteSRegister(fd,6711FPMulAdd(ReadSRegister(fa),6712-ReadSRegister(fn),6713ReadSRegister(fm)));6714break;6715case FMADD_d:6716WriteDRegister(fd,6717FPMulAdd(ReadDRegister(fa),6718ReadDRegister(fn),6719ReadDRegister(fm)));6720break;6721case FMSUB_d:6722WriteDRegister(fd,6723FPMulAdd(ReadDRegister(fa),6724-ReadDRegister(fn),6725ReadDRegister(fm)));6726break;6727// Negated variants of the above.6728case FNMADD_h:6729WriteHRegister(fd,6730FPMulAdd(-ReadHRegister(fa),6731-ReadHRegister(fn),6732ReadHRegister(fm)));6733break;6734case FNMSUB_h:6735WriteHRegister(fd,6736FPMulAdd(-ReadHRegister(fa),6737ReadHRegister(fn),6738ReadHRegister(fm)));6739break;6740case FNMADD_s:6741WriteSRegister(fd,6742FPMulAdd(-ReadSRegister(fa),6743-ReadSRegister(fn),6744ReadSRegister(fm)));6745break;6746case FNMSUB_s:6747WriteSRegister(fd,6748FPMulAdd(-ReadSRegister(fa),6749ReadSRegister(fn),6750ReadSRegister(fm)));6751break;6752case FNMADD_d:6753WriteDRegister(fd,6754FPMulAdd(-ReadDRegister(fa),6755-ReadDRegister(fn),6756ReadDRegister(fm)));6757break;6758case FNMSUB_d:6759WriteDRegister(fd,6760FPMulAdd(-ReadDRegister(fa),6761ReadDRegister(fn),6762ReadDRegister(fm)));6763break;6764default:6765VIXL_UNIMPLEMENTED();6766}6767}676867696770bool Simulator::FPProcessNaNs(const Instruction* instr) {6771unsigned fd = instr->GetRd();6772unsigned fn = instr->GetRn();6773unsigned fm = instr->GetRm();6774bool done = false;67756776if (instr->Mask(FP64) == FP64) {6777double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));6778if (IsNaN(result)) {6779WriteDRegister(fd, result);6780done = true;6781}6782} else if (instr->Mask(FP32) == FP32) {6783float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));6784if (IsNaN(result)) {6785WriteSRegister(fd, result);6786done = true;6787}6788} else {6789VIXL_ASSERT(instr->Mask(FP16) == FP16);6790VIXL_UNIMPLEMENTED();6791}67926793return done;6794}679567966797void Simulator::SysOp_W(int op, int64_t val) {6798switch (op) {6799case IVAU:6800case CVAC:6801case CVAU:6802case CVAP:6803case CVADP:6804case CIVAC:6805case CGVAC:6806case CGDVAC:6807case CGVAP:6808case CGDVAP:6809case CIGVAC:6810case CIGDVAC: {6811// Perform a placeholder memory access to ensure that we have read access6812// to the specified address. The read access does not require a tag match,6813// so temporarily disable MTE.6814bool mte_enabled = MetaDataDepot::MetaDataMTE::IsActive();6815MetaDataDepot::MetaDataMTE::SetActive(false);6816volatile uint8_t y = *MemRead<uint8_t>(val);6817MetaDataDepot::MetaDataMTE::SetActive(mte_enabled);6818USE(y);6819// TODO: Implement ZVA, GVA, GZVA.6820break;6821}6822default:6823VIXL_UNIMPLEMENTED();6824}6825}68266827void Simulator::PACHelper(int dst,6828int src,6829PACKey key,6830decltype(&Simulator::AddPAC) pac_fn) {6831VIXL_ASSERT((dst == 17) || (dst == 30));6832VIXL_ASSERT((src == -1) || (src == 16) || (src == 31));68336834uint64_t modifier = (src == -1) ? 0 : ReadXRegister(src, Reg31IsStackPointer);6835uint64_t result =6836(this->*pac_fn)(ReadXRegister(dst), modifier, key, kInstructionPointer);6837WriteXRegister(dst, result);6838}68396840void Simulator::VisitSystem(const Instruction* instr) {6841PACKey pac_key = kPACKeyIA; // Default key for PAC/AUTH handling.68426843switch (form_hash_) {6844case "cfinv_m_pstate"_h:6845ReadNzcv().SetC(!ReadC());6846break;6847case "axflag_m_pstate"_h:6848ReadNzcv().SetN(0);6849ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());6850ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());6851ReadNzcv().SetV(0);6852break;6853case "xaflag_m_pstate"_h: {6854// Can't set the flags in place due to the logical dependencies.6855uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;6856uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();6857uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();6858uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();6859ReadNzcv().SetN(n);6860ReadNzcv().SetZ(z);6861ReadNzcv().SetC(c);6862ReadNzcv().SetV(v);6863break;6864}6865case "xpaclri_hi_hints"_h:6866WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));6867break;6868case "clrex_bn_barriers"_h:6869PrintExclusiveAccessWarning();6870ClearLocalMonitor();6871break;6872case "msr_sr_systemmove"_h:6873switch (instr->GetImmSystemRegister()) {6874case NZCV:6875ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));6876LogSystemRegister(NZCV);6877break;6878case FPCR:6879ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));6880LogSystemRegister(FPCR);6881break;6882default:6883VIXL_UNIMPLEMENTED();6884}6885break;6886case "mrs_rs_systemmove"_h:6887switch (instr->GetImmSystemRegister()) {6888case NZCV:6889WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());6890break;6891case FPCR:6892WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());6893break;6894case RNDR:6895case RNDRRS: {6896uint64_t high = jrand48(rand_state_);6897uint64_t low = jrand48(rand_state_);6898uint64_t rand_num = (high << 32) | (low & 0xffffffff);6899WriteXRegister(instr->GetRt(), rand_num);6900// Simulate successful random number generation.6901// TODO: Return failure occasionally as a random number cannot be6902// returned in a period of time.6903ReadNzcv().SetRawValue(NoFlag);6904LogSystemRegister(NZCV);6905break;6906}6907default:6908VIXL_UNIMPLEMENTED();6909}6910break;6911case "nop_hi_hints"_h:6912case "esb_hi_hints"_h:6913case "csdb_hi_hints"_h:6914break;6915case "bti_hb_hints"_h:6916switch (instr->GetImmHint()) {6917case BTI_jc:6918break;6919case BTI:6920if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {6921VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");6922}6923break;6924case BTI_c:6925if (PcIsInGuardedPage() &&6926(ReadBType() == BranchFromGuardedNotToIP)) {6927VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");6928}6929break;6930case BTI_j:6931if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {6932VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");6933}6934break;6935default:6936VIXL_UNREACHABLE();6937}6938return;6939case "pacib1716_hi_hints"_h:6940pac_key = kPACKeyIB;6941VIXL_FALLTHROUGH();6942case "pacia1716_hi_hints"_h:6943PACHelper(17, 16, pac_key, &Simulator::AddPAC);6944break;6945case "pacibsp_hi_hints"_h:6946pac_key = kPACKeyIB;6947VIXL_FALLTHROUGH();6948case "paciasp_hi_hints"_h:6949PACHelper(30, 31, pac_key, &Simulator::AddPAC);69506951// Check BType allows PACI[AB]SP instructions.6952if (PcIsInGuardedPage()) {6953switch (ReadBType()) {6954case BranchFromGuardedNotToIP:6955// TODO: This case depends on the value of SCTLR_EL1.BT0, which we6956// assume here to be zero. This allows execution of PACI[AB]SP when6957// BTYPE is BranchFromGuardedNotToIP (0b11).6958case DefaultBType:6959case BranchFromUnguardedOrToIP:6960case BranchAndLink:6961break;6962}6963}6964break;6965case "pacibz_hi_hints"_h:6966pac_key = kPACKeyIB;6967VIXL_FALLTHROUGH();6968case "paciaz_hi_hints"_h:6969PACHelper(30, -1, pac_key, &Simulator::AddPAC);6970break;6971case "autib1716_hi_hints"_h:6972pac_key = kPACKeyIB;6973VIXL_FALLTHROUGH();6974case "autia1716_hi_hints"_h:6975PACHelper(17, 16, pac_key, &Simulator::AuthPAC);6976break;6977case "autibsp_hi_hints"_h:6978pac_key = kPACKeyIB;6979VIXL_FALLTHROUGH();6980case "autiasp_hi_hints"_h:6981PACHelper(30, 31, pac_key, &Simulator::AuthPAC);6982break;6983case "autibz_hi_hints"_h:6984pac_key = kPACKeyIB;6985VIXL_FALLTHROUGH();6986case "autiaz_hi_hints"_h:6987PACHelper(30, -1, pac_key, &Simulator::AuthPAC);6988break;6989case "dsb_bo_barriers"_h:6990case "dmb_bo_barriers"_h:6991case "isb_bi_barriers"_h:6992__sync_synchronize();6993break;6994case "sys_cr_systeminstrs"_h:6995SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));6996break;6997default:6998VIXL_UNIMPLEMENTED();6999}7000}700170027003void Simulator::VisitException(const Instruction* instr) {7004switch (instr->Mask(ExceptionMask)) {7005case HLT:7006switch (instr->GetImmException()) {7007case kUnreachableOpcode:7008DoUnreachable(instr);7009return;7010case kTraceOpcode:7011DoTrace(instr);7012return;7013case kLogOpcode:7014DoLog(instr);7015return;7016case kPrintfOpcode:7017DoPrintf(instr);7018return;7019case kRuntimeCallOpcode:7020DoRuntimeCall(instr);7021return;7022case kSetCPUFeaturesOpcode:7023case kEnableCPUFeaturesOpcode:7024case kDisableCPUFeaturesOpcode:7025DoConfigureCPUFeatures(instr);7026return;7027case kSaveCPUFeaturesOpcode:7028DoSaveCPUFeatures(instr);7029return;7030case kRestoreCPUFeaturesOpcode:7031DoRestoreCPUFeatures(instr);7032return;7033case kMTEActive:7034MetaDataDepot::MetaDataMTE::SetActive(true);7035return;7036case kMTEInactive:7037MetaDataDepot::MetaDataMTE::SetActive(false);7038return;7039default:7040HostBreakpoint();7041return;7042}7043case BRK:7044if (debugger_enabled_) {7045uint64_t next_instr =7046reinterpret_cast<uint64_t>(pc_->GetNextInstruction());7047if (!debugger_->IsBreakpoint(next_instr)) {7048debugger_->RegisterBreakpoint(next_instr);7049}7050} else {7051HostBreakpoint();7052}7053return;7054default:7055VIXL_UNIMPLEMENTED();7056}7057}705870597060void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {7061VisitUnimplemented(instr);7062}706370647065void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {7066VisitUnimplemented(instr);7067}706870697070void Simulator::VisitCryptoAES(const Instruction* instr) {7071VisitUnimplemented(instr);7072}707370747075void Simulator::VisitNEON2RegMisc(const Instruction* instr) {7076NEONFormatDecoder nfd(instr);7077VectorFormat vf = nfd.GetVectorFormat();70787079static const NEONFormatMap map_lp =7080{{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};7081VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);70827083static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};7084VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);70857086static const NEONFormatMap map_fcvtn = {{22, 30},7087{NF_4H, NF_8H, NF_2S, NF_4S}};7088VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);70897090SimVRegister& rd = ReadVRegister(instr->GetRd());7091SimVRegister& rn = ReadVRegister(instr->GetRn());70927093if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {7094// These instructions all use a two bit size field, except NOT and RBIT,7095// which use the field to encode the operation.7096switch (instr->Mask(NEON2RegMiscMask)) {7097case NEON_REV64:7098rev64(vf, rd, rn);7099break;7100case NEON_REV32:7101rev32(vf, rd, rn);7102break;7103case NEON_REV16:7104rev16(vf, rd, rn);7105break;7106case NEON_SUQADD:7107suqadd(vf, rd, rd, rn);7108break;7109case NEON_USQADD:7110usqadd(vf, rd, rd, rn);7111break;7112case NEON_CLS:7113cls(vf, rd, rn);7114break;7115case NEON_CLZ:7116clz(vf, rd, rn);7117break;7118case NEON_CNT:7119cnt(vf, rd, rn);7120break;7121case NEON_SQABS:7122abs(vf, rd, rn).SignedSaturate(vf);7123break;7124case NEON_SQNEG:7125neg(vf, rd, rn).SignedSaturate(vf);7126break;7127case NEON_CMGT_zero:7128cmp(vf, rd, rn, 0, gt);7129break;7130case NEON_CMGE_zero:7131cmp(vf, rd, rn, 0, ge);7132break;7133case NEON_CMEQ_zero:7134cmp(vf, rd, rn, 0, eq);7135break;7136case NEON_CMLE_zero:7137cmp(vf, rd, rn, 0, le);7138break;7139case NEON_CMLT_zero:7140cmp(vf, rd, rn, 0, lt);7141break;7142case NEON_ABS:7143abs(vf, rd, rn);7144break;7145case NEON_NEG:7146neg(vf, rd, rn);7147break;7148case NEON_SADDLP:7149saddlp(vf_lp, rd, rn);7150break;7151case NEON_UADDLP:7152uaddlp(vf_lp, rd, rn);7153break;7154case NEON_SADALP:7155sadalp(vf_lp, rd, rn);7156break;7157case NEON_UADALP:7158uadalp(vf_lp, rd, rn);7159break;7160case NEON_RBIT_NOT:7161vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());7162switch (instr->GetFPType()) {7163case 0:7164not_(vf, rd, rn);7165break;7166case 1:7167rbit(vf, rd, rn);7168break;7169default:7170VIXL_UNIMPLEMENTED();7171}7172break;7173}7174} else {7175VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());7176FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());7177bool inexact_exception = false;7178FrintMode frint_mode = kFrintToInteger;71797180// These instructions all use a one bit size field, except XTN, SQXTUN,7181// SHLL, SQXTN and UQXTN, which use a two bit size field.7182switch (instr->Mask(NEON2RegMiscFPMask)) {7183case NEON_FABS:7184fabs_(fpf, rd, rn);7185return;7186case NEON_FNEG:7187fneg(fpf, rd, rn);7188return;7189case NEON_FSQRT:7190fsqrt(fpf, rd, rn);7191return;7192case NEON_FCVTL:7193if (instr->Mask(NEON_Q)) {7194fcvtl2(vf_fcvtl, rd, rn);7195} else {7196fcvtl(vf_fcvtl, rd, rn);7197}7198return;7199case NEON_FCVTN:7200if (instr->Mask(NEON_Q)) {7201fcvtn2(vf_fcvtn, rd, rn);7202} else {7203fcvtn(vf_fcvtn, rd, rn);7204}7205return;7206case NEON_FCVTXN:7207if (instr->Mask(NEON_Q)) {7208fcvtxn2(vf_fcvtn, rd, rn);7209} else {7210fcvtxn(vf_fcvtn, rd, rn);7211}7212return;72137214// The following instructions break from the switch statement, rather7215// than return.7216case NEON_FRINT32X:7217inexact_exception = true;7218frint_mode = kFrintToInt32;7219break; // Use FPCR rounding mode.7220case NEON_FRINT32Z:7221inexact_exception = true;7222frint_mode = kFrintToInt32;7223fpcr_rounding = FPZero;7224break;7225case NEON_FRINT64X:7226inexact_exception = true;7227frint_mode = kFrintToInt64;7228break; // Use FPCR rounding mode.7229case NEON_FRINT64Z:7230inexact_exception = true;7231frint_mode = kFrintToInt64;7232fpcr_rounding = FPZero;7233break;7234case NEON_FRINTI:7235break; // Use FPCR rounding mode.7236case NEON_FRINTX:7237inexact_exception = true;7238break;7239case NEON_FRINTA:7240fpcr_rounding = FPTieAway;7241break;7242case NEON_FRINTM:7243fpcr_rounding = FPNegativeInfinity;7244break;7245case NEON_FRINTN:7246fpcr_rounding = FPTieEven;7247break;7248case NEON_FRINTP:7249fpcr_rounding = FPPositiveInfinity;7250break;7251case NEON_FRINTZ:7252fpcr_rounding = FPZero;7253break;72547255case NEON_FCVTNS:7256fcvts(fpf, rd, rn, FPTieEven);7257return;7258case NEON_FCVTNU:7259fcvtu(fpf, rd, rn, FPTieEven);7260return;7261case NEON_FCVTPS:7262fcvts(fpf, rd, rn, FPPositiveInfinity);7263return;7264case NEON_FCVTPU:7265fcvtu(fpf, rd, rn, FPPositiveInfinity);7266return;7267case NEON_FCVTMS:7268fcvts(fpf, rd, rn, FPNegativeInfinity);7269return;7270case NEON_FCVTMU:7271fcvtu(fpf, rd, rn, FPNegativeInfinity);7272return;7273case NEON_FCVTZS:7274fcvts(fpf, rd, rn, FPZero);7275return;7276case NEON_FCVTZU:7277fcvtu(fpf, rd, rn, FPZero);7278return;7279case NEON_FCVTAS:7280fcvts(fpf, rd, rn, FPTieAway);7281return;7282case NEON_FCVTAU:7283fcvtu(fpf, rd, rn, FPTieAway);7284return;7285case NEON_SCVTF:7286scvtf(fpf, rd, rn, 0, fpcr_rounding);7287return;7288case NEON_UCVTF:7289ucvtf(fpf, rd, rn, 0, fpcr_rounding);7290return;7291case NEON_URSQRTE:7292ursqrte(fpf, rd, rn);7293return;7294case NEON_URECPE:7295urecpe(fpf, rd, rn);7296return;7297case NEON_FRSQRTE:7298frsqrte(fpf, rd, rn);7299return;7300case NEON_FRECPE:7301frecpe(fpf, rd, rn, fpcr_rounding);7302return;7303case NEON_FCMGT_zero:7304fcmp_zero(fpf, rd, rn, gt);7305return;7306case NEON_FCMGE_zero:7307fcmp_zero(fpf, rd, rn, ge);7308return;7309case NEON_FCMEQ_zero:7310fcmp_zero(fpf, rd, rn, eq);7311return;7312case NEON_FCMLE_zero:7313fcmp_zero(fpf, rd, rn, le);7314return;7315case NEON_FCMLT_zero:7316fcmp_zero(fpf, rd, rn, lt);7317return;7318default:7319if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&7320(instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {7321switch (instr->Mask(NEON2RegMiscMask)) {7322case NEON_XTN:7323xtn(vf, rd, rn);7324return;7325case NEON_SQXTN:7326sqxtn(vf, rd, rn);7327return;7328case NEON_UQXTN:7329uqxtn(vf, rd, rn);7330return;7331case NEON_SQXTUN:7332sqxtun(vf, rd, rn);7333return;7334case NEON_SHLL:7335vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());7336if (instr->Mask(NEON_Q)) {7337shll2(vf, rd, rn);7338} else {7339shll(vf, rd, rn);7340}7341return;7342default:7343VIXL_UNIMPLEMENTED();7344}7345} else {7346VIXL_UNIMPLEMENTED();7347}7348}73497350// Only FRINT* instructions fall through the switch above.7351frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);7352}7353}735473557356void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {7357static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};7358NEONFormatDecoder nfd(instr);7359VectorFormat fpf = nfd.GetVectorFormat(&map_half);73607361FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());73627363SimVRegister& rd = ReadVRegister(instr->GetRd());7364SimVRegister& rn = ReadVRegister(instr->GetRn());73657366switch (instr->Mask(NEON2RegMiscFP16Mask)) {7367case NEON_SCVTF_H:7368scvtf(fpf, rd, rn, 0, fpcr_rounding);7369return;7370case NEON_UCVTF_H:7371ucvtf(fpf, rd, rn, 0, fpcr_rounding);7372return;7373case NEON_FCVTNS_H:7374fcvts(fpf, rd, rn, FPTieEven);7375return;7376case NEON_FCVTNU_H:7377fcvtu(fpf, rd, rn, FPTieEven);7378return;7379case NEON_FCVTPS_H:7380fcvts(fpf, rd, rn, FPPositiveInfinity);7381return;7382case NEON_FCVTPU_H:7383fcvtu(fpf, rd, rn, FPPositiveInfinity);7384return;7385case NEON_FCVTMS_H:7386fcvts(fpf, rd, rn, FPNegativeInfinity);7387return;7388case NEON_FCVTMU_H:7389fcvtu(fpf, rd, rn, FPNegativeInfinity);7390return;7391case NEON_FCVTZS_H:7392fcvts(fpf, rd, rn, FPZero);7393return;7394case NEON_FCVTZU_H:7395fcvtu(fpf, rd, rn, FPZero);7396return;7397case NEON_FCVTAS_H:7398fcvts(fpf, rd, rn, FPTieAway);7399return;7400case NEON_FCVTAU_H:7401fcvtu(fpf, rd, rn, FPTieAway);7402return;7403case NEON_FRINTI_H:7404frint(fpf, rd, rn, fpcr_rounding, false);7405return;7406case NEON_FRINTX_H:7407frint(fpf, rd, rn, fpcr_rounding, true);7408return;7409case NEON_FRINTA_H:7410frint(fpf, rd, rn, FPTieAway, false);7411return;7412case NEON_FRINTM_H:7413frint(fpf, rd, rn, FPNegativeInfinity, false);7414return;7415case NEON_FRINTN_H:7416frint(fpf, rd, rn, FPTieEven, false);7417return;7418case NEON_FRINTP_H:7419frint(fpf, rd, rn, FPPositiveInfinity, false);7420return;7421case NEON_FRINTZ_H:7422frint(fpf, rd, rn, FPZero, false);7423return;7424case NEON_FABS_H:7425fabs_(fpf, rd, rn);7426return;7427case NEON_FNEG_H:7428fneg(fpf, rd, rn);7429return;7430case NEON_FSQRT_H:7431fsqrt(fpf, rd, rn);7432return;7433case NEON_FRSQRTE_H:7434frsqrte(fpf, rd, rn);7435return;7436case NEON_FRECPE_H:7437frecpe(fpf, rd, rn, fpcr_rounding);7438return;7439case NEON_FCMGT_H_zero:7440fcmp_zero(fpf, rd, rn, gt);7441return;7442case NEON_FCMGE_H_zero:7443fcmp_zero(fpf, rd, rn, ge);7444return;7445case NEON_FCMEQ_H_zero:7446fcmp_zero(fpf, rd, rn, eq);7447return;7448case NEON_FCMLE_H_zero:7449fcmp_zero(fpf, rd, rn, le);7450return;7451case NEON_FCMLT_H_zero:7452fcmp_zero(fpf, rd, rn, lt);7453return;7454default:7455VIXL_UNIMPLEMENTED();7456return;7457}7458}745974607461void Simulator::VisitNEON3Same(const Instruction* instr) {7462NEONFormatDecoder nfd(instr);7463SimVRegister& rd = ReadVRegister(instr->GetRd());7464SimVRegister& rn = ReadVRegister(instr->GetRn());7465SimVRegister& rm = ReadVRegister(instr->GetRm());74667467if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {7468VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());7469switch (instr->Mask(NEON3SameLogicalMask)) {7470case NEON_AND:7471and_(vf, rd, rn, rm);7472break;7473case NEON_ORR:7474orr(vf, rd, rn, rm);7475break;7476case NEON_ORN:7477orn(vf, rd, rn, rm);7478break;7479case NEON_EOR:7480eor(vf, rd, rn, rm);7481break;7482case NEON_BIC:7483bic(vf, rd, rn, rm);7484break;7485case NEON_BIF:7486bif(vf, rd, rn, rm);7487break;7488case NEON_BIT:7489bit(vf, rd, rn, rm);7490break;7491case NEON_BSL:7492bsl(vf, rd, rd, rn, rm);7493break;7494default:7495VIXL_UNIMPLEMENTED();7496}7497} else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {7498VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());7499switch (instr->Mask(NEON3SameFPMask)) {7500case NEON_FADD:7501fadd(vf, rd, rn, rm);7502break;7503case NEON_FSUB:7504fsub(vf, rd, rn, rm);7505break;7506case NEON_FMUL:7507fmul(vf, rd, rn, rm);7508break;7509case NEON_FDIV:7510fdiv(vf, rd, rn, rm);7511break;7512case NEON_FMAX:7513fmax(vf, rd, rn, rm);7514break;7515case NEON_FMIN:7516fmin(vf, rd, rn, rm);7517break;7518case NEON_FMAXNM:7519fmaxnm(vf, rd, rn, rm);7520break;7521case NEON_FMINNM:7522fminnm(vf, rd, rn, rm);7523break;7524case NEON_FMLA:7525fmla(vf, rd, rd, rn, rm);7526break;7527case NEON_FMLS:7528fmls(vf, rd, rd, rn, rm);7529break;7530case NEON_FMULX:7531fmulx(vf, rd, rn, rm);7532break;7533case NEON_FACGE:7534fabscmp(vf, rd, rn, rm, ge);7535break;7536case NEON_FACGT:7537fabscmp(vf, rd, rn, rm, gt);7538break;7539case NEON_FCMEQ:7540fcmp(vf, rd, rn, rm, eq);7541break;7542case NEON_FCMGE:7543fcmp(vf, rd, rn, rm, ge);7544break;7545case NEON_FCMGT:7546fcmp(vf, rd, rn, rm, gt);7547break;7548case NEON_FRECPS:7549frecps(vf, rd, rn, rm);7550break;7551case NEON_FRSQRTS:7552frsqrts(vf, rd, rn, rm);7553break;7554case NEON_FABD:7555fabd(vf, rd, rn, rm);7556break;7557case NEON_FADDP:7558faddp(vf, rd, rn, rm);7559break;7560case NEON_FMAXP:7561fmaxp(vf, rd, rn, rm);7562break;7563case NEON_FMAXNMP:7564fmaxnmp(vf, rd, rn, rm);7565break;7566case NEON_FMINP:7567fminp(vf, rd, rn, rm);7568break;7569case NEON_FMINNMP:7570fminnmp(vf, rd, rn, rm);7571break;7572default:7573// FMLAL{2} and FMLSL{2} have special-case encodings.7574switch (instr->Mask(NEON3SameFHMMask)) {7575case NEON_FMLAL:7576fmlal(vf, rd, rn, rm);7577break;7578case NEON_FMLAL2:7579fmlal2(vf, rd, rn, rm);7580break;7581case NEON_FMLSL:7582fmlsl(vf, rd, rn, rm);7583break;7584case NEON_FMLSL2:7585fmlsl2(vf, rd, rn, rm);7586break;7587default:7588VIXL_UNIMPLEMENTED();7589}7590}7591} else {7592VectorFormat vf = nfd.GetVectorFormat();7593switch (instr->Mask(NEON3SameMask)) {7594case NEON_ADD:7595add(vf, rd, rn, rm);7596break;7597case NEON_ADDP:7598addp(vf, rd, rn, rm);7599break;7600case NEON_CMEQ:7601cmp(vf, rd, rn, rm, eq);7602break;7603case NEON_CMGE:7604cmp(vf, rd, rn, rm, ge);7605break;7606case NEON_CMGT:7607cmp(vf, rd, rn, rm, gt);7608break;7609case NEON_CMHI:7610cmp(vf, rd, rn, rm, hi);7611break;7612case NEON_CMHS:7613cmp(vf, rd, rn, rm, hs);7614break;7615case NEON_CMTST:7616cmptst(vf, rd, rn, rm);7617break;7618case NEON_MLS:7619mls(vf, rd, rd, rn, rm);7620break;7621case NEON_MLA:7622mla(vf, rd, rd, rn, rm);7623break;7624case NEON_MUL:7625mul(vf, rd, rn, rm);7626break;7627case NEON_PMUL:7628pmul(vf, rd, rn, rm);7629break;7630case NEON_SMAX:7631smax(vf, rd, rn, rm);7632break;7633case NEON_SMAXP:7634smaxp(vf, rd, rn, rm);7635break;7636case NEON_SMIN:7637smin(vf, rd, rn, rm);7638break;7639case NEON_SMINP:7640sminp(vf, rd, rn, rm);7641break;7642case NEON_SUB:7643sub(vf, rd, rn, rm);7644break;7645case NEON_UMAX:7646umax(vf, rd, rn, rm);7647break;7648case NEON_UMAXP:7649umaxp(vf, rd, rn, rm);7650break;7651case NEON_UMIN:7652umin(vf, rd, rn, rm);7653break;7654case NEON_UMINP:7655uminp(vf, rd, rn, rm);7656break;7657case NEON_SSHL:7658sshl(vf, rd, rn, rm);7659break;7660case NEON_USHL:7661ushl(vf, rd, rn, rm);7662break;7663case NEON_SABD:7664absdiff(vf, rd, rn, rm, true);7665break;7666case NEON_UABD:7667absdiff(vf, rd, rn, rm, false);7668break;7669case NEON_SABA:7670saba(vf, rd, rn, rm);7671break;7672case NEON_UABA:7673uaba(vf, rd, rn, rm);7674break;7675case NEON_UQADD:7676add(vf, rd, rn, rm).UnsignedSaturate(vf);7677break;7678case NEON_SQADD:7679add(vf, rd, rn, rm).SignedSaturate(vf);7680break;7681case NEON_UQSUB:7682sub(vf, rd, rn, rm).UnsignedSaturate(vf);7683break;7684case NEON_SQSUB:7685sub(vf, rd, rn, rm).SignedSaturate(vf);7686break;7687case NEON_SQDMULH:7688sqdmulh(vf, rd, rn, rm);7689break;7690case NEON_SQRDMULH:7691sqrdmulh(vf, rd, rn, rm);7692break;7693case NEON_UQSHL:7694ushl(vf, rd, rn, rm).UnsignedSaturate(vf);7695break;7696case NEON_SQSHL:7697sshl(vf, rd, rn, rm).SignedSaturate(vf);7698break;7699case NEON_URSHL:7700ushl(vf, rd, rn, rm).Round(vf);7701break;7702case NEON_SRSHL:7703sshl(vf, rd, rn, rm).Round(vf);7704break;7705case NEON_UQRSHL:7706ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);7707break;7708case NEON_SQRSHL:7709sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);7710break;7711case NEON_UHADD:7712add(vf, rd, rn, rm).Uhalve(vf);7713break;7714case NEON_URHADD:7715add(vf, rd, rn, rm).Uhalve(vf).Round(vf);7716break;7717case NEON_SHADD:7718add(vf, rd, rn, rm).Halve(vf);7719break;7720case NEON_SRHADD:7721add(vf, rd, rn, rm).Halve(vf).Round(vf);7722break;7723case NEON_UHSUB:7724sub(vf, rd, rn, rm).Uhalve(vf);7725break;7726case NEON_SHSUB:7727sub(vf, rd, rn, rm).Halve(vf);7728break;7729default:7730VIXL_UNIMPLEMENTED();7731}7732}7733}773477357736void Simulator::VisitNEON3SameFP16(const Instruction* instr) {7737NEONFormatDecoder nfd(instr);7738SimVRegister& rd = ReadVRegister(instr->GetRd());7739SimVRegister& rn = ReadVRegister(instr->GetRn());7740SimVRegister& rm = ReadVRegister(instr->GetRm());77417742VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());7743switch (instr->Mask(NEON3SameFP16Mask)) {7744#define SIM_FUNC(A, B) \7745case NEON_##A##_H: \7746B(vf, rd, rn, rm); \7747break;7748SIM_FUNC(FMAXNM, fmaxnm);7749SIM_FUNC(FADD, fadd);7750SIM_FUNC(FMULX, fmulx);7751SIM_FUNC(FMAX, fmax);7752SIM_FUNC(FRECPS, frecps);7753SIM_FUNC(FMINNM, fminnm);7754SIM_FUNC(FSUB, fsub);7755SIM_FUNC(FMIN, fmin);7756SIM_FUNC(FRSQRTS, frsqrts);7757SIM_FUNC(FMAXNMP, fmaxnmp);7758SIM_FUNC(FADDP, faddp);7759SIM_FUNC(FMUL, fmul);7760SIM_FUNC(FMAXP, fmaxp);7761SIM_FUNC(FDIV, fdiv);7762SIM_FUNC(FMINNMP, fminnmp);7763SIM_FUNC(FABD, fabd);7764SIM_FUNC(FMINP, fminp);7765#undef SIM_FUNC7766case NEON_FMLA_H:7767fmla(vf, rd, rd, rn, rm);7768break;7769case NEON_FMLS_H:7770fmls(vf, rd, rd, rn, rm);7771break;7772case NEON_FCMEQ_H:7773fcmp(vf, rd, rn, rm, eq);7774break;7775case NEON_FCMGE_H:7776fcmp(vf, rd, rn, rm, ge);7777break;7778case NEON_FACGE_H:7779fabscmp(vf, rd, rn, rm, ge);7780break;7781case NEON_FCMGT_H:7782fcmp(vf, rd, rn, rm, gt);7783break;7784case NEON_FACGT_H:7785fabscmp(vf, rd, rn, rm, gt);7786break;7787default:7788VIXL_UNIMPLEMENTED();7789break;7790}7791}77927793void Simulator::VisitNEON3SameExtra(const Instruction* instr) {7794NEONFormatDecoder nfd(instr);7795SimVRegister& rd = ReadVRegister(instr->GetRd());7796SimVRegister& rn = ReadVRegister(instr->GetRn());7797SimVRegister& rm = ReadVRegister(instr->GetRm());7798int rot = 0;7799VectorFormat vf = nfd.GetVectorFormat();78007801switch (form_hash_) {7802case "fcmla_asimdsame2_c"_h:7803rot = instr->GetImmRotFcmlaVec();7804fcmla(vf, rd, rn, rm, rd, rot);7805break;7806case "fcadd_asimdsame2_c"_h:7807rot = instr->GetImmRotFcadd();7808fcadd(vf, rd, rn, rm, rot);7809break;7810case "sdot_asimdsame2_d"_h:7811sdot(vf, rd, rn, rm);7812break;7813case "udot_asimdsame2_d"_h:7814udot(vf, rd, rn, rm);7815break;7816case "usdot_asimdsame2_d"_h:7817usdot(vf, rd, rn, rm);7818break;7819case "sqrdmlah_asimdsame2_only"_h:7820sqrdmlah(vf, rd, rn, rm);7821break;7822case "sqrdmlsh_asimdsame2_only"_h:7823sqrdmlsh(vf, rd, rn, rm);7824break;7825}7826}782778287829void Simulator::VisitNEON3Different(const Instruction* instr) {7830NEONFormatDecoder nfd(instr);7831VectorFormat vf = nfd.GetVectorFormat();7832VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());78337834SimVRegister& rd = ReadVRegister(instr->GetRd());7835SimVRegister& rn = ReadVRegister(instr->GetRn());7836SimVRegister& rm = ReadVRegister(instr->GetRm());7837int size = instr->GetNEONSize();78387839switch (instr->Mask(NEON3DifferentMask)) {7840case NEON_PMULL:7841if ((size == 1) || (size == 2)) { // S/D reserved.7842VisitUnallocated(instr);7843} else {7844if (size == 3) vf_l = kFormat1Q;7845pmull(vf_l, rd, rn, rm);7846}7847break;7848case NEON_PMULL2:7849if ((size == 1) || (size == 2)) { // S/D reserved.7850VisitUnallocated(instr);7851} else {7852if (size == 3) vf_l = kFormat1Q;7853pmull2(vf_l, rd, rn, rm);7854}7855break;7856case NEON_UADDL:7857uaddl(vf_l, rd, rn, rm);7858break;7859case NEON_UADDL2:7860uaddl2(vf_l, rd, rn, rm);7861break;7862case NEON_SADDL:7863saddl(vf_l, rd, rn, rm);7864break;7865case NEON_SADDL2:7866saddl2(vf_l, rd, rn, rm);7867break;7868case NEON_USUBL:7869usubl(vf_l, rd, rn, rm);7870break;7871case NEON_USUBL2:7872usubl2(vf_l, rd, rn, rm);7873break;7874case NEON_SSUBL:7875ssubl(vf_l, rd, rn, rm);7876break;7877case NEON_SSUBL2:7878ssubl2(vf_l, rd, rn, rm);7879break;7880case NEON_SABAL:7881sabal(vf_l, rd, rn, rm);7882break;7883case NEON_SABAL2:7884sabal2(vf_l, rd, rn, rm);7885break;7886case NEON_UABAL:7887uabal(vf_l, rd, rn, rm);7888break;7889case NEON_UABAL2:7890uabal2(vf_l, rd, rn, rm);7891break;7892case NEON_SABDL:7893sabdl(vf_l, rd, rn, rm);7894break;7895case NEON_SABDL2:7896sabdl2(vf_l, rd, rn, rm);7897break;7898case NEON_UABDL:7899uabdl(vf_l, rd, rn, rm);7900break;7901case NEON_UABDL2:7902uabdl2(vf_l, rd, rn, rm);7903break;7904case NEON_SMLAL:7905smlal(vf_l, rd, rn, rm);7906break;7907case NEON_SMLAL2:7908smlal2(vf_l, rd, rn, rm);7909break;7910case NEON_UMLAL:7911umlal(vf_l, rd, rn, rm);7912break;7913case NEON_UMLAL2:7914umlal2(vf_l, rd, rn, rm);7915break;7916case NEON_SMLSL:7917smlsl(vf_l, rd, rn, rm);7918break;7919case NEON_SMLSL2:7920smlsl2(vf_l, rd, rn, rm);7921break;7922case NEON_UMLSL:7923umlsl(vf_l, rd, rn, rm);7924break;7925case NEON_UMLSL2:7926umlsl2(vf_l, rd, rn, rm);7927break;7928case NEON_SMULL:7929smull(vf_l, rd, rn, rm);7930break;7931case NEON_SMULL2:7932smull2(vf_l, rd, rn, rm);7933break;7934case NEON_UMULL:7935umull(vf_l, rd, rn, rm);7936break;7937case NEON_UMULL2:7938umull2(vf_l, rd, rn, rm);7939break;7940case NEON_SQDMLAL:7941sqdmlal(vf_l, rd, rn, rm);7942break;7943case NEON_SQDMLAL2:7944sqdmlal2(vf_l, rd, rn, rm);7945break;7946case NEON_SQDMLSL:7947sqdmlsl(vf_l, rd, rn, rm);7948break;7949case NEON_SQDMLSL2:7950sqdmlsl2(vf_l, rd, rn, rm);7951break;7952case NEON_SQDMULL:7953sqdmull(vf_l, rd, rn, rm);7954break;7955case NEON_SQDMULL2:7956sqdmull2(vf_l, rd, rn, rm);7957break;7958case NEON_UADDW:7959uaddw(vf_l, rd, rn, rm);7960break;7961case NEON_UADDW2:7962uaddw2(vf_l, rd, rn, rm);7963break;7964case NEON_SADDW:7965saddw(vf_l, rd, rn, rm);7966break;7967case NEON_SADDW2:7968saddw2(vf_l, rd, rn, rm);7969break;7970case NEON_USUBW:7971usubw(vf_l, rd, rn, rm);7972break;7973case NEON_USUBW2:7974usubw2(vf_l, rd, rn, rm);7975break;7976case NEON_SSUBW:7977ssubw(vf_l, rd, rn, rm);7978break;7979case NEON_SSUBW2:7980ssubw2(vf_l, rd, rn, rm);7981break;7982case NEON_ADDHN:7983addhn(vf, rd, rn, rm);7984break;7985case NEON_ADDHN2:7986addhn2(vf, rd, rn, rm);7987break;7988case NEON_RADDHN:7989raddhn(vf, rd, rn, rm);7990break;7991case NEON_RADDHN2:7992raddhn2(vf, rd, rn, rm);7993break;7994case NEON_SUBHN:7995subhn(vf, rd, rn, rm);7996break;7997case NEON_SUBHN2:7998subhn2(vf, rd, rn, rm);7999break;8000case NEON_RSUBHN:8001rsubhn(vf, rd, rn, rm);8002break;8003case NEON_RSUBHN2:8004rsubhn2(vf, rd, rn, rm);8005break;8006default:8007VIXL_UNIMPLEMENTED();8008}8009}801080118012void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {8013NEONFormatDecoder nfd(instr);80148015static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};80168017SimVRegister& rd = ReadVRegister(instr->GetRd());8018SimVRegister& rn = ReadVRegister(instr->GetRn());80198020if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {8021VectorFormat vf = nfd.GetVectorFormat(&map_half);8022switch (instr->Mask(NEONAcrossLanesFP16Mask)) {8023case NEON_FMAXV_H:8024fmaxv(vf, rd, rn);8025break;8026case NEON_FMINV_H:8027fminv(vf, rd, rn);8028break;8029case NEON_FMAXNMV_H:8030fmaxnmv(vf, rd, rn);8031break;8032case NEON_FMINNMV_H:8033fminnmv(vf, rd, rn);8034break;8035default:8036VIXL_UNIMPLEMENTED();8037}8038} else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {8039// The input operand's VectorFormat is passed for these instructions.8040VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());80418042switch (instr->Mask(NEONAcrossLanesFPMask)) {8043case NEON_FMAXV:8044fmaxv(vf, rd, rn);8045break;8046case NEON_FMINV:8047fminv(vf, rd, rn);8048break;8049case NEON_FMAXNMV:8050fmaxnmv(vf, rd, rn);8051break;8052case NEON_FMINNMV:8053fminnmv(vf, rd, rn);8054break;8055default:8056VIXL_UNIMPLEMENTED();8057}8058} else {8059VectorFormat vf = nfd.GetVectorFormat();80608061switch (instr->Mask(NEONAcrossLanesMask)) {8062case NEON_ADDV:8063addv(vf, rd, rn);8064break;8065case NEON_SMAXV:8066smaxv(vf, rd, rn);8067break;8068case NEON_SMINV:8069sminv(vf, rd, rn);8070break;8071case NEON_UMAXV:8072umaxv(vf, rd, rn);8073break;8074case NEON_UMINV:8075uminv(vf, rd, rn);8076break;8077case NEON_SADDLV:8078saddlv(vf, rd, rn);8079break;8080case NEON_UADDLV:8081uaddlv(vf, rd, rn);8082break;8083default:8084VIXL_UNIMPLEMENTED();8085}8086}8087}80888089void Simulator::SimulateNEONMulByElementLong(const Instruction* instr) {8090NEONFormatDecoder nfd(instr);8091VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());80928093SimVRegister& rd = ReadVRegister(instr->GetRd());8094SimVRegister& rn = ReadVRegister(instr->GetRn());80958096int rm_reg = instr->GetRm();8097int index = (instr->GetNEONH() << 1) | instr->GetNEONL();8098if (instr->GetNEONSize() == 1) {8099rm_reg = instr->GetRmLow16();8100index = (index << 1) | instr->GetNEONM();8101}8102SimVRegister& rm = ReadVRegister(rm_reg);81038104SimVRegister temp;8105VectorFormat indexform =8106VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vf));8107dup_element(indexform, temp, rm, index);81088109bool is_2 = instr->Mask(NEON_Q) ? true : false;81108111switch (form_hash_) {8112case "smull_asimdelem_l"_h:8113smull(vf, rd, rn, temp, is_2);8114break;8115case "umull_asimdelem_l"_h:8116umull(vf, rd, rn, temp, is_2);8117break;8118case "smlal_asimdelem_l"_h:8119smlal(vf, rd, rn, temp, is_2);8120break;8121case "umlal_asimdelem_l"_h:8122umlal(vf, rd, rn, temp, is_2);8123break;8124case "smlsl_asimdelem_l"_h:8125smlsl(vf, rd, rn, temp, is_2);8126break;8127case "umlsl_asimdelem_l"_h:8128umlsl(vf, rd, rn, temp, is_2);8129break;8130case "sqdmull_asimdelem_l"_h:8131sqdmull(vf, rd, rn, temp, is_2);8132break;8133case "sqdmlal_asimdelem_l"_h:8134sqdmlal(vf, rd, rn, temp, is_2);8135break;8136case "sqdmlsl_asimdelem_l"_h:8137sqdmlsl(vf, rd, rn, temp, is_2);8138break;8139default:8140VIXL_UNREACHABLE();8141}8142}81438144void Simulator::SimulateNEONFPMulByElementLong(const Instruction* instr) {8145VectorFormat vform = instr->GetNEONQ() ? kFormat4S : kFormat2S;8146SimVRegister& rd = ReadVRegister(instr->GetRd());8147SimVRegister& rn = ReadVRegister(instr->GetRn());8148SimVRegister& rm = ReadVRegister(instr->GetRmLow16());81498150int index =8151(instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();81528153switch (form_hash_) {8154case "fmlal_asimdelem_lh"_h:8155fmlal(vform, rd, rn, rm, index);8156break;8157case "fmlal2_asimdelem_lh"_h:8158fmlal2(vform, rd, rn, rm, index);8159break;8160case "fmlsl_asimdelem_lh"_h:8161fmlsl(vform, rd, rn, rm, index);8162break;8163case "fmlsl2_asimdelem_lh"_h:8164fmlsl2(vform, rd, rn, rm, index);8165break;8166default:8167VIXL_UNREACHABLE();8168}8169}81708171void Simulator::SimulateNEONFPMulByElement(const Instruction* instr) {8172NEONFormatDecoder nfd(instr);8173static const NEONFormatMap map =8174{{23, 22, 30},8175{NF_4H, NF_8H, NF_UNDEF, NF_UNDEF, NF_2S, NF_4S, NF_UNDEF, NF_2D}};8176VectorFormat vform = nfd.GetVectorFormat(&map);81778178SimVRegister& rd = ReadVRegister(instr->GetRd());8179SimVRegister& rn = ReadVRegister(instr->GetRn());81808181int rm_reg = instr->GetRm();8182int index =8183(instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();81848185if ((vform == kFormat4H) || (vform == kFormat8H)) {8186rm_reg &= 0xf;8187} else if ((vform == kFormat2S) || (vform == kFormat4S)) {8188index >>= 1;8189} else {8190VIXL_ASSERT(vform == kFormat2D);8191VIXL_ASSERT(instr->GetNEONL() == 0);8192index >>= 2;8193}81948195SimVRegister& rm = ReadVRegister(rm_reg);81968197switch (form_hash_) {8198case "fmul_asimdelem_rh_h"_h:8199case "fmul_asimdelem_r_sd"_h:8200fmul(vform, rd, rn, rm, index);8201break;8202case "fmla_asimdelem_rh_h"_h:8203case "fmla_asimdelem_r_sd"_h:8204fmla(vform, rd, rn, rm, index);8205break;8206case "fmls_asimdelem_rh_h"_h:8207case "fmls_asimdelem_r_sd"_h:8208fmls(vform, rd, rn, rm, index);8209break;8210case "fmulx_asimdelem_rh_h"_h:8211case "fmulx_asimdelem_r_sd"_h:8212fmulx(vform, rd, rn, rm, index);8213break;8214default:8215VIXL_UNREACHABLE();8216}8217}82188219void Simulator::SimulateNEONComplexMulByElement(const Instruction* instr) {8220VectorFormat vform = instr->GetNEONQ() ? kFormat8H : kFormat4H;8221SimVRegister& rd = ReadVRegister(instr->GetRd());8222SimVRegister& rn = ReadVRegister(instr->GetRn());8223SimVRegister& rm = ReadVRegister(instr->GetRm());8224int index = (instr->GetNEONH() << 1) | instr->GetNEONL();82258226switch (form_hash_) {8227case "fcmla_asimdelem_c_s"_h:8228vform = kFormat4S;8229index >>= 1;8230VIXL_FALLTHROUGH();8231case "fcmla_asimdelem_c_h"_h:8232fcmla(vform, rd, rn, rm, index, instr->GetImmRotFcmlaSca());8233break;8234default:8235VIXL_UNREACHABLE();8236}8237}82388239void Simulator::SimulateNEONDotProdByElement(const Instruction* instr) {8240VectorFormat vform = instr->GetNEONQ() ? kFormat4S : kFormat2S;82418242SimVRegister& rd = ReadVRegister(instr->GetRd());8243SimVRegister& rn = ReadVRegister(instr->GetRn());8244SimVRegister& rm = ReadVRegister(instr->GetRm());8245int index = (instr->GetNEONH() << 1) | instr->GetNEONL();82468247SimVRegister temp;8248// NEON indexed `dot` allows the index value exceed the register size.8249// Promote the format to Q-sized vector format before the duplication.8250dup_elements_to_segments(VectorFormatFillQ(vform), temp, rm, index);82518252switch (form_hash_) {8253case "sdot_asimdelem_d"_h:8254sdot(vform, rd, rn, temp);8255break;8256case "udot_asimdelem_d"_h:8257udot(vform, rd, rn, temp);8258break;8259case "sudot_asimdelem_d"_h:8260usdot(vform, rd, temp, rn);8261break;8262case "usdot_asimdelem_d"_h:8263usdot(vform, rd, rn, temp);8264break;8265}8266}82678268void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {8269NEONFormatDecoder nfd(instr);8270VectorFormat vform = nfd.GetVectorFormat();82718272SimVRegister& rd = ReadVRegister(instr->GetRd());8273SimVRegister& rn = ReadVRegister(instr->GetRn());82748275int rm_reg = instr->GetRm();8276int index = (instr->GetNEONH() << 1) | instr->GetNEONL();82778278if ((vform == kFormat4H) || (vform == kFormat8H)) {8279rm_reg &= 0xf;8280index = (index << 1) | instr->GetNEONM();8281}82828283SimVRegister& rm = ReadVRegister(rm_reg);82848285switch (form_hash_) {8286case "mul_asimdelem_r"_h:8287mul(vform, rd, rn, rm, index);8288break;8289case "mla_asimdelem_r"_h:8290mla(vform, rd, rn, rm, index);8291break;8292case "mls_asimdelem_r"_h:8293mls(vform, rd, rn, rm, index);8294break;8295case "sqdmulh_asimdelem_r"_h:8296sqdmulh(vform, rd, rn, rm, index);8297break;8298case "sqrdmulh_asimdelem_r"_h:8299sqrdmulh(vform, rd, rn, rm, index);8300break;8301case "sqrdmlah_asimdelem_r"_h:8302sqrdmlah(vform, rd, rn, rm, index);8303break;8304case "sqrdmlsh_asimdelem_r"_h:8305sqrdmlsh(vform, rd, rn, rm, index);8306break;8307}8308}830983108311void Simulator::VisitNEONCopy(const Instruction* instr) {8312NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());8313VectorFormat vf = nfd.GetVectorFormat();83148315SimVRegister& rd = ReadVRegister(instr->GetRd());8316SimVRegister& rn = ReadVRegister(instr->GetRn());8317int imm5 = instr->GetImmNEON5();8318int tz = CountTrailingZeros(imm5, 32);8319int reg_index = ExtractSignedBitfield32(31, tz + 1, imm5);83208321if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {8322int imm4 = instr->GetImmNEON4();8323int rn_index = ExtractSignedBitfield32(31, tz, imm4);8324mov(kFormat16B, rd, rd); // Zero bits beyond the MSB of a Q register.8325ins_element(vf, rd, reg_index, rn, rn_index);8326} else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {8327mov(kFormat16B, rd, rd); // Zero bits beyond the MSB of a Q register.8328ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));8329} else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {8330uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);8331value &= MaxUintFromFormat(vf);8332WriteXRegister(instr->GetRd(), value);8333} else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {8334int64_t value = LogicVRegister(rn).Int(vf, reg_index);8335if (instr->GetNEONQ()) {8336WriteXRegister(instr->GetRd(), value);8337} else {8338WriteWRegister(instr->GetRd(), (int32_t)value);8339}8340} else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {8341dup_element(vf, rd, rn, reg_index);8342} else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {8343dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));8344} else {8345VIXL_UNIMPLEMENTED();8346}8347}834883498350void Simulator::VisitNEONExtract(const Instruction* instr) {8351NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());8352VectorFormat vf = nfd.GetVectorFormat();8353SimVRegister& rd = ReadVRegister(instr->GetRd());8354SimVRegister& rn = ReadVRegister(instr->GetRn());8355SimVRegister& rm = ReadVRegister(instr->GetRm());8356if (instr->Mask(NEONExtractMask) == NEON_EXT) {8357int index = instr->GetImmNEONExt();8358ext(vf, rd, rn, rm, index);8359} else {8360VIXL_UNIMPLEMENTED();8361}8362}836383648365void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,8366AddrMode addr_mode) {8367NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());8368VectorFormat vf = nfd.GetVectorFormat();83698370uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);8371int reg_size = RegisterSizeInBytesFromFormat(vf);83728373int reg[4];8374uint64_t addr[4];8375for (int i = 0; i < 4; i++) {8376reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;8377addr[i] = addr_base + (i * reg_size);8378}8379int struct_parts = 1;8380int reg_count = 1;8381bool log_read = true;83828383// Bit 23 determines whether this is an offset or post-index addressing mode.8384// In offset mode, bits 20 to 16 should be zero; these bits encode the8385// register or immediate in post-index mode.8386if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {8387VIXL_UNREACHABLE();8388}83898390// We use the PostIndex mask here, as it works in this case for both Offset8391// and PostIndex addressing.8392switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {8393case NEON_LD1_4v:8394case NEON_LD1_4v_post:8395if (!ld1(vf, ReadVRegister(reg[3]), addr[3])) {8396return;8397}8398reg_count++;8399VIXL_FALLTHROUGH();8400case NEON_LD1_3v:8401case NEON_LD1_3v_post:8402if (!ld1(vf, ReadVRegister(reg[2]), addr[2])) {8403return;8404}8405reg_count++;8406VIXL_FALLTHROUGH();8407case NEON_LD1_2v:8408case NEON_LD1_2v_post:8409if (!ld1(vf, ReadVRegister(reg[1]), addr[1])) {8410return;8411}8412reg_count++;8413VIXL_FALLTHROUGH();8414case NEON_LD1_1v:8415case NEON_LD1_1v_post:8416if (!ld1(vf, ReadVRegister(reg[0]), addr[0])) {8417return;8418}8419break;8420case NEON_ST1_4v:8421case NEON_ST1_4v_post:8422if (!st1(vf, ReadVRegister(reg[3]), addr[3])) return;8423reg_count++;8424VIXL_FALLTHROUGH();8425case NEON_ST1_3v:8426case NEON_ST1_3v_post:8427if (!st1(vf, ReadVRegister(reg[2]), addr[2])) return;8428reg_count++;8429VIXL_FALLTHROUGH();8430case NEON_ST1_2v:8431case NEON_ST1_2v_post:8432if (!st1(vf, ReadVRegister(reg[1]), addr[1])) return;8433reg_count++;8434VIXL_FALLTHROUGH();8435case NEON_ST1_1v:8436case NEON_ST1_1v_post:8437if (!st1(vf, ReadVRegister(reg[0]), addr[0])) return;8438log_read = false;8439break;8440case NEON_LD2_post:8441case NEON_LD2:8442if (!ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0])) {8443return;8444}8445struct_parts = 2;8446reg_count = 2;8447break;8448case NEON_ST2:8449case NEON_ST2_post:8450if (!st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0])) {8451return;8452}8453struct_parts = 2;8454reg_count = 2;8455log_read = false;8456break;8457case NEON_LD3_post:8458case NEON_LD3:8459if (!ld3(vf,8460ReadVRegister(reg[0]),8461ReadVRegister(reg[1]),8462ReadVRegister(reg[2]),8463addr[0])) {8464return;8465}8466struct_parts = 3;8467reg_count = 3;8468break;8469case NEON_ST3:8470case NEON_ST3_post:8471if (!st3(vf,8472ReadVRegister(reg[0]),8473ReadVRegister(reg[1]),8474ReadVRegister(reg[2]),8475addr[0])) {8476return;8477}8478struct_parts = 3;8479reg_count = 3;8480log_read = false;8481break;8482case NEON_ST4:8483case NEON_ST4_post:8484if (!st4(vf,8485ReadVRegister(reg[0]),8486ReadVRegister(reg[1]),8487ReadVRegister(reg[2]),8488ReadVRegister(reg[3]),8489addr[0])) {8490return;8491}8492struct_parts = 4;8493reg_count = 4;8494log_read = false;8495break;8496case NEON_LD4_post:8497case NEON_LD4:8498if (!ld4(vf,8499ReadVRegister(reg[0]),8500ReadVRegister(reg[1]),8501ReadVRegister(reg[2]),8502ReadVRegister(reg[3]),8503addr[0])) {8504return;8505}8506struct_parts = 4;8507reg_count = 4;8508break;8509default:8510VIXL_UNIMPLEMENTED();8511}85128513bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();8514if (do_trace) {8515PrintRegisterFormat print_format =8516GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));8517const char* op;8518if (log_read) {8519op = "<-";8520} else {8521op = "->";8522// Stores don't represent a change to the source register's value, so only8523// print the relevant part of the value.8524print_format = GetPrintRegPartial(print_format);8525}85268527VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));8528for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {8529uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));8530PrintVStructAccess(reg[s], struct_parts, print_format, op, address);8531}8532}85338534if (addr_mode == PostIndex) {8535int rm = instr->GetRm();8536// The immediate post index addressing mode is indicated by rm = 31.8537// The immediate is implied by the number of vector registers used.8538addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)8539: ReadXRegister(rm);8540WriteXRegister(instr->GetRn(),8541addr_base,8542LogRegWrites,8543Reg31IsStackPointer);8544} else {8545VIXL_ASSERT(addr_mode == Offset);8546}8547}854885498550void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {8551NEONLoadStoreMultiStructHelper(instr, Offset);8552}855385548555void Simulator::VisitNEONLoadStoreMultiStructPostIndex(8556const Instruction* instr) {8557NEONLoadStoreMultiStructHelper(instr, PostIndex);8558}855985608561void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,8562AddrMode addr_mode) {8563uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);8564int rt = instr->GetRt();85658566// Bit 23 determines whether this is an offset or post-index addressing mode.8567// In offset mode, bits 20 to 16 should be zero; these bits encode the8568// register or immediate in post-index mode.8569if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {8570VIXL_UNREACHABLE();8571}85728573// We use the PostIndex mask here, as it works in this case for both Offset8574// and PostIndex addressing.8575bool do_load = false;85768577bool replicating = false;85788579NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());8580VectorFormat vf_t = nfd.GetVectorFormat();85818582VectorFormat vf = kFormat16B;8583switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {8584case NEON_LD1_b:8585case NEON_LD1_b_post:8586case NEON_LD2_b:8587case NEON_LD2_b_post:8588case NEON_LD3_b:8589case NEON_LD3_b_post:8590case NEON_LD4_b:8591case NEON_LD4_b_post:8592do_load = true;8593VIXL_FALLTHROUGH();8594case NEON_ST1_b:8595case NEON_ST1_b_post:8596case NEON_ST2_b:8597case NEON_ST2_b_post:8598case NEON_ST3_b:8599case NEON_ST3_b_post:8600case NEON_ST4_b:8601case NEON_ST4_b_post:8602break;86038604case NEON_LD1_h:8605case NEON_LD1_h_post:8606case NEON_LD2_h:8607case NEON_LD2_h_post:8608case NEON_LD3_h:8609case NEON_LD3_h_post:8610case NEON_LD4_h:8611case NEON_LD4_h_post:8612do_load = true;8613VIXL_FALLTHROUGH();8614case NEON_ST1_h:8615case NEON_ST1_h_post:8616case NEON_ST2_h:8617case NEON_ST2_h_post:8618case NEON_ST3_h:8619case NEON_ST3_h_post:8620case NEON_ST4_h:8621case NEON_ST4_h_post:8622vf = kFormat8H;8623break;8624case NEON_LD1_s:8625case NEON_LD1_s_post:8626case NEON_LD2_s:8627case NEON_LD2_s_post:8628case NEON_LD3_s:8629case NEON_LD3_s_post:8630case NEON_LD4_s:8631case NEON_LD4_s_post:8632do_load = true;8633VIXL_FALLTHROUGH();8634case NEON_ST1_s:8635case NEON_ST1_s_post:8636case NEON_ST2_s:8637case NEON_ST2_s_post:8638case NEON_ST3_s:8639case NEON_ST3_s_post:8640case NEON_ST4_s:8641case NEON_ST4_s_post: {8642VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);8643VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==8644NEON_LD1_d_post);8645VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);8646VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==8647NEON_ST1_d_post);8648vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;8649break;8650}86518652case NEON_LD1R:8653case NEON_LD1R_post:8654case NEON_LD2R:8655case NEON_LD2R_post:8656case NEON_LD3R:8657case NEON_LD3R_post:8658case NEON_LD4R:8659case NEON_LD4R_post:8660vf = vf_t;8661do_load = true;8662replicating = true;8663break;86648665default:8666VIXL_UNIMPLEMENTED();8667}86688669int index_shift = LaneSizeInBytesLog2FromFormat(vf);8670int lane = instr->GetNEONLSIndex(index_shift);8671int reg_count = 0;8672int rt2 = (rt + 1) % kNumberOfVRegisters;8673int rt3 = (rt2 + 1) % kNumberOfVRegisters;8674int rt4 = (rt3 + 1) % kNumberOfVRegisters;8675switch (instr->Mask(NEONLoadStoreSingleLenMask)) {8676case NEONLoadStoreSingle1:8677reg_count = 1;8678if (replicating) {8679VIXL_ASSERT(do_load);8680if (!ld1r(vf, ReadVRegister(rt), addr)) {8681return;8682}8683} else if (do_load) {8684if (!ld1(vf, ReadVRegister(rt), lane, addr)) {8685return;8686}8687} else {8688if (!st1(vf, ReadVRegister(rt), lane, addr)) return;8689}8690break;8691case NEONLoadStoreSingle2:8692reg_count = 2;8693if (replicating) {8694VIXL_ASSERT(do_load);8695if (!ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr)) {8696return;8697}8698} else if (do_load) {8699if (!ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr)) {8700return;8701}8702} else {8703if (!st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr)) return;8704}8705break;8706case NEONLoadStoreSingle3:8707reg_count = 3;8708if (replicating) {8709VIXL_ASSERT(do_load);8710if (!ld3r(vf,8711ReadVRegister(rt),8712ReadVRegister(rt2),8713ReadVRegister(rt3),8714addr)) {8715return;8716}8717} else if (do_load) {8718if (!ld3(vf,8719ReadVRegister(rt),8720ReadVRegister(rt2),8721ReadVRegister(rt3),8722lane,8723addr)) {8724return;8725}8726} else {8727if (!st3(vf,8728ReadVRegister(rt),8729ReadVRegister(rt2),8730ReadVRegister(rt3),8731lane,8732addr)) {8733return;8734}8735}8736break;8737case NEONLoadStoreSingle4:8738reg_count = 4;8739if (replicating) {8740VIXL_ASSERT(do_load);8741if (!ld4r(vf,8742ReadVRegister(rt),8743ReadVRegister(rt2),8744ReadVRegister(rt3),8745ReadVRegister(rt4),8746addr)) {8747return;8748}8749} else if (do_load) {8750if (!ld4(vf,8751ReadVRegister(rt),8752ReadVRegister(rt2),8753ReadVRegister(rt3),8754ReadVRegister(rt4),8755lane,8756addr)) {8757return;8758}8759} else {8760if (!st4(vf,8761ReadVRegister(rt),8762ReadVRegister(rt2),8763ReadVRegister(rt3),8764ReadVRegister(rt4),8765lane,8766addr)) {8767return;8768}8769}8770break;8771default:8772VIXL_UNIMPLEMENTED();8773}87748775// Trace registers and/or memory writes.8776PrintRegisterFormat print_format =8777GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));8778if (do_load) {8779if (ShouldTraceVRegs()) {8780if (replicating) {8781PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);8782} else {8783PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);8784}8785}8786} else {8787if (ShouldTraceWrites()) {8788// Stores don't represent a change to the source register's value, so only8789// print the relevant part of the value.8790print_format = GetPrintRegPartial(print_format);8791PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);8792}8793}87948795if (addr_mode == PostIndex) {8796int rm = instr->GetRm();8797int lane_size = LaneSizeInBytesFromFormat(vf);8798WriteXRegister(instr->GetRn(),8799addr + ((rm == 31) ? (reg_count * lane_size)8800: ReadXRegister(rm)),8801LogRegWrites,8802Reg31IsStackPointer);8803}8804}880588068807void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {8808NEONLoadStoreSingleStructHelper(instr, Offset);8809}881088118812void Simulator::VisitNEONLoadStoreSingleStructPostIndex(8813const Instruction* instr) {8814NEONLoadStoreSingleStructHelper(instr, PostIndex);8815}881688178818void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {8819SimVRegister& rd = ReadVRegister(instr->GetRd());8820int cmode = instr->GetNEONCmode();8821int cmode_3_1 = (cmode >> 1) & 7;8822int cmode_3 = (cmode >> 3) & 1;8823int cmode_2 = (cmode >> 2) & 1;8824int cmode_1 = (cmode >> 1) & 1;8825int cmode_0 = cmode & 1;8826int half_enc = instr->ExtractBit(11);8827int q = instr->GetNEONQ();8828int op_bit = instr->GetNEONModImmOp();8829uint64_t imm8 = instr->GetImmNEONabcdefgh();8830// Find the format and immediate value8831uint64_t imm = 0;8832VectorFormat vform = kFormatUndefined;8833switch (cmode_3_1) {8834case 0x0:8835case 0x1:8836case 0x2:8837case 0x3:8838vform = (q == 1) ? kFormat4S : kFormat2S;8839imm = imm8 << (8 * cmode_3_1);8840break;8841case 0x4:8842case 0x5:8843vform = (q == 1) ? kFormat8H : kFormat4H;8844imm = imm8 << (8 * cmode_1);8845break;8846case 0x6:8847vform = (q == 1) ? kFormat4S : kFormat2S;8848if (cmode_0 == 0) {8849imm = imm8 << 8 | 0x000000ff;8850} else {8851imm = imm8 << 16 | 0x0000ffff;8852}8853break;8854case 0x7:8855if (cmode_0 == 0 && op_bit == 0) {8856vform = q ? kFormat16B : kFormat8B;8857imm = imm8;8858} else if (cmode_0 == 0 && op_bit == 1) {8859vform = q ? kFormat2D : kFormat1D;8860imm = 0;8861for (int i = 0; i < 8; ++i) {8862if (imm8 & (1 << i)) {8863imm |= (UINT64_C(0xff) << (8 * i));8864}8865}8866} else { // cmode_0 == 1, cmode == 0xf.8867if (half_enc == 1) {8868vform = q ? kFormat8H : kFormat4H;8869imm = Float16ToRawbits(instr->GetImmNEONFP16());8870} else if (op_bit == 0) {8871vform = q ? kFormat4S : kFormat2S;8872imm = FloatToRawbits(instr->GetImmNEONFP32());8873} else if (q == 1) {8874vform = kFormat2D;8875imm = DoubleToRawbits(instr->GetImmNEONFP64());8876} else {8877VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));8878VisitUnallocated(instr);8879}8880}8881break;8882default:8883VIXL_UNREACHABLE();8884break;8885}88868887// Find the operation8888NEONModifiedImmediateOp op;8889if (cmode_3 == 0) {8890if (cmode_0 == 0) {8891op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;8892} else { // cmode<0> == '1'8893op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;8894}8895} else { // cmode<3> == '1'8896if (cmode_2 == 0) {8897if (cmode_0 == 0) {8898op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;8899} else { // cmode<0> == '1'8900op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;8901}8902} else { // cmode<2> == '1'8903if (cmode_1 == 0) {8904op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;8905} else { // cmode<1> == '1'8906if (cmode_0 == 0) {8907op = NEONModifiedImmediate_MOVI;8908} else { // cmode<0> == '1'8909op = NEONModifiedImmediate_MOVI;8910}8911}8912}8913}89148915// Call the logic function8916if (op == NEONModifiedImmediate_ORR) {8917orr(vform, rd, rd, imm);8918} else if (op == NEONModifiedImmediate_BIC) {8919bic(vform, rd, rd, imm);8920} else if (op == NEONModifiedImmediate_MOVI) {8921movi(vform, rd, imm);8922} else if (op == NEONModifiedImmediate_MVNI) {8923mvni(vform, rd, imm);8924} else {8925VisitUnimplemented(instr);8926}8927}892889298930void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {8931NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());8932VectorFormat vf = nfd.GetVectorFormat();89338934SimVRegister& rd = ReadVRegister(instr->GetRd());8935SimVRegister& rn = ReadVRegister(instr->GetRn());89368937if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {8938// These instructions all use a two bit size field, except NOT and RBIT,8939// which use the field to encode the operation.8940switch (instr->Mask(NEONScalar2RegMiscMask)) {8941case NEON_CMEQ_zero_scalar:8942cmp(vf, rd, rn, 0, eq);8943break;8944case NEON_CMGE_zero_scalar:8945cmp(vf, rd, rn, 0, ge);8946break;8947case NEON_CMGT_zero_scalar:8948cmp(vf, rd, rn, 0, gt);8949break;8950case NEON_CMLT_zero_scalar:8951cmp(vf, rd, rn, 0, lt);8952break;8953case NEON_CMLE_zero_scalar:8954cmp(vf, rd, rn, 0, le);8955break;8956case NEON_ABS_scalar:8957abs(vf, rd, rn);8958break;8959case NEON_SQABS_scalar:8960abs(vf, rd, rn).SignedSaturate(vf);8961break;8962case NEON_NEG_scalar:8963neg(vf, rd, rn);8964break;8965case NEON_SQNEG_scalar:8966neg(vf, rd, rn).SignedSaturate(vf);8967break;8968case NEON_SUQADD_scalar:8969suqadd(vf, rd, rd, rn);8970break;8971case NEON_USQADD_scalar:8972usqadd(vf, rd, rd, rn);8973break;8974default:8975VIXL_UNIMPLEMENTED();8976break;8977}8978} else {8979VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());8980FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());89818982// These instructions all use a one bit size field, except SQXTUN, SQXTN8983// and UQXTN, which use a two bit size field.8984switch (instr->Mask(NEONScalar2RegMiscFPMask)) {8985case NEON_FRECPE_scalar:8986frecpe(fpf, rd, rn, fpcr_rounding);8987break;8988case NEON_FRECPX_scalar:8989frecpx(fpf, rd, rn);8990break;8991case NEON_FRSQRTE_scalar:8992frsqrte(fpf, rd, rn);8993break;8994case NEON_FCMGT_zero_scalar:8995fcmp_zero(fpf, rd, rn, gt);8996break;8997case NEON_FCMGE_zero_scalar:8998fcmp_zero(fpf, rd, rn, ge);8999break;9000case NEON_FCMEQ_zero_scalar:9001fcmp_zero(fpf, rd, rn, eq);9002break;9003case NEON_FCMLE_zero_scalar:9004fcmp_zero(fpf, rd, rn, le);9005break;9006case NEON_FCMLT_zero_scalar:9007fcmp_zero(fpf, rd, rn, lt);9008break;9009case NEON_SCVTF_scalar:9010scvtf(fpf, rd, rn, 0, fpcr_rounding);9011break;9012case NEON_UCVTF_scalar:9013ucvtf(fpf, rd, rn, 0, fpcr_rounding);9014break;9015case NEON_FCVTNS_scalar:9016fcvts(fpf, rd, rn, FPTieEven);9017break;9018case NEON_FCVTNU_scalar:9019fcvtu(fpf, rd, rn, FPTieEven);9020break;9021case NEON_FCVTPS_scalar:9022fcvts(fpf, rd, rn, FPPositiveInfinity);9023break;9024case NEON_FCVTPU_scalar:9025fcvtu(fpf, rd, rn, FPPositiveInfinity);9026break;9027case NEON_FCVTMS_scalar:9028fcvts(fpf, rd, rn, FPNegativeInfinity);9029break;9030case NEON_FCVTMU_scalar:9031fcvtu(fpf, rd, rn, FPNegativeInfinity);9032break;9033case NEON_FCVTZS_scalar:9034fcvts(fpf, rd, rn, FPZero);9035break;9036case NEON_FCVTZU_scalar:9037fcvtu(fpf, rd, rn, FPZero);9038break;9039case NEON_FCVTAS_scalar:9040fcvts(fpf, rd, rn, FPTieAway);9041break;9042case NEON_FCVTAU_scalar:9043fcvtu(fpf, rd, rn, FPTieAway);9044break;9045case NEON_FCVTXN_scalar:9046// Unlike all of the other FP instructions above, fcvtxn encodes dest9047// size S as size<0>=1. There's only one case, so we ignore the form.9048VIXL_ASSERT(instr->ExtractBit(22) == 1);9049fcvtxn(kFormatS, rd, rn);9050break;9051default:9052switch (instr->Mask(NEONScalar2RegMiscMask)) {9053case NEON_SQXTN_scalar:9054sqxtn(vf, rd, rn);9055break;9056case NEON_UQXTN_scalar:9057uqxtn(vf, rd, rn);9058break;9059case NEON_SQXTUN_scalar:9060sqxtun(vf, rd, rn);9061break;9062default:9063VIXL_UNIMPLEMENTED();9064}9065}9066}9067}906890699070void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {9071VectorFormat fpf = kFormatH;9072FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());90739074SimVRegister& rd = ReadVRegister(instr->GetRd());9075SimVRegister& rn = ReadVRegister(instr->GetRn());90769077switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {9078case NEON_FRECPE_H_scalar:9079frecpe(fpf, rd, rn, fpcr_rounding);9080break;9081case NEON_FRECPX_H_scalar:9082frecpx(fpf, rd, rn);9083break;9084case NEON_FRSQRTE_H_scalar:9085frsqrte(fpf, rd, rn);9086break;9087case NEON_FCMGT_H_zero_scalar:9088fcmp_zero(fpf, rd, rn, gt);9089break;9090case NEON_FCMGE_H_zero_scalar:9091fcmp_zero(fpf, rd, rn, ge);9092break;9093case NEON_FCMEQ_H_zero_scalar:9094fcmp_zero(fpf, rd, rn, eq);9095break;9096case NEON_FCMLE_H_zero_scalar:9097fcmp_zero(fpf, rd, rn, le);9098break;9099case NEON_FCMLT_H_zero_scalar:9100fcmp_zero(fpf, rd, rn, lt);9101break;9102case NEON_SCVTF_H_scalar:9103scvtf(fpf, rd, rn, 0, fpcr_rounding);9104break;9105case NEON_UCVTF_H_scalar:9106ucvtf(fpf, rd, rn, 0, fpcr_rounding);9107break;9108case NEON_FCVTNS_H_scalar:9109fcvts(fpf, rd, rn, FPTieEven);9110break;9111case NEON_FCVTNU_H_scalar:9112fcvtu(fpf, rd, rn, FPTieEven);9113break;9114case NEON_FCVTPS_H_scalar:9115fcvts(fpf, rd, rn, FPPositiveInfinity);9116break;9117case NEON_FCVTPU_H_scalar:9118fcvtu(fpf, rd, rn, FPPositiveInfinity);9119break;9120case NEON_FCVTMS_H_scalar:9121fcvts(fpf, rd, rn, FPNegativeInfinity);9122break;9123case NEON_FCVTMU_H_scalar:9124fcvtu(fpf, rd, rn, FPNegativeInfinity);9125break;9126case NEON_FCVTZS_H_scalar:9127fcvts(fpf, rd, rn, FPZero);9128break;9129case NEON_FCVTZU_H_scalar:9130fcvtu(fpf, rd, rn, FPZero);9131break;9132case NEON_FCVTAS_H_scalar:9133fcvts(fpf, rd, rn, FPTieAway);9134break;9135case NEON_FCVTAU_H_scalar:9136fcvtu(fpf, rd, rn, FPTieAway);9137break;9138}9139}914091419142void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {9143NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());9144VectorFormat vf = nfd.GetVectorFormat();91459146SimVRegister& rd = ReadVRegister(instr->GetRd());9147SimVRegister& rn = ReadVRegister(instr->GetRn());9148SimVRegister& rm = ReadVRegister(instr->GetRm());9149switch (instr->Mask(NEONScalar3DiffMask)) {9150case NEON_SQDMLAL_scalar:9151sqdmlal(vf, rd, rn, rm);9152break;9153case NEON_SQDMLSL_scalar:9154sqdmlsl(vf, rd, rn, rm);9155break;9156case NEON_SQDMULL_scalar:9157sqdmull(vf, rd, rn, rm);9158break;9159default:9160VIXL_UNIMPLEMENTED();9161}9162}916391649165void Simulator::VisitNEONScalar3Same(const Instruction* instr) {9166NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());9167VectorFormat vf = nfd.GetVectorFormat();91689169SimVRegister& rd = ReadVRegister(instr->GetRd());9170SimVRegister& rn = ReadVRegister(instr->GetRn());9171SimVRegister& rm = ReadVRegister(instr->GetRm());91729173if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {9174vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());9175switch (instr->Mask(NEONScalar3SameFPMask)) {9176case NEON_FMULX_scalar:9177fmulx(vf, rd, rn, rm);9178break;9179case NEON_FACGE_scalar:9180fabscmp(vf, rd, rn, rm, ge);9181break;9182case NEON_FACGT_scalar:9183fabscmp(vf, rd, rn, rm, gt);9184break;9185case NEON_FCMEQ_scalar:9186fcmp(vf, rd, rn, rm, eq);9187break;9188case NEON_FCMGE_scalar:9189fcmp(vf, rd, rn, rm, ge);9190break;9191case NEON_FCMGT_scalar:9192fcmp(vf, rd, rn, rm, gt);9193break;9194case NEON_FRECPS_scalar:9195frecps(vf, rd, rn, rm);9196break;9197case NEON_FRSQRTS_scalar:9198frsqrts(vf, rd, rn, rm);9199break;9200case NEON_FABD_scalar:9201fabd(vf, rd, rn, rm);9202break;9203default:9204VIXL_UNIMPLEMENTED();9205}9206} else {9207switch (instr->Mask(NEONScalar3SameMask)) {9208case NEON_ADD_scalar:9209add(vf, rd, rn, rm);9210break;9211case NEON_SUB_scalar:9212sub(vf, rd, rn, rm);9213break;9214case NEON_CMEQ_scalar:9215cmp(vf, rd, rn, rm, eq);9216break;9217case NEON_CMGE_scalar:9218cmp(vf, rd, rn, rm, ge);9219break;9220case NEON_CMGT_scalar:9221cmp(vf, rd, rn, rm, gt);9222break;9223case NEON_CMHI_scalar:9224cmp(vf, rd, rn, rm, hi);9225break;9226case NEON_CMHS_scalar:9227cmp(vf, rd, rn, rm, hs);9228break;9229case NEON_CMTST_scalar:9230cmptst(vf, rd, rn, rm);9231break;9232case NEON_USHL_scalar:9233ushl(vf, rd, rn, rm);9234break;9235case NEON_SSHL_scalar:9236sshl(vf, rd, rn, rm);9237break;9238case NEON_SQDMULH_scalar:9239sqdmulh(vf, rd, rn, rm);9240break;9241case NEON_SQRDMULH_scalar:9242sqrdmulh(vf, rd, rn, rm);9243break;9244case NEON_UQADD_scalar:9245add(vf, rd, rn, rm).UnsignedSaturate(vf);9246break;9247case NEON_SQADD_scalar:9248add(vf, rd, rn, rm).SignedSaturate(vf);9249break;9250case NEON_UQSUB_scalar:9251sub(vf, rd, rn, rm).UnsignedSaturate(vf);9252break;9253case NEON_SQSUB_scalar:9254sub(vf, rd, rn, rm).SignedSaturate(vf);9255break;9256case NEON_UQSHL_scalar:9257ushl(vf, rd, rn, rm).UnsignedSaturate(vf);9258break;9259case NEON_SQSHL_scalar:9260sshl(vf, rd, rn, rm).SignedSaturate(vf);9261break;9262case NEON_URSHL_scalar:9263ushl(vf, rd, rn, rm).Round(vf);9264break;9265case NEON_SRSHL_scalar:9266sshl(vf, rd, rn, rm).Round(vf);9267break;9268case NEON_UQRSHL_scalar:9269ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);9270break;9271case NEON_SQRSHL_scalar:9272sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);9273break;9274default:9275VIXL_UNIMPLEMENTED();9276}9277}9278}92799280void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {9281SimVRegister& rd = ReadVRegister(instr->GetRd());9282SimVRegister& rn = ReadVRegister(instr->GetRn());9283SimVRegister& rm = ReadVRegister(instr->GetRm());92849285switch (instr->Mask(NEONScalar3SameFP16Mask)) {9286case NEON_FABD_H_scalar:9287fabd(kFormatH, rd, rn, rm);9288break;9289case NEON_FMULX_H_scalar:9290fmulx(kFormatH, rd, rn, rm);9291break;9292case NEON_FCMEQ_H_scalar:9293fcmp(kFormatH, rd, rn, rm, eq);9294break;9295case NEON_FCMGE_H_scalar:9296fcmp(kFormatH, rd, rn, rm, ge);9297break;9298case NEON_FCMGT_H_scalar:9299fcmp(kFormatH, rd, rn, rm, gt);9300break;9301case NEON_FACGE_H_scalar:9302fabscmp(kFormatH, rd, rn, rm, ge);9303break;9304case NEON_FACGT_H_scalar:9305fabscmp(kFormatH, rd, rn, rm, gt);9306break;9307case NEON_FRECPS_H_scalar:9308frecps(kFormatH, rd, rn, rm);9309break;9310case NEON_FRSQRTS_H_scalar:9311frsqrts(kFormatH, rd, rn, rm);9312break;9313default:9314VIXL_UNREACHABLE();9315}9316}931793189319void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {9320NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());9321VectorFormat vf = nfd.GetVectorFormat();93229323SimVRegister& rd = ReadVRegister(instr->GetRd());9324SimVRegister& rn = ReadVRegister(instr->GetRn());9325SimVRegister& rm = ReadVRegister(instr->GetRm());93269327switch (instr->Mask(NEONScalar3SameExtraMask)) {9328case NEON_SQRDMLAH_scalar:9329sqrdmlah(vf, rd, rn, rm);9330break;9331case NEON_SQRDMLSH_scalar:9332sqrdmlsh(vf, rd, rn, rm);9333break;9334default:9335VIXL_UNIMPLEMENTED();9336}9337}93389339void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {9340NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());9341VectorFormat vf = nfd.GetVectorFormat();9342VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());93439344SimVRegister& rd = ReadVRegister(instr->GetRd());9345SimVRegister& rn = ReadVRegister(instr->GetRn());9346ByElementOp Op = NULL;93479348int rm_reg = instr->GetRm();9349int index = (instr->GetNEONH() << 1) | instr->GetNEONL();9350if (instr->GetNEONSize() == 1) {9351rm_reg &= 0xf;9352index = (index << 1) | instr->GetNEONM();9353}93549355switch (instr->Mask(NEONScalarByIndexedElementMask)) {9356case NEON_SQDMULL_byelement_scalar:9357Op = &Simulator::sqdmull;9358break;9359case NEON_SQDMLAL_byelement_scalar:9360Op = &Simulator::sqdmlal;9361break;9362case NEON_SQDMLSL_byelement_scalar:9363Op = &Simulator::sqdmlsl;9364break;9365case NEON_SQDMULH_byelement_scalar:9366Op = &Simulator::sqdmulh;9367vf = vf_r;9368break;9369case NEON_SQRDMULH_byelement_scalar:9370Op = &Simulator::sqrdmulh;9371vf = vf_r;9372break;9373case NEON_SQRDMLAH_byelement_scalar:9374Op = &Simulator::sqrdmlah;9375vf = vf_r;9376break;9377case NEON_SQRDMLSH_byelement_scalar:9378Op = &Simulator::sqrdmlsh;9379vf = vf_r;9380break;9381default:9382vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());9383index = instr->GetNEONH();9384if (instr->GetFPType() == 0) {9385index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();9386rm_reg &= 0xf;9387vf = kFormatH;9388} else if ((instr->GetFPType() & 1) == 0) {9389index = (index << 1) | instr->GetNEONL();9390}9391switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {9392case NEON_FMUL_H_byelement_scalar:9393case NEON_FMUL_byelement_scalar:9394Op = &Simulator::fmul;9395break;9396case NEON_FMLA_H_byelement_scalar:9397case NEON_FMLA_byelement_scalar:9398Op = &Simulator::fmla;9399break;9400case NEON_FMLS_H_byelement_scalar:9401case NEON_FMLS_byelement_scalar:9402Op = &Simulator::fmls;9403break;9404case NEON_FMULX_H_byelement_scalar:9405case NEON_FMULX_byelement_scalar:9406Op = &Simulator::fmulx;9407break;9408default:9409VIXL_UNIMPLEMENTED();9410}9411}94129413(this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);9414}941594169417void Simulator::VisitNEONScalarCopy(const Instruction* instr) {9418NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());9419VectorFormat vf = nfd.GetVectorFormat();94209421SimVRegister& rd = ReadVRegister(instr->GetRd());9422SimVRegister& rn = ReadVRegister(instr->GetRn());94239424if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {9425int imm5 = instr->GetImmNEON5();9426int tz = CountTrailingZeros(imm5, 32);9427int rn_index = ExtractSignedBitfield32(31, tz + 1, imm5);9428dup_element(vf, rd, rn, rn_index);9429} else {9430VIXL_UNIMPLEMENTED();9431}9432}943394349435void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {9436NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());9437VectorFormat vf = nfd.GetVectorFormat();94389439SimVRegister& rd = ReadVRegister(instr->GetRd());9440SimVRegister& rn = ReadVRegister(instr->GetRn());9441switch (instr->Mask(NEONScalarPairwiseMask)) {9442case NEON_ADDP_scalar: {9443// All pairwise operations except ADDP use bit U to differentiate FP169444// from FP32/FP64 variations.9445NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());9446addp(nfd_addp.GetVectorFormat(), rd, rn);9447break;9448}9449case NEON_FADDP_h_scalar:9450case NEON_FADDP_scalar:9451faddp(vf, rd, rn);9452break;9453case NEON_FMAXP_h_scalar:9454case NEON_FMAXP_scalar:9455fmaxp(vf, rd, rn);9456break;9457case NEON_FMAXNMP_h_scalar:9458case NEON_FMAXNMP_scalar:9459fmaxnmp(vf, rd, rn);9460break;9461case NEON_FMINP_h_scalar:9462case NEON_FMINP_scalar:9463fminp(vf, rd, rn);9464break;9465case NEON_FMINNMP_h_scalar:9466case NEON_FMINNMP_scalar:9467fminnmp(vf, rd, rn);9468break;9469default:9470VIXL_UNIMPLEMENTED();9471}9472}947394749475void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {9476SimVRegister& rd = ReadVRegister(instr->GetRd());9477SimVRegister& rn = ReadVRegister(instr->GetRn());9478FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());94799480static const NEONFormatMap map = {{22, 21, 20, 19},9481{NF_UNDEF,9482NF_B,9483NF_H,9484NF_H,9485NF_S,9486NF_S,9487NF_S,9488NF_S,9489NF_D,9490NF_D,9491NF_D,9492NF_D,9493NF_D,9494NF_D,9495NF_D,9496NF_D}};9497NEONFormatDecoder nfd(instr, &map);9498VectorFormat vf = nfd.GetVectorFormat();94999500int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());9501int immh_immb = instr->GetImmNEONImmhImmb();9502int right_shift = (16 << highest_set_bit) - immh_immb;9503int left_shift = immh_immb - (8 << highest_set_bit);9504switch (instr->Mask(NEONScalarShiftImmediateMask)) {9505case NEON_SHL_scalar:9506shl(vf, rd, rn, left_shift);9507break;9508case NEON_SLI_scalar:9509sli(vf, rd, rn, left_shift);9510break;9511case NEON_SQSHL_imm_scalar:9512sqshl(vf, rd, rn, left_shift);9513break;9514case NEON_UQSHL_imm_scalar:9515uqshl(vf, rd, rn, left_shift);9516break;9517case NEON_SQSHLU_scalar:9518sqshlu(vf, rd, rn, left_shift);9519break;9520case NEON_SRI_scalar:9521sri(vf, rd, rn, right_shift);9522break;9523case NEON_SSHR_scalar:9524sshr(vf, rd, rn, right_shift);9525break;9526case NEON_USHR_scalar:9527ushr(vf, rd, rn, right_shift);9528break;9529case NEON_SRSHR_scalar:9530sshr(vf, rd, rn, right_shift).Round(vf);9531break;9532case NEON_URSHR_scalar:9533ushr(vf, rd, rn, right_shift).Round(vf);9534break;9535case NEON_SSRA_scalar:9536ssra(vf, rd, rn, right_shift);9537break;9538case NEON_USRA_scalar:9539usra(vf, rd, rn, right_shift);9540break;9541case NEON_SRSRA_scalar:9542srsra(vf, rd, rn, right_shift);9543break;9544case NEON_URSRA_scalar:9545ursra(vf, rd, rn, right_shift);9546break;9547case NEON_UQSHRN_scalar:9548uqshrn(vf, rd, rn, right_shift);9549break;9550case NEON_UQRSHRN_scalar:9551uqrshrn(vf, rd, rn, right_shift);9552break;9553case NEON_SQSHRN_scalar:9554sqshrn(vf, rd, rn, right_shift);9555break;9556case NEON_SQRSHRN_scalar:9557sqrshrn(vf, rd, rn, right_shift);9558break;9559case NEON_SQSHRUN_scalar:9560sqshrun(vf, rd, rn, right_shift);9561break;9562case NEON_SQRSHRUN_scalar:9563sqrshrun(vf, rd, rn, right_shift);9564break;9565case NEON_FCVTZS_imm_scalar:9566fcvts(vf, rd, rn, FPZero, right_shift);9567break;9568case NEON_FCVTZU_imm_scalar:9569fcvtu(vf, rd, rn, FPZero, right_shift);9570break;9571case NEON_SCVTF_imm_scalar:9572scvtf(vf, rd, rn, right_shift, fpcr_rounding);9573break;9574case NEON_UCVTF_imm_scalar:9575ucvtf(vf, rd, rn, right_shift, fpcr_rounding);9576break;9577default:9578VIXL_UNIMPLEMENTED();9579}9580}958195829583void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {9584SimVRegister& rd = ReadVRegister(instr->GetRd());9585SimVRegister& rn = ReadVRegister(instr->GetRn());9586FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());95879588// 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,9589// 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.9590static const NEONFormatMap map = {{22, 21, 20, 19, 30},9591{NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,9592NF_4H, NF_8H, NF_4H, NF_8H,9593NF_2S, NF_4S, NF_2S, NF_4S,9594NF_2S, NF_4S, NF_2S, NF_4S,9595NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,9596NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,9597NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,9598NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};9599NEONFormatDecoder nfd(instr, &map);9600VectorFormat vf = nfd.GetVectorFormat();96019602// 0001->8H, 001x->4S, 01xx->2D, all others undefined.9603static const NEONFormatMap map_l =9604{{22, 21, 20, 19},9605{NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};9606VectorFormat vf_l = nfd.GetVectorFormat(&map_l);96079608int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());9609int immh_immb = instr->GetImmNEONImmhImmb();9610int right_shift = (16 << highest_set_bit) - immh_immb;9611int left_shift = immh_immb - (8 << highest_set_bit);96129613switch (instr->Mask(NEONShiftImmediateMask)) {9614case NEON_SHL:9615shl(vf, rd, rn, left_shift);9616break;9617case NEON_SLI:9618sli(vf, rd, rn, left_shift);9619break;9620case NEON_SQSHLU:9621sqshlu(vf, rd, rn, left_shift);9622break;9623case NEON_SRI:9624sri(vf, rd, rn, right_shift);9625break;9626case NEON_SSHR:9627sshr(vf, rd, rn, right_shift);9628break;9629case NEON_USHR:9630ushr(vf, rd, rn, right_shift);9631break;9632case NEON_SRSHR:9633sshr(vf, rd, rn, right_shift).Round(vf);9634break;9635case NEON_URSHR:9636ushr(vf, rd, rn, right_shift).Round(vf);9637break;9638case NEON_SSRA:9639ssra(vf, rd, rn, right_shift);9640break;9641case NEON_USRA:9642usra(vf, rd, rn, right_shift);9643break;9644case NEON_SRSRA:9645srsra(vf, rd, rn, right_shift);9646break;9647case NEON_URSRA:9648ursra(vf, rd, rn, right_shift);9649break;9650case NEON_SQSHL_imm:9651sqshl(vf, rd, rn, left_shift);9652break;9653case NEON_UQSHL_imm:9654uqshl(vf, rd, rn, left_shift);9655break;9656case NEON_SCVTF_imm:9657scvtf(vf, rd, rn, right_shift, fpcr_rounding);9658break;9659case NEON_UCVTF_imm:9660ucvtf(vf, rd, rn, right_shift, fpcr_rounding);9661break;9662case NEON_FCVTZS_imm:9663fcvts(vf, rd, rn, FPZero, right_shift);9664break;9665case NEON_FCVTZU_imm:9666fcvtu(vf, rd, rn, FPZero, right_shift);9667break;9668case NEON_SSHLL:9669vf = vf_l;9670if (instr->Mask(NEON_Q)) {9671sshll2(vf, rd, rn, left_shift);9672} else {9673sshll(vf, rd, rn, left_shift);9674}9675break;9676case NEON_USHLL:9677vf = vf_l;9678if (instr->Mask(NEON_Q)) {9679ushll2(vf, rd, rn, left_shift);9680} else {9681ushll(vf, rd, rn, left_shift);9682}9683break;9684case NEON_SHRN:9685if (instr->Mask(NEON_Q)) {9686shrn2(vf, rd, rn, right_shift);9687} else {9688shrn(vf, rd, rn, right_shift);9689}9690break;9691case NEON_RSHRN:9692if (instr->Mask(NEON_Q)) {9693rshrn2(vf, rd, rn, right_shift);9694} else {9695rshrn(vf, rd, rn, right_shift);9696}9697break;9698case NEON_UQSHRN:9699if (instr->Mask(NEON_Q)) {9700uqshrn2(vf, rd, rn, right_shift);9701} else {9702uqshrn(vf, rd, rn, right_shift);9703}9704break;9705case NEON_UQRSHRN:9706if (instr->Mask(NEON_Q)) {9707uqrshrn2(vf, rd, rn, right_shift);9708} else {9709uqrshrn(vf, rd, rn, right_shift);9710}9711break;9712case NEON_SQSHRN:9713if (instr->Mask(NEON_Q)) {9714sqshrn2(vf, rd, rn, right_shift);9715} else {9716sqshrn(vf, rd, rn, right_shift);9717}9718break;9719case NEON_SQRSHRN:9720if (instr->Mask(NEON_Q)) {9721sqrshrn2(vf, rd, rn, right_shift);9722} else {9723sqrshrn(vf, rd, rn, right_shift);9724}9725break;9726case NEON_SQSHRUN:9727if (instr->Mask(NEON_Q)) {9728sqshrun2(vf, rd, rn, right_shift);9729} else {9730sqshrun(vf, rd, rn, right_shift);9731}9732break;9733case NEON_SQRSHRUN:9734if (instr->Mask(NEON_Q)) {9735sqrshrun2(vf, rd, rn, right_shift);9736} else {9737sqrshrun(vf, rd, rn, right_shift);9738}9739break;9740default:9741VIXL_UNIMPLEMENTED();9742}9743}974497459746void Simulator::VisitNEONTable(const Instruction* instr) {9747NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());9748VectorFormat vf = nfd.GetVectorFormat();97499750SimVRegister& rd = ReadVRegister(instr->GetRd());9751SimVRegister& rn = ReadVRegister(instr->GetRn());9752SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);9753SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);9754SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);9755SimVRegister& rm = ReadVRegister(instr->GetRm());97569757switch (instr->Mask(NEONTableMask)) {9758case NEON_TBL_1v:9759tbl(vf, rd, rn, rm);9760break;9761case NEON_TBL_2v:9762tbl(vf, rd, rn, rn2, rm);9763break;9764case NEON_TBL_3v:9765tbl(vf, rd, rn, rn2, rn3, rm);9766break;9767case NEON_TBL_4v:9768tbl(vf, rd, rn, rn2, rn3, rn4, rm);9769break;9770case NEON_TBX_1v:9771tbx(vf, rd, rn, rm);9772break;9773case NEON_TBX_2v:9774tbx(vf, rd, rn, rn2, rm);9775break;9776case NEON_TBX_3v:9777tbx(vf, rd, rn, rn2, rn3, rm);9778break;9779case NEON_TBX_4v:9780tbx(vf, rd, rn, rn2, rn3, rn4, rm);9781break;9782default:9783VIXL_UNIMPLEMENTED();9784}9785}978697879788void Simulator::VisitNEONPerm(const Instruction* instr) {9789NEONFormatDecoder nfd(instr);9790VectorFormat vf = nfd.GetVectorFormat();97919792SimVRegister& rd = ReadVRegister(instr->GetRd());9793SimVRegister& rn = ReadVRegister(instr->GetRn());9794SimVRegister& rm = ReadVRegister(instr->GetRm());97959796switch (instr->Mask(NEONPermMask)) {9797case NEON_TRN1:9798trn1(vf, rd, rn, rm);9799break;9800case NEON_TRN2:9801trn2(vf, rd, rn, rm);9802break;9803case NEON_UZP1:9804uzp1(vf, rd, rn, rm);9805break;9806case NEON_UZP2:9807uzp2(vf, rd, rn, rm);9808break;9809case NEON_ZIP1:9810zip1(vf, rd, rn, rm);9811break;9812case NEON_ZIP2:9813zip2(vf, rd, rn, rm);9814break;9815default:9816VIXL_UNIMPLEMENTED();9817}9818}98199820void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {9821SimVRegister& zd = ReadVRegister(instr->GetRd());9822SimVRegister& zn = ReadVRegister(instr->GetRn());9823SimVRegister& zm = ReadVRegister(instr->GetRm());9824SimVRegister temp;98259826VectorFormat vform = kFormatVnD;9827mov(vform, temp, zm);98289829switch (instr->Mask(SVEAddressGenerationMask)) {9830case ADR_z_az_d_s32_scaled:9831sxt(vform, temp, temp, kSRegSize);9832break;9833case ADR_z_az_d_u32_scaled:9834uxt(vform, temp, temp, kSRegSize);9835break;9836case ADR_z_az_s_same_scaled:9837vform = kFormatVnS;9838break;9839case ADR_z_az_d_same_scaled:9840// Nothing to do.9841break;9842default:9843VIXL_UNIMPLEMENTED();9844break;9845}98469847int shift_amount = instr->ExtractBits(11, 10);9848shl(vform, temp, temp, shift_amount);9849add(vform, zd, zn, temp);9850}98519852void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(9853const Instruction* instr) {9854Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);9855switch (op) {9856case AND_z_zi:9857case EOR_z_zi:9858case ORR_z_zi: {9859int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();9860uint64_t imm = instr->GetSVEImmLogical();9861// Valid immediate is a non-zero bits9862VIXL_ASSERT(imm != 0);9863SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(9864op),9865SVEFormatFromLaneSizeInBytesLog2(lane_size),9866ReadVRegister(instr->GetRd()),9867imm);9868break;9869}9870default:9871VIXL_UNIMPLEMENTED();9872break;9873}9874}98759876void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {9877switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {9878case DUPM_z_i: {9879/* DUPM uses the same lane size and immediate encoding as bitwise logical9880* immediate instructions. */9881int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();9882uint64_t imm = instr->GetSVEImmLogical();9883VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);9884dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);9885break;9886}9887default:9888VIXL_UNIMPLEMENTED();9889break;9890}9891}98929893void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {9894SimVRegister& zd = ReadVRegister(instr->GetRd());9895SimVRegister& zn = ReadVRegister(instr->GetRn());9896SimVRegister& zm = ReadVRegister(instr->GetRm());9897Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);98989899LogicalOp logical_op = LogicalOpMask;9900switch (op) {9901case AND_z_zz:9902logical_op = AND;9903break;9904case BIC_z_zz:9905logical_op = BIC;9906break;9907case EOR_z_zz:9908logical_op = EOR;9909break;9910case ORR_z_zz:9911logical_op = ORR;9912break;9913default:9914VIXL_UNIMPLEMENTED();9915break;9916}9917// Lane size of registers is irrelevant to the bitwise operations, so perform9918// the operation on D-sized lanes.9919SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);9920}99219922void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {9923SimVRegister& zdn = ReadVRegister(instr->GetRd());9924SimPRegister& pg = ReadPRegister(instr->GetPgLow8());99259926SimVRegister scratch;9927SimVRegister result;99289929bool for_division = false;9930Shift shift_op = NO_SHIFT;9931switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {9932case ASRD_z_p_zi:9933shift_op = ASR;9934for_division = true;9935break;9936case ASR_z_p_zi:9937shift_op = ASR;9938break;9939case LSL_z_p_zi:9940shift_op = LSL;9941break;9942case LSR_z_p_zi:9943shift_op = LSR;9944break;9945default:9946VIXL_UNIMPLEMENTED();9947break;9948}99499950std::pair<int, int> shift_and_lane_size =9951instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);9952unsigned lane_size = shift_and_lane_size.second;9953VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);9954int shift_dist = shift_and_lane_size.first;99559956if ((shift_op == ASR) && for_division) {9957asrd(vform, result, zdn, shift_dist);9958} else {9959if (shift_op == LSL) {9960// Shift distance is computed differently for LSL. Convert the result.9961shift_dist = (8 << lane_size) - shift_dist;9962}9963dup_immediate(vform, scratch, shift_dist);9964SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);9965}9966mov_merging(vform, zdn, pg, result);9967}99689969void Simulator::VisitSVEBitwiseShiftByVector_Predicated(9970const Instruction* instr) {9971VectorFormat vform = instr->GetSVEVectorFormat();9972SimVRegister& zdn = ReadVRegister(instr->GetRd());9973SimVRegister& zm = ReadVRegister(instr->GetRn());9974SimPRegister& pg = ReadPRegister(instr->GetPgLow8());9975SimVRegister result;99769977// SVE uses the whole (saturated) lane for the shift amount.9978bool shift_in_ls_byte = false;99799980switch (form_hash_) {9981case "asrr_z_p_zz"_h:9982sshr(vform, result, zm, zdn);9983break;9984case "asr_z_p_zz"_h:9985sshr(vform, result, zdn, zm);9986break;9987case "lslr_z_p_zz"_h:9988sshl(vform, result, zm, zdn, shift_in_ls_byte);9989break;9990case "lsl_z_p_zz"_h:9991sshl(vform, result, zdn, zm, shift_in_ls_byte);9992break;9993case "lsrr_z_p_zz"_h:9994ushr(vform, result, zm, zdn);9995break;9996case "lsr_z_p_zz"_h:9997ushr(vform, result, zdn, zm);9998break;9999case "sqrshl_z_p_zz"_h:10000sshl(vform, result, zdn, zm, shift_in_ls_byte)10001.Round(vform)10002.SignedSaturate(vform);10003break;10004case "sqrshlr_z_p_zz"_h:10005sshl(vform, result, zm, zdn, shift_in_ls_byte)10006.Round(vform)10007.SignedSaturate(vform);10008break;10009case "sqshl_z_p_zz"_h:10010sshl(vform, result, zdn, zm, shift_in_ls_byte).SignedSaturate(vform);10011break;10012case "sqshlr_z_p_zz"_h:10013sshl(vform, result, zm, zdn, shift_in_ls_byte).SignedSaturate(vform);10014break;10015case "srshl_z_p_zz"_h:10016sshl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);10017break;10018case "srshlr_z_p_zz"_h:10019sshl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);10020break;10021case "uqrshl_z_p_zz"_h:10022ushl(vform, result, zdn, zm, shift_in_ls_byte)10023.Round(vform)10024.UnsignedSaturate(vform);10025break;10026case "uqrshlr_z_p_zz"_h:10027ushl(vform, result, zm, zdn, shift_in_ls_byte)10028.Round(vform)10029.UnsignedSaturate(vform);10030break;10031case "uqshl_z_p_zz"_h:10032ushl(vform, result, zdn, zm, shift_in_ls_byte).UnsignedSaturate(vform);10033break;10034case "uqshlr_z_p_zz"_h:10035ushl(vform, result, zm, zdn, shift_in_ls_byte).UnsignedSaturate(vform);10036break;10037case "urshl_z_p_zz"_h:10038ushl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);10039break;10040case "urshlr_z_p_zz"_h:10041ushl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);10042break;10043default:10044VIXL_UNIMPLEMENTED();10045break;10046}10047mov_merging(vform, zdn, pg, result);10048}1004910050void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(10051const Instruction* instr) {10052VectorFormat vform = instr->GetSVEVectorFormat();10053SimVRegister& zdn = ReadVRegister(instr->GetRd());10054SimVRegister& zm = ReadVRegister(instr->GetRn());10055SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1005610057SimVRegister result;10058Shift shift_op = ASR;1005910060switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {10061case ASR_z_p_zw:10062break;10063case LSL_z_p_zw:10064shift_op = LSL;10065break;10066case LSR_z_p_zw:10067shift_op = LSR;10068break;10069default:10070VIXL_UNIMPLEMENTED();10071break;10072}10073SVEBitwiseShiftHelper(shift_op,10074vform,10075result,10076zdn,10077zm,10078/* is_wide_elements = */ true);10079mov_merging(vform, zdn, pg, result);10080}1008110082void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {10083SimVRegister& zd = ReadVRegister(instr->GetRd());10084SimVRegister& zn = ReadVRegister(instr->GetRn());1008510086Shift shift_op = NO_SHIFT;10087switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {10088case ASR_z_zi:10089case ASR_z_zw:10090shift_op = ASR;10091break;10092case LSL_z_zi:10093case LSL_z_zw:10094shift_op = LSL;10095break;10096case LSR_z_zi:10097case LSR_z_zw:10098shift_op = LSR;10099break;10100default:10101VIXL_UNIMPLEMENTED();10102break;10103}1010410105switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {10106case ASR_z_zi:10107case LSL_z_zi:10108case LSR_z_zi: {10109SimVRegister scratch;10110std::pair<int, int> shift_and_lane_size =10111instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);10112unsigned lane_size = shift_and_lane_size.second;10113VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);10114VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);10115int shift_dist = shift_and_lane_size.first;10116if (shift_op == LSL) {10117// Shift distance is computed differently for LSL. Convert the result.10118shift_dist = (8 << lane_size) - shift_dist;10119}10120dup_immediate(vform, scratch, shift_dist);10121SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);10122break;10123}10124case ASR_z_zw:10125case LSL_z_zw:10126case LSR_z_zw:10127SVEBitwiseShiftHelper(shift_op,10128instr->GetSVEVectorFormat(),10129zd,10130zn,10131ReadVRegister(instr->GetRm()),10132true);10133break;10134default:10135VIXL_UNIMPLEMENTED();10136break;10137}10138}1013910140void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {10141// Although the instructions have a separate encoding class, the lane size is10142// encoded in the same way as most other SVE instructions.10143VectorFormat vform = instr->GetSVEVectorFormat();1014410145int pattern = instr->GetImmSVEPredicateConstraint();10146int count = GetPredicateConstraintLaneCount(vform, pattern);10147int multiplier = instr->ExtractBits(19, 16) + 1;1014810149switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {10150case DECB_r_rs:10151case DECD_r_rs:10152case DECH_r_rs:10153case DECW_r_rs:10154count = -count;10155break;10156case INCB_r_rs:10157case INCD_r_rs:10158case INCH_r_rs:10159case INCW_r_rs:10160// Nothing to do.10161break;10162default:10163VIXL_UNIMPLEMENTED();10164return;10165}1016610167WriteXRegister(instr->GetRd(),10168IncDecN(ReadXRegister(instr->GetRd()),10169count * multiplier,10170kXRegSize));10171}1017210173void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {10174VectorFormat vform = instr->GetSVEVectorFormat();10175if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {10176VIXL_UNIMPLEMENTED();10177}1017810179int pattern = instr->GetImmSVEPredicateConstraint();10180int count = GetPredicateConstraintLaneCount(vform, pattern);10181int multiplier = instr->ExtractBits(19, 16) + 1;1018210183switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {10184case DECD_z_zs:10185case DECH_z_zs:10186case DECW_z_zs:10187count = -count;10188break;10189case INCD_z_zs:10190case INCH_z_zs:10191case INCW_z_zs:10192// Nothing to do.10193break;10194default:10195VIXL_UNIMPLEMENTED();10196break;10197}1019810199SimVRegister& zd = ReadVRegister(instr->GetRd());10200SimVRegister scratch;10201dup_immediate(vform,10202scratch,10203IncDecN(0,10204count * multiplier,10205LaneSizeInBitsFromFormat(vform)));10206add(vform, zd, zd, scratch);10207}1020810209void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(10210const Instruction* instr) {10211// Although the instructions have a separate encoding class, the lane size is10212// encoded in the same way as most other SVE instructions.10213VectorFormat vform = instr->GetSVEVectorFormat();1021410215int pattern = instr->GetImmSVEPredicateConstraint();10216int count = GetPredicateConstraintLaneCount(vform, pattern);10217int multiplier = instr->ExtractBits(19, 16) + 1;1021810219unsigned width = kXRegSize;10220bool is_signed = false;1022110222switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {10223case SQDECB_r_rs_sx:10224case SQDECD_r_rs_sx:10225case SQDECH_r_rs_sx:10226case SQDECW_r_rs_sx:10227width = kWRegSize;10228VIXL_FALLTHROUGH();10229case SQDECB_r_rs_x:10230case SQDECD_r_rs_x:10231case SQDECH_r_rs_x:10232case SQDECW_r_rs_x:10233is_signed = true;10234count = -count;10235break;10236case SQINCB_r_rs_sx:10237case SQINCD_r_rs_sx:10238case SQINCH_r_rs_sx:10239case SQINCW_r_rs_sx:10240width = kWRegSize;10241VIXL_FALLTHROUGH();10242case SQINCB_r_rs_x:10243case SQINCD_r_rs_x:10244case SQINCH_r_rs_x:10245case SQINCW_r_rs_x:10246is_signed = true;10247break;10248case UQDECB_r_rs_uw:10249case UQDECD_r_rs_uw:10250case UQDECH_r_rs_uw:10251case UQDECW_r_rs_uw:10252width = kWRegSize;10253VIXL_FALLTHROUGH();10254case UQDECB_r_rs_x:10255case UQDECD_r_rs_x:10256case UQDECH_r_rs_x:10257case UQDECW_r_rs_x:10258count = -count;10259break;10260case UQINCB_r_rs_uw:10261case UQINCD_r_rs_uw:10262case UQINCH_r_rs_uw:10263case UQINCW_r_rs_uw:10264width = kWRegSize;10265VIXL_FALLTHROUGH();10266case UQINCB_r_rs_x:10267case UQINCD_r_rs_x:10268case UQINCH_r_rs_x:10269case UQINCW_r_rs_x:10270// Nothing to do.10271break;10272default:10273VIXL_UNIMPLEMENTED();10274break;10275}1027610277WriteXRegister(instr->GetRd(),10278IncDecN(ReadXRegister(instr->GetRd()),10279count * multiplier,10280width,10281true,10282is_signed));10283}1028410285void Simulator::VisitSVESaturatingIncDecVectorByElementCount(10286const Instruction* instr) {10287VectorFormat vform = instr->GetSVEVectorFormat();10288if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {10289VIXL_UNIMPLEMENTED();10290}1029110292int pattern = instr->GetImmSVEPredicateConstraint();10293int count = GetPredicateConstraintLaneCount(vform, pattern);10294int multiplier = instr->ExtractBits(19, 16) + 1;1029510296SimVRegister& zd = ReadVRegister(instr->GetRd());10297SimVRegister scratch;10298dup_immediate(vform,10299scratch,10300IncDecN(0,10301count * multiplier,10302LaneSizeInBitsFromFormat(vform)));1030310304switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {10305case SQDECD_z_zs:10306case SQDECH_z_zs:10307case SQDECW_z_zs:10308sub(vform, zd, zd, scratch).SignedSaturate(vform);10309break;10310case SQINCD_z_zs:10311case SQINCH_z_zs:10312case SQINCW_z_zs:10313add(vform, zd, zd, scratch).SignedSaturate(vform);10314break;10315case UQDECD_z_zs:10316case UQDECH_z_zs:10317case UQDECW_z_zs:10318sub(vform, zd, zd, scratch).UnsignedSaturate(vform);10319break;10320case UQINCD_z_zs:10321case UQINCH_z_zs:10322case UQINCW_z_zs:10323add(vform, zd, zd, scratch).UnsignedSaturate(vform);10324break;10325default:10326VIXL_UNIMPLEMENTED();10327break;10328}10329}1033010331void Simulator::VisitSVEElementCount(const Instruction* instr) {10332switch (instr->Mask(SVEElementCountMask)) {10333case CNTB_r_s:10334case CNTD_r_s:10335case CNTH_r_s:10336case CNTW_r_s:10337// All handled below.10338break;10339default:10340VIXL_UNIMPLEMENTED();10341break;10342}1034310344// Although the instructions are separated, the lane size is encoded in the10345// same way as most other SVE instructions.10346VectorFormat vform = instr->GetSVEVectorFormat();1034710348int pattern = instr->GetImmSVEPredicateConstraint();10349int count = GetPredicateConstraintLaneCount(vform, pattern);10350int multiplier = instr->ExtractBits(19, 16) + 1;10351WriteXRegister(instr->GetRd(), count * multiplier);10352}1035310354void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {10355VectorFormat vform = instr->GetSVEVectorFormat();10356SimVRegister& vdn = ReadVRegister(instr->GetRd());10357SimVRegister& zm = ReadVRegister(instr->GetRn());10358SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1035910360if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1036110362switch (instr->Mask(SVEFPAccumulatingReductionMask)) {10363case FADDA_v_p_z:10364fadda(vform, vdn, pg, zm);10365break;10366default:10367VIXL_UNIMPLEMENTED();10368break;10369}10370}1037110372void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {10373VectorFormat vform = instr->GetSVEVectorFormat();10374SimVRegister& zdn = ReadVRegister(instr->GetRd());10375SimVRegister& zm = ReadVRegister(instr->GetRn());10376SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1037710378if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1037910380SimVRegister result;10381switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {10382case FABD_z_p_zz:10383fabd(vform, result, zdn, zm);10384break;10385case FADD_z_p_zz:10386fadd(vform, result, zdn, zm);10387break;10388case FDIVR_z_p_zz:10389fdiv(vform, result, zm, zdn);10390break;10391case FDIV_z_p_zz:10392fdiv(vform, result, zdn, zm);10393break;10394case FMAXNM_z_p_zz:10395fmaxnm(vform, result, zdn, zm);10396break;10397case FMAX_z_p_zz:10398fmax(vform, result, zdn, zm);10399break;10400case FMINNM_z_p_zz:10401fminnm(vform, result, zdn, zm);10402break;10403case FMIN_z_p_zz:10404fmin(vform, result, zdn, zm);10405break;10406case FMULX_z_p_zz:10407fmulx(vform, result, zdn, zm);10408break;10409case FMUL_z_p_zz:10410fmul(vform, result, zdn, zm);10411break;10412case FSCALE_z_p_zz:10413fscale(vform, result, zdn, zm);10414break;10415case FSUBR_z_p_zz:10416fsub(vform, result, zm, zdn);10417break;10418case FSUB_z_p_zz:10419fsub(vform, result, zdn, zm);10420break;10421default:10422VIXL_UNIMPLEMENTED();10423break;10424}10425mov_merging(vform, zdn, pg, result);10426}1042710428void Simulator::VisitSVEFPArithmeticWithImm_Predicated(10429const Instruction* instr) {10430VectorFormat vform = instr->GetSVEVectorFormat();10431if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {10432VIXL_UNIMPLEMENTED();10433}1043410435SimVRegister& zdn = ReadVRegister(instr->GetRd());10436SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10437SimVRegister result;1043810439int i1 = instr->ExtractBit(5);10440SimVRegister add_sub_imm, min_max_imm, mul_imm;10441uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);10442uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);10443uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);10444dup_immediate(vform, add_sub_imm, i1 ? one : half);10445dup_immediate(vform, min_max_imm, i1 ? one : 0);10446dup_immediate(vform, mul_imm, i1 ? two : half);1044710448switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {10449case FADD_z_p_zs:10450fadd(vform, result, zdn, add_sub_imm);10451break;10452case FMAXNM_z_p_zs:10453fmaxnm(vform, result, zdn, min_max_imm);10454break;10455case FMAX_z_p_zs:10456fmax(vform, result, zdn, min_max_imm);10457break;10458case FMINNM_z_p_zs:10459fminnm(vform, result, zdn, min_max_imm);10460break;10461case FMIN_z_p_zs:10462fmin(vform, result, zdn, min_max_imm);10463break;10464case FMUL_z_p_zs:10465fmul(vform, result, zdn, mul_imm);10466break;10467case FSUBR_z_p_zs:10468fsub(vform, result, add_sub_imm, zdn);10469break;10470case FSUB_z_p_zs:10471fsub(vform, result, zdn, add_sub_imm);10472break;10473default:10474VIXL_UNIMPLEMENTED();10475break;10476}10477mov_merging(vform, zdn, pg, result);10478}1047910480void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {10481VectorFormat vform = instr->GetSVEVectorFormat();10482SimVRegister& zd = ReadVRegister(instr->GetRd());10483SimVRegister& zm = ReadVRegister(instr->GetRn());1048410485if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1048610487switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {10488case FTMAD_z_zzi:10489ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));10490break;10491default:10492VIXL_UNIMPLEMENTED();10493break;10494}10495}1049610497void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {10498VectorFormat vform = instr->GetSVEVectorFormat();10499SimVRegister& zd = ReadVRegister(instr->GetRd());10500SimVRegister& zn = ReadVRegister(instr->GetRn());10501SimVRegister& zm = ReadVRegister(instr->GetRm());1050210503if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1050410505switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {10506case FADD_z_zz:10507fadd(vform, zd, zn, zm);10508break;10509case FMUL_z_zz:10510fmul(vform, zd, zn, zm);10511break;10512case FRECPS_z_zz:10513frecps(vform, zd, zn, zm);10514break;10515case FRSQRTS_z_zz:10516frsqrts(vform, zd, zn, zm);10517break;10518case FSUB_z_zz:10519fsub(vform, zd, zn, zm);10520break;10521case FTSMUL_z_zz:10522ftsmul(vform, zd, zn, zm);10523break;10524default:10525VIXL_UNIMPLEMENTED();10526break;10527}10528}1052910530void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {10531SimPRegister& pd = ReadPRegister(instr->GetPd());10532SimVRegister& zn = ReadVRegister(instr->GetRn());10533SimVRegister& zm = ReadVRegister(instr->GetRm());10534SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10535VectorFormat vform = instr->GetSVEVectorFormat();10536SimVRegister result;1053710538if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1053910540switch (instr->Mask(SVEFPCompareVectorsMask)) {10541case FACGE_p_p_zz:10542fabscmp(vform, result, zn, zm, ge);10543break;10544case FACGT_p_p_zz:10545fabscmp(vform, result, zn, zm, gt);10546break;10547case FCMEQ_p_p_zz:10548fcmp(vform, result, zn, zm, eq);10549break;10550case FCMGE_p_p_zz:10551fcmp(vform, result, zn, zm, ge);10552break;10553case FCMGT_p_p_zz:10554fcmp(vform, result, zn, zm, gt);10555break;10556case FCMNE_p_p_zz:10557fcmp(vform, result, zn, zm, ne);10558break;10559case FCMUO_p_p_zz:10560fcmp(vform, result, zn, zm, uo);10561break;10562default:10563VIXL_UNIMPLEMENTED();10564break;10565}1056610567ExtractFromSimVRegister(vform, pd, result);10568mov_zeroing(pd, pg, pd);10569}1057010571void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {10572SimPRegister& pd = ReadPRegister(instr->GetPd());10573SimVRegister& zn = ReadVRegister(instr->GetRn());10574SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10575VectorFormat vform = instr->GetSVEVectorFormat();1057610577if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1057810579SimVRegister result;10580SimVRegister zeros;10581dup_immediate(kFormatVnD, zeros, 0);1058210583switch (instr->Mask(SVEFPCompareWithZeroMask)) {10584case FCMEQ_p_p_z0:10585fcmp(vform, result, zn, zeros, eq);10586break;10587case FCMGE_p_p_z0:10588fcmp(vform, result, zn, zeros, ge);10589break;10590case FCMGT_p_p_z0:10591fcmp(vform, result, zn, zeros, gt);10592break;10593case FCMLE_p_p_z0:10594fcmp(vform, result, zn, zeros, le);10595break;10596case FCMLT_p_p_z0:10597fcmp(vform, result, zn, zeros, lt);10598break;10599case FCMNE_p_p_z0:10600fcmp(vform, result, zn, zeros, ne);10601break;10602default:10603VIXL_UNIMPLEMENTED();10604break;10605}1060610607ExtractFromSimVRegister(vform, pd, result);10608mov_zeroing(pd, pg, pd);10609}1061010611void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {10612VectorFormat vform = instr->GetSVEVectorFormat();1061310614if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {10615VIXL_UNIMPLEMENTED();10616}1061710618SimVRegister& zdn = ReadVRegister(instr->GetRd());10619SimVRegister& zm = ReadVRegister(instr->GetRn());10620SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10621int rot = instr->ExtractBit(16);1062210623SimVRegister result;1062410625switch (instr->Mask(SVEFPComplexAdditionMask)) {10626case FCADD_z_p_zz:10627fcadd(vform, result, zdn, zm, rot);10628break;10629default:10630VIXL_UNIMPLEMENTED();10631break;10632}10633mov_merging(vform, zdn, pg, result);10634}1063510636void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {10637VectorFormat vform = instr->GetSVEVectorFormat();1063810639if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {10640VIXL_UNIMPLEMENTED();10641}1064210643SimVRegister& zda = ReadVRegister(instr->GetRd());10644SimVRegister& zn = ReadVRegister(instr->GetRn());10645SimVRegister& zm = ReadVRegister(instr->GetRm());10646SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10647int rot = instr->ExtractBits(14, 13);1064810649SimVRegister result;1065010651switch (instr->Mask(SVEFPComplexMulAddMask)) {10652case FCMLA_z_p_zzz:10653fcmla(vform, result, zn, zm, zda, rot);10654break;10655default:10656VIXL_UNIMPLEMENTED();10657break;10658}10659mov_merging(vform, zda, pg, result);10660}1066110662void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {10663SimVRegister& zda = ReadVRegister(instr->GetRd());10664SimVRegister& zn = ReadVRegister(instr->GetRn());10665int rot = instr->ExtractBits(11, 10);10666unsigned zm_code = instr->GetRm();10667int index = -1;10668VectorFormat vform, vform_dup;1066910670switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {10671case FCMLA_z_zzzi_h:10672vform = kFormatVnH;10673vform_dup = kFormatVnS;10674index = zm_code >> 3;10675zm_code &= 0x7;10676break;10677case FCMLA_z_zzzi_s:10678vform = kFormatVnS;10679vform_dup = kFormatVnD;10680index = zm_code >> 4;10681zm_code &= 0xf;10682break;10683default:10684VIXL_UNIMPLEMENTED();10685break;10686}1068710688if (index >= 0) {10689SimVRegister temp;10690dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);10691fcmla(vform, zda, zn, temp, zda, rot);10692}10693}1069410695typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,10696LogicVRegister dst,10697const LogicVRegister& src);1069810699void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {10700VectorFormat vform = instr->GetSVEVectorFormat();10701SimVRegister& vd = ReadVRegister(instr->GetRd());10702SimVRegister& zn = ReadVRegister(instr->GetRn());10703SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10704int lane_size = LaneSizeInBitsFromFormat(vform);1070510706uint64_t inactive_value = 0;10707FastReduceFn fn = nullptr;1070810709if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1071010711switch (instr->Mask(SVEFPFastReductionMask)) {10712case FADDV_v_p_z:10713fn = &Simulator::faddv;10714break;10715case FMAXNMV_v_p_z:10716inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);10717fn = &Simulator::fmaxnmv;10718break;10719case FMAXV_v_p_z:10720inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);10721fn = &Simulator::fmaxv;10722break;10723case FMINNMV_v_p_z:10724inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);10725fn = &Simulator::fminnmv;10726break;10727case FMINV_v_p_z:10728inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);10729fn = &Simulator::fminv;10730break;10731default:10732VIXL_UNIMPLEMENTED();10733break;10734}1073510736SimVRegister scratch;10737dup_immediate(vform, scratch, inactive_value);10738mov_merging(vform, scratch, pg, zn);10739if (fn != nullptr) (this->*fn)(vform, vd, scratch);10740}1074110742void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {10743VectorFormat vform = kFormatUndefined;1074410745switch (instr->Mask(SVEFPMulIndexMask)) {10746case FMUL_z_zzi_d:10747vform = kFormatVnD;10748break;10749case FMUL_z_zzi_h_i3h:10750case FMUL_z_zzi_h:10751vform = kFormatVnH;10752break;10753case FMUL_z_zzi_s:10754vform = kFormatVnS;10755break;10756default:10757VIXL_UNIMPLEMENTED();10758break;10759}1076010761SimVRegister& zd = ReadVRegister(instr->GetRd());10762SimVRegister& zn = ReadVRegister(instr->GetRn());10763SimVRegister temp;1076410765dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());10766fmul(vform, zd, zn, temp);10767}1076810769void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {10770VectorFormat vform = instr->GetSVEVectorFormat();10771SimVRegister& zd = ReadVRegister(instr->GetRd());10772SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10773SimVRegister result;1077410775if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1077610777if (instr->ExtractBit(15) == 0) {10778// Floating-point multiply-accumulate writing addend.10779SimVRegister& zm = ReadVRegister(instr->GetRm());10780SimVRegister& zn = ReadVRegister(instr->GetRn());1078110782switch (instr->Mask(SVEFPMulAddMask)) {10783// zda = zda + zn * zm10784case FMLA_z_p_zzz:10785fmla(vform, result, zd, zn, zm);10786break;10787// zda = -zda + -zn * zm10788case FNMLA_z_p_zzz:10789fneg(vform, result, zd);10790fmls(vform, result, result, zn, zm);10791break;10792// zda = zda + -zn * zm10793case FMLS_z_p_zzz:10794fmls(vform, result, zd, zn, zm);10795break;10796// zda = -zda + zn * zm10797case FNMLS_z_p_zzz:10798fneg(vform, result, zd);10799fmla(vform, result, result, zn, zm);10800break;10801default:10802VIXL_UNIMPLEMENTED();10803break;10804}10805} else {10806// Floating-point multiply-accumulate writing multiplicand.10807SimVRegister& za = ReadVRegister(instr->GetRm());10808SimVRegister& zm = ReadVRegister(instr->GetRn());1080910810switch (instr->Mask(SVEFPMulAddMask)) {10811// zdn = za + zdn * zm10812case FMAD_z_p_zzz:10813fmla(vform, result, za, zd, zm);10814break;10815// zdn = -za + -zdn * zm10816case FNMAD_z_p_zzz:10817fneg(vform, result, za);10818fmls(vform, result, result, zd, zm);10819break;10820// zdn = za + -zdn * zm10821case FMSB_z_p_zzz:10822fmls(vform, result, za, zd, zm);10823break;10824// zdn = -za + zdn * zm10825case FNMSB_z_p_zzz:10826fneg(vform, result, za);10827fmla(vform, result, result, zd, zm);10828break;10829default:10830VIXL_UNIMPLEMENTED();10831break;10832}10833}1083410835mov_merging(vform, zd, pg, result);10836}1083710838void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {10839VectorFormat vform = kFormatUndefined;1084010841switch (instr->Mask(SVEFPMulAddIndexMask)) {10842case FMLA_z_zzzi_d:10843case FMLS_z_zzzi_d:10844vform = kFormatVnD;10845break;10846case FMLA_z_zzzi_s:10847case FMLS_z_zzzi_s:10848vform = kFormatVnS;10849break;10850case FMLA_z_zzzi_h:10851case FMLS_z_zzzi_h:10852case FMLA_z_zzzi_h_i3h:10853case FMLS_z_zzzi_h_i3h:10854vform = kFormatVnH;10855break;10856default:10857VIXL_UNIMPLEMENTED();10858break;10859}1086010861SimVRegister& zd = ReadVRegister(instr->GetRd());10862SimVRegister& zn = ReadVRegister(instr->GetRn());10863SimVRegister temp;1086410865dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());10866if (instr->ExtractBit(10) == 1) {10867fmls(vform, zd, zd, zn, temp);10868} else {10869fmla(vform, zd, zd, zn, temp);10870}10871}1087210873void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {10874SimVRegister& zd = ReadVRegister(instr->GetRd());10875SimVRegister& zn = ReadVRegister(instr->GetRn());10876SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10877int dst_data_size;10878int src_data_size;1087910880switch (instr->Mask(SVEFPConvertToIntMask)) {10881case FCVTZS_z_p_z_d2w:10882case FCVTZU_z_p_z_d2w:10883dst_data_size = kSRegSize;10884src_data_size = kDRegSize;10885break;10886case FCVTZS_z_p_z_d2x:10887case FCVTZU_z_p_z_d2x:10888dst_data_size = kDRegSize;10889src_data_size = kDRegSize;10890break;10891case FCVTZS_z_p_z_fp162h:10892case FCVTZU_z_p_z_fp162h:10893dst_data_size = kHRegSize;10894src_data_size = kHRegSize;10895break;10896case FCVTZS_z_p_z_fp162w:10897case FCVTZU_z_p_z_fp162w:10898dst_data_size = kSRegSize;10899src_data_size = kHRegSize;10900break;10901case FCVTZS_z_p_z_fp162x:10902case FCVTZU_z_p_z_fp162x:10903dst_data_size = kDRegSize;10904src_data_size = kHRegSize;10905break;10906case FCVTZS_z_p_z_s2w:10907case FCVTZU_z_p_z_s2w:10908dst_data_size = kSRegSize;10909src_data_size = kSRegSize;10910break;10911case FCVTZS_z_p_z_s2x:10912case FCVTZU_z_p_z_s2x:10913dst_data_size = kDRegSize;10914src_data_size = kSRegSize;10915break;10916default:10917VIXL_UNIMPLEMENTED();10918dst_data_size = 0;10919src_data_size = 0;10920break;10921}1092210923VectorFormat vform =10924SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));1092510926if (instr->ExtractBit(16) == 0) {10927fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);10928} else {10929fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);10930}10931}1093210933void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {10934SimVRegister& zd = ReadVRegister(instr->GetRd());10935SimVRegister& zn = ReadVRegister(instr->GetRn());10936SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10937VectorFormat dst_data_size = kFormatUndefined;10938VectorFormat src_data_size = kFormatUndefined;1093910940switch (instr->Mask(SVEFPConvertPrecisionMask)) {10941case FCVT_z_p_z_d2h:10942dst_data_size = kFormatVnH;10943src_data_size = kFormatVnD;10944break;10945case FCVT_z_p_z_d2s:10946dst_data_size = kFormatVnS;10947src_data_size = kFormatVnD;10948break;10949case FCVT_z_p_z_h2d:10950dst_data_size = kFormatVnD;10951src_data_size = kFormatVnH;10952break;10953case FCVT_z_p_z_h2s:10954dst_data_size = kFormatVnS;10955src_data_size = kFormatVnH;10956break;10957case FCVT_z_p_z_s2d:10958dst_data_size = kFormatVnD;10959src_data_size = kFormatVnS;10960break;10961case FCVT_z_p_z_s2h:10962dst_data_size = kFormatVnH;10963src_data_size = kFormatVnS;10964break;10965default:10966VIXL_UNIMPLEMENTED();10967break;10968}1096910970fcvt(dst_data_size, src_data_size, zd, pg, zn);10971}1097210973void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {10974SimVRegister& zd = ReadVRegister(instr->GetRd());10975SimVRegister& zn = ReadVRegister(instr->GetRn());10976SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10977VectorFormat vform = instr->GetSVEVectorFormat();10978SimVRegister result;1097910980switch (instr->Mask(SVEFPUnaryOpMask)) {10981case FRECPX_z_p_z:10982frecpx(vform, result, zn);10983break;10984case FSQRT_z_p_z:10985fsqrt(vform, result, zn);10986break;10987default:10988VIXL_UNIMPLEMENTED();10989break;10990}10991mov_merging(vform, zd, pg, result);10992}1099310994void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {10995SimVRegister& zd = ReadVRegister(instr->GetRd());10996SimVRegister& zn = ReadVRegister(instr->GetRn());10997SimPRegister& pg = ReadPRegister(instr->GetPgLow8());10998VectorFormat vform = instr->GetSVEVectorFormat();10999FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());11000bool exact_exception = false;1100111002if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1100311004switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {11005case FRINTA_z_p_z:11006fpcr_rounding = FPTieAway;11007break;11008case FRINTI_z_p_z:11009break; // Use FPCR rounding mode.11010case FRINTM_z_p_z:11011fpcr_rounding = FPNegativeInfinity;11012break;11013case FRINTN_z_p_z:11014fpcr_rounding = FPTieEven;11015break;11016case FRINTP_z_p_z:11017fpcr_rounding = FPPositiveInfinity;11018break;11019case FRINTX_z_p_z:11020exact_exception = true;11021break;11022case FRINTZ_z_p_z:11023fpcr_rounding = FPZero;11024break;11025default:11026VIXL_UNIMPLEMENTED();11027break;11028}1102911030SimVRegister result;11031frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);11032mov_merging(vform, zd, pg, result);11033}1103411035void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {11036SimVRegister& zd = ReadVRegister(instr->GetRd());11037SimVRegister& zn = ReadVRegister(instr->GetRn());11038SimPRegister& pg = ReadPRegister(instr->GetPgLow8());11039FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());11040int dst_data_size;11041int src_data_size;1104211043switch (instr->Mask(SVEIntConvertToFPMask)) {11044case SCVTF_z_p_z_h2fp16:11045case UCVTF_z_p_z_h2fp16:11046dst_data_size = kHRegSize;11047src_data_size = kHRegSize;11048break;11049case SCVTF_z_p_z_w2d:11050case UCVTF_z_p_z_w2d:11051dst_data_size = kDRegSize;11052src_data_size = kSRegSize;11053break;11054case SCVTF_z_p_z_w2fp16:11055case UCVTF_z_p_z_w2fp16:11056dst_data_size = kHRegSize;11057src_data_size = kSRegSize;11058break;11059case SCVTF_z_p_z_w2s:11060case UCVTF_z_p_z_w2s:11061dst_data_size = kSRegSize;11062src_data_size = kSRegSize;11063break;11064case SCVTF_z_p_z_x2d:11065case UCVTF_z_p_z_x2d:11066dst_data_size = kDRegSize;11067src_data_size = kDRegSize;11068break;11069case SCVTF_z_p_z_x2fp16:11070case UCVTF_z_p_z_x2fp16:11071dst_data_size = kHRegSize;11072src_data_size = kDRegSize;11073break;11074case SCVTF_z_p_z_x2s:11075case UCVTF_z_p_z_x2s:11076dst_data_size = kSRegSize;11077src_data_size = kDRegSize;11078break;11079default:11080VIXL_UNIMPLEMENTED();11081dst_data_size = 0;11082src_data_size = 0;11083break;11084}1108511086VectorFormat vform =11087SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));1108811089if (instr->ExtractBit(16) == 0) {11090scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);11091} else {11092ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);11093}11094}1109511096void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {11097VectorFormat vform = instr->GetSVEVectorFormat();11098SimVRegister& zd = ReadVRegister(instr->GetRd());11099SimVRegister& zn = ReadVRegister(instr->GetRn());11100FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());1110111102if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1110311104switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {11105case FRECPE_z_z:11106frecpe(vform, zd, zn, fpcr_rounding);11107break;11108case FRSQRTE_z_z:11109frsqrte(vform, zd, zn);11110break;11111default:11112VIXL_UNIMPLEMENTED();11113break;11114}11115}1111611117void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {11118VectorFormat vform = instr->GetSVEVectorFormat();11119SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));1112011121int count = CountActiveLanes(vform, pg);1112211123if (instr->ExtractBit(11) == 0) {11124SimVRegister& zdn = ReadVRegister(instr->GetRd());11125switch (instr->Mask(SVEIncDecByPredicateCountMask)) {11126case DECP_z_p_z:11127sub_uint(vform, zdn, zdn, count);11128break;11129case INCP_z_p_z:11130add_uint(vform, zdn, zdn, count);11131break;11132case SQDECP_z_p_z:11133sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);11134break;11135case SQINCP_z_p_z:11136add_uint(vform, zdn, zdn, count).SignedSaturate(vform);11137break;11138case UQDECP_z_p_z:11139sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);11140break;11141case UQINCP_z_p_z:11142add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);11143break;11144default:11145VIXL_UNIMPLEMENTED();11146break;11147}11148} else {11149bool is_saturating = (instr->ExtractBit(18) == 0);11150bool decrement =11151is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);11152bool is_signed = (instr->ExtractBit(16) == 0);11153bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;11154unsigned width = sf ? kXRegSize : kWRegSize;1115511156switch (instr->Mask(SVEIncDecByPredicateCountMask)) {11157case DECP_r_p_r:11158case INCP_r_p_r:11159case SQDECP_r_p_r_sx:11160case SQDECP_r_p_r_x:11161case SQINCP_r_p_r_sx:11162case SQINCP_r_p_r_x:11163case UQDECP_r_p_r_uw:11164case UQDECP_r_p_r_x:11165case UQINCP_r_p_r_uw:11166case UQINCP_r_p_r_x:11167WriteXRegister(instr->GetRd(),11168IncDecN(ReadXRegister(instr->GetRd()),11169decrement ? -count : count,11170width,11171is_saturating,11172is_signed));11173break;11174default:11175VIXL_UNIMPLEMENTED();11176break;11177}11178}11179}1118011181uint64_t Simulator::IncDecN(uint64_t acc,11182int64_t delta,11183unsigned n,11184bool is_saturating,11185bool is_signed) {11186VIXL_ASSERT(n <= 64);11187VIXL_ASSERT(IsIntN(n, delta));1118811189uint64_t sign_mask = UINT64_C(1) << (n - 1);11190uint64_t mask = GetUintMask(n);1119111192acc &= mask; // Ignore initial accumulator high bits.11193uint64_t result = (acc + delta) & mask;1119411195bool result_negative = ((result & sign_mask) != 0);1119611197if (is_saturating) {11198if (is_signed) {11199bool acc_negative = ((acc & sign_mask) != 0);11200bool delta_negative = delta < 0;1120111202// If the signs of the operands are the same, but different from the11203// result, there was an overflow.11204if ((acc_negative == delta_negative) &&11205(acc_negative != result_negative)) {11206if (result_negative) {11207// Saturate to [..., INT<n>_MAX].11208result_negative = false;11209result = mask & ~sign_mask; // E.g. 0x000000007fffffff11210} else {11211// Saturate to [INT<n>_MIN, ...].11212result_negative = true;11213result = ~mask | sign_mask; // E.g. 0xffffffff8000000011214}11215}11216} else {11217if ((delta < 0) && (result > acc)) {11218// Saturate to [0, ...].11219result = 0;11220} else if ((delta > 0) && (result < acc)) {11221// Saturate to [..., UINT<n>_MAX].11222result = mask;11223}11224}11225}1122611227// Sign-extend if necessary.11228if (result_negative && is_signed) result |= ~mask;1122911230return result;11231}1123211233void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {11234VectorFormat vform = instr->GetSVEVectorFormat();11235SimVRegister& zd = ReadVRegister(instr->GetRd());11236switch (instr->Mask(SVEIndexGenerationMask)) {11237case INDEX_z_ii:11238case INDEX_z_ir:11239case INDEX_z_ri:11240case INDEX_z_rr: {11241uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())11242: instr->ExtractSignedBits(9, 5);11243uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())11244: instr->ExtractSignedBits(20, 16);11245index(vform, zd, start, step);11246break;11247}11248default:11249VIXL_UNIMPLEMENTED();11250break;11251}11252}1125311254void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {11255VectorFormat vform = instr->GetSVEVectorFormat();11256SimVRegister& zd = ReadVRegister(instr->GetRd());11257SimVRegister& zn = ReadVRegister(instr->GetRn());11258SimVRegister& zm = ReadVRegister(instr->GetRm());11259switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {11260case ADD_z_zz:11261add(vform, zd, zn, zm);11262break;11263case SQADD_z_zz:11264add(vform, zd, zn, zm).SignedSaturate(vform);11265break;11266case SQSUB_z_zz:11267sub(vform, zd, zn, zm).SignedSaturate(vform);11268break;11269case SUB_z_zz:11270sub(vform, zd, zn, zm);11271break;11272case UQADD_z_zz:11273add(vform, zd, zn, zm).UnsignedSaturate(vform);11274break;11275case UQSUB_z_zz:11276sub(vform, zd, zn, zm).UnsignedSaturate(vform);11277break;11278default:11279VIXL_UNIMPLEMENTED();11280break;11281}11282}1128311284void Simulator::VisitSVEIntAddSubtractVectors_Predicated(11285const Instruction* instr) {11286VectorFormat vform = instr->GetSVEVectorFormat();11287SimVRegister& zdn = ReadVRegister(instr->GetRd());11288SimVRegister& zm = ReadVRegister(instr->GetRn());11289SimPRegister& pg = ReadPRegister(instr->GetPgLow8());11290SimVRegister result;1129111292switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {11293case ADD_z_p_zz:11294add(vform, result, zdn, zm);11295break;11296case SUBR_z_p_zz:11297sub(vform, result, zm, zdn);11298break;11299case SUB_z_p_zz:11300sub(vform, result, zdn, zm);11301break;11302default:11303VIXL_UNIMPLEMENTED();11304break;11305}11306mov_merging(vform, zdn, pg, result);11307}1130811309void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {11310VectorFormat vform = instr->GetSVEVectorFormat();11311SimVRegister& zdn = ReadVRegister(instr->GetRd());11312SimVRegister& zm = ReadVRegister(instr->GetRn());11313SimPRegister& pg = ReadPRegister(instr->GetPgLow8());11314SimVRegister result;1131511316switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {11317case AND_z_p_zz:11318SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);11319break;11320case BIC_z_p_zz:11321SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);11322break;11323case EOR_z_p_zz:11324SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);11325break;11326case ORR_z_p_zz:11327SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);11328break;11329default:11330VIXL_UNIMPLEMENTED();11331break;11332}11333mov_merging(vform, zdn, pg, result);11334}1133511336void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {11337VectorFormat vform = instr->GetSVEVectorFormat();11338SimVRegister& zdn = ReadVRegister(instr->GetRd());11339SimVRegister& zm = ReadVRegister(instr->GetRn());11340SimPRegister& pg = ReadPRegister(instr->GetPgLow8());11341SimVRegister result;1134211343switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {11344case MUL_z_p_zz:11345mul(vform, result, zdn, zm);11346break;11347case SMULH_z_p_zz:11348smulh(vform, result, zdn, zm);11349break;11350case UMULH_z_p_zz:11351umulh(vform, result, zdn, zm);11352break;11353default:11354VIXL_UNIMPLEMENTED();11355break;11356}11357mov_merging(vform, zdn, pg, result);11358}1135911360void Simulator::VisitSVEIntMinMaxDifference_Predicated(11361const Instruction* instr) {11362VectorFormat vform = instr->GetSVEVectorFormat();11363SimVRegister& zdn = ReadVRegister(instr->GetRd());11364SimVRegister& zm = ReadVRegister(instr->GetRn());11365SimPRegister& pg = ReadPRegister(instr->GetPgLow8());11366SimVRegister result;1136711368switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {11369case SABD_z_p_zz:11370absdiff(vform, result, zdn, zm, true);11371break;11372case SMAX_z_p_zz:11373smax(vform, result, zdn, zm);11374break;11375case SMIN_z_p_zz:11376smin(vform, result, zdn, zm);11377break;11378case UABD_z_p_zz:11379absdiff(vform, result, zdn, zm, false);11380break;11381case UMAX_z_p_zz:11382umax(vform, result, zdn, zm);11383break;11384case UMIN_z_p_zz:11385umin(vform, result, zdn, zm);11386break;11387default:11388VIXL_UNIMPLEMENTED();11389break;11390}11391mov_merging(vform, zdn, pg, result);11392}1139311394void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {11395VectorFormat vform = instr->GetSVEVectorFormat();11396SimVRegister& zd = ReadVRegister(instr->GetRd());11397SimVRegister scratch;1139811399switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {11400case MUL_z_zi:11401dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());11402mul(vform, zd, zd, scratch);11403break;11404default:11405VIXL_UNIMPLEMENTED();11406break;11407}11408}1140911410void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {11411VectorFormat vform = instr->GetSVEVectorFormat();11412SimVRegister& zdn = ReadVRegister(instr->GetRd());11413SimVRegister& zm = ReadVRegister(instr->GetRn());11414SimPRegister& pg = ReadPRegister(instr->GetPgLow8());11415SimVRegister result;1141611417VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));1141811419switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {11420case SDIVR_z_p_zz:11421sdiv(vform, result, zm, zdn);11422break;11423case SDIV_z_p_zz:11424sdiv(vform, result, zdn, zm);11425break;11426case UDIVR_z_p_zz:11427udiv(vform, result, zm, zdn);11428break;11429case UDIV_z_p_zz:11430udiv(vform, result, zdn, zm);11431break;11432default:11433VIXL_UNIMPLEMENTED();11434break;11435}11436mov_merging(vform, zdn, pg, result);11437}1143811439void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {11440VectorFormat vform = instr->GetSVEVectorFormat();11441SimVRegister& zd = ReadVRegister(instr->GetRd());11442SimVRegister scratch;1144311444uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();11445int64_t signed_imm = instr->GetImmSVEIntWideSigned();1144611447switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {11448case SMAX_z_zi:11449dup_immediate(vform, scratch, signed_imm);11450smax(vform, zd, zd, scratch);11451break;11452case SMIN_z_zi:11453dup_immediate(vform, scratch, signed_imm);11454smin(vform, zd, zd, scratch);11455break;11456case UMAX_z_zi:11457dup_immediate(vform, scratch, unsigned_imm);11458umax(vform, zd, zd, scratch);11459break;11460case UMIN_z_zi:11461dup_immediate(vform, scratch, unsigned_imm);11462umin(vform, zd, zd, scratch);11463break;11464default:11465VIXL_UNIMPLEMENTED();11466break;11467}11468}1146911470void Simulator::VisitSVEIntCompareScalarCountAndLimit(11471const Instruction* instr) {11472unsigned rn_code = instr->GetRn();11473unsigned rm_code = instr->GetRm();11474SimPRegister& pd = ReadPRegister(instr->GetPd());11475VectorFormat vform = instr->GetSVEVectorFormat();1147611477bool is_64_bit = instr->ExtractBit(12) == 1;11478int rsize = is_64_bit ? kXRegSize : kWRegSize;11479uint64_t mask = is_64_bit ? kXRegMask : kWRegMask;1148011481uint64_t usrc1 = ReadXRegister(rn_code);11482int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);11483uint64_t usrc2 = ssrc2 & mask;1148411485bool reverse = (form_hash_ == "whilege_p_p_rr"_h) ||11486(form_hash_ == "whilegt_p_p_rr"_h) ||11487(form_hash_ == "whilehi_p_p_rr"_h) ||11488(form_hash_ == "whilehs_p_p_rr"_h);1148911490int lane_count = LaneCountFromFormat(vform);11491bool last = true;11492for (int i = 0; i < lane_count; i++) {11493usrc1 &= mask;11494int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1);1149511496bool cond = false;11497switch (form_hash_) {11498case "whilele_p_p_rr"_h:11499cond = ssrc1 <= ssrc2;11500break;11501case "whilelo_p_p_rr"_h:11502cond = usrc1 < usrc2;11503break;11504case "whilels_p_p_rr"_h:11505cond = usrc1 <= usrc2;11506break;11507case "whilelt_p_p_rr"_h:11508cond = ssrc1 < ssrc2;11509break;11510case "whilege_p_p_rr"_h:11511cond = ssrc1 >= ssrc2;11512break;11513case "whilegt_p_p_rr"_h:11514cond = ssrc1 > ssrc2;11515break;11516case "whilehi_p_p_rr"_h:11517cond = usrc1 > usrc2;11518break;11519case "whilehs_p_p_rr"_h:11520cond = usrc1 >= usrc2;11521break;11522default:11523VIXL_UNIMPLEMENTED();11524break;11525}11526last = last && cond;11527LogicPRegister dst(pd);11528int lane = reverse ? ((lane_count - 1) - i) : i;11529dst.SetActive(vform, lane, last);11530usrc1 += reverse ? -1 : 1;11531}1153211533PredTest(vform, GetPTrue(), pd);11534LogSystemRegister(NZCV);11535}1153611537void Simulator::VisitSVEConditionallyTerminateScalars(11538const Instruction* instr) {11539unsigned rn_code = instr->GetRn();11540unsigned rm_code = instr->GetRm();11541bool is_64_bit = instr->ExtractBit(22) == 1;11542uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);11543uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);11544bool term = false;11545switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {11546case CTERMEQ_rr:11547term = src1 == src2;11548break;11549case CTERMNE_rr:11550term = src1 != src2;11551break;11552default:11553VIXL_UNIMPLEMENTED();11554break;11555}11556ReadNzcv().SetN(term ? 1 : 0);11557ReadNzcv().SetV(term ? 0 : !ReadC());11558LogSystemRegister(NZCV);11559}1156011561void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {11562bool commute_inputs = false;11563Condition cond = al;11564switch (instr->Mask(SVEIntCompareSignedImmMask)) {11565case CMPEQ_p_p_zi:11566cond = eq;11567break;11568case CMPGE_p_p_zi:11569cond = ge;11570break;11571case CMPGT_p_p_zi:11572cond = gt;11573break;11574case CMPLE_p_p_zi:11575cond = ge;11576commute_inputs = true;11577break;11578case CMPLT_p_p_zi:11579cond = gt;11580commute_inputs = true;11581break;11582case CMPNE_p_p_zi:11583cond = ne;11584break;11585default:11586VIXL_UNIMPLEMENTED();11587break;11588}1158911590VectorFormat vform = instr->GetSVEVectorFormat();11591SimVRegister src2;11592dup_immediate(vform,11593src2,11594ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));11595SVEIntCompareVectorsHelper(cond,11596vform,11597ReadPRegister(instr->GetPd()),11598ReadPRegister(instr->GetPgLow8()),11599commute_inputs ? src211600: ReadVRegister(instr->GetRn()),11601commute_inputs ? ReadVRegister(instr->GetRn())11602: src2);11603}1160411605void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {11606bool commute_inputs = false;11607Condition cond = al;11608switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {11609case CMPHI_p_p_zi:11610cond = hi;11611break;11612case CMPHS_p_p_zi:11613cond = hs;11614break;11615case CMPLO_p_p_zi:11616cond = hi;11617commute_inputs = true;11618break;11619case CMPLS_p_p_zi:11620cond = hs;11621commute_inputs = true;11622break;11623default:11624VIXL_UNIMPLEMENTED();11625break;11626}1162711628VectorFormat vform = instr->GetSVEVectorFormat();11629SimVRegister src2;11630dup_immediate(vform, src2, instr->ExtractBits(20, 14));11631SVEIntCompareVectorsHelper(cond,11632vform,11633ReadPRegister(instr->GetPd()),11634ReadPRegister(instr->GetPgLow8()),11635commute_inputs ? src211636: ReadVRegister(instr->GetRn()),11637commute_inputs ? ReadVRegister(instr->GetRn())11638: src2);11639}1164011641void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {11642Instr op = instr->Mask(SVEIntCompareVectorsMask);11643bool is_wide_elements = false;11644switch (op) {11645case CMPEQ_p_p_zw:11646case CMPGE_p_p_zw:11647case CMPGT_p_p_zw:11648case CMPHI_p_p_zw:11649case CMPHS_p_p_zw:11650case CMPLE_p_p_zw:11651case CMPLO_p_p_zw:11652case CMPLS_p_p_zw:11653case CMPLT_p_p_zw:11654case CMPNE_p_p_zw:11655is_wide_elements = true;11656break;11657}1165811659Condition cond;11660switch (op) {11661case CMPEQ_p_p_zw:11662case CMPEQ_p_p_zz:11663cond = eq;11664break;11665case CMPGE_p_p_zw:11666case CMPGE_p_p_zz:11667cond = ge;11668break;11669case CMPGT_p_p_zw:11670case CMPGT_p_p_zz:11671cond = gt;11672break;11673case CMPHI_p_p_zw:11674case CMPHI_p_p_zz:11675cond = hi;11676break;11677case CMPHS_p_p_zw:11678case CMPHS_p_p_zz:11679cond = hs;11680break;11681case CMPNE_p_p_zw:11682case CMPNE_p_p_zz:11683cond = ne;11684break;11685case CMPLE_p_p_zw:11686cond = le;11687break;11688case CMPLO_p_p_zw:11689cond = lo;11690break;11691case CMPLS_p_p_zw:11692cond = ls;11693break;11694case CMPLT_p_p_zw:11695cond = lt;11696break;11697default:11698VIXL_UNIMPLEMENTED();11699cond = al;11700break;11701}1170211703SVEIntCompareVectorsHelper(cond,11704instr->GetSVEVectorFormat(),11705ReadPRegister(instr->GetPd()),11706ReadPRegister(instr->GetPgLow8()),11707ReadVRegister(instr->GetRn()),11708ReadVRegister(instr->GetRm()),11709is_wide_elements);11710}1171111712void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {11713VectorFormat vform = instr->GetSVEVectorFormat();11714SimVRegister& zd = ReadVRegister(instr->GetRd());11715SimVRegister& zn = ReadVRegister(instr->GetRn());1171611717VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||11718(vform == kFormatVnD));1171911720switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {11721case FEXPA_z_z:11722fexpa(vform, zd, zn);11723break;11724default:11725VIXL_UNIMPLEMENTED();11726break;11727}11728}1172911730void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {11731VectorFormat vform = instr->GetSVEVectorFormat();11732SimVRegister& zd = ReadVRegister(instr->GetRd());11733SimVRegister& zn = ReadVRegister(instr->GetRn());11734SimVRegister& zm = ReadVRegister(instr->GetRm());1173511736VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||11737(vform == kFormatVnD));1173811739switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {11740case FTSSEL_z_zz:11741ftssel(vform, zd, zn, zm);11742break;11743default:11744VIXL_UNIMPLEMENTED();11745break;11746}11747}1174811749void Simulator::VisitSVEConstructivePrefix_Unpredicated(11750const Instruction* instr) {11751SimVRegister& zd = ReadVRegister(instr->GetRd());11752SimVRegister& zn = ReadVRegister(instr->GetRn());1175311754switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {11755case MOVPRFX_z_z:11756mov(kFormatVnD, zd, zn); // The lane size is arbitrary.11757break;11758default:11759VIXL_UNIMPLEMENTED();11760break;11761}11762}1176311764void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {11765VectorFormat vform = instr->GetSVEVectorFormat();1176611767SimVRegister& zd = ReadVRegister(instr->GetRd());11768SimVRegister& zm = ReadVRegister(instr->GetRm());1176911770SimVRegister result;11771switch (instr->Mask(SVEIntMulAddPredicatedMask)) {11772case MLA_z_p_zzz:11773mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);11774break;11775case MLS_z_p_zzz:11776mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);11777break;11778case MAD_z_p_zzz:11779// 'za' is encoded in 'Rn'.11780mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);11781break;11782case MSB_z_p_zzz: {11783// 'za' is encoded in 'Rn'.11784mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);11785break;11786}11787default:11788VIXL_UNIMPLEMENTED();11789break;11790}11791mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);11792}1179311794void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {11795VectorFormat vform = instr->GetSVEVectorFormat();11796SimVRegister& zda = ReadVRegister(instr->GetRd());11797SimVRegister& zn = ReadVRegister(instr->GetRn());11798SimVRegister& zm = ReadVRegister(instr->GetRm());1179911800switch (form_hash_) {11801case "sdot_z_zzz"_h:11802sdot(vform, zda, zn, zm);11803break;11804case "udot_z_zzz"_h:11805udot(vform, zda, zn, zm);11806break;11807case "usdot_z_zzz_s"_h:11808usdot(vform, zda, zn, zm);11809break;11810default:11811VIXL_UNIMPLEMENTED();11812break;11813}11814}1181511816void Simulator::VisitSVEMovprfx(const Instruction* instr) {11817VectorFormat vform = instr->GetSVEVectorFormat();11818SimVRegister& zn = ReadVRegister(instr->GetRn());11819SimPRegister& pg = ReadPRegister(instr->GetPgLow8());11820SimVRegister& zd = ReadVRegister(instr->GetRd());1182111822switch (instr->Mask(SVEMovprfxMask)) {11823case MOVPRFX_z_p_z:11824if (instr->ExtractBit(16)) {11825mov_merging(vform, zd, pg, zn);11826} else {11827mov_zeroing(vform, zd, pg, zn);11828}11829break;11830default:11831VIXL_UNIMPLEMENTED();11832break;11833}11834}1183511836void Simulator::VisitSVEIntReduction(const Instruction* instr) {11837VectorFormat vform = instr->GetSVEVectorFormat();11838SimVRegister& vd = ReadVRegister(instr->GetRd());11839SimVRegister& zn = ReadVRegister(instr->GetRn());11840SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1184111842if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {11843switch (instr->Mask(SVEIntReductionLogicalMask)) {11844case ANDV_r_p_z:11845andv(vform, vd, pg, zn);11846break;11847case EORV_r_p_z:11848eorv(vform, vd, pg, zn);11849break;11850case ORV_r_p_z:11851orv(vform, vd, pg, zn);11852break;11853default:11854VIXL_UNIMPLEMENTED();11855break;11856}11857} else {11858switch (instr->Mask(SVEIntReductionMask)) {11859case SADDV_r_p_z:11860saddv(vform, vd, pg, zn);11861break;11862case SMAXV_r_p_z:11863smaxv(vform, vd, pg, zn);11864break;11865case SMINV_r_p_z:11866sminv(vform, vd, pg, zn);11867break;11868case UADDV_r_p_z:11869uaddv(vform, vd, pg, zn);11870break;11871case UMAXV_r_p_z:11872umaxv(vform, vd, pg, zn);11873break;11874case UMINV_r_p_z:11875uminv(vform, vd, pg, zn);11876break;11877default:11878VIXL_UNIMPLEMENTED();11879break;11880}11881}11882}1188311884void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {11885VectorFormat vform = instr->GetSVEVectorFormat();11886SimVRegister& zn = ReadVRegister(instr->GetRn());1188711888SimVRegister result;11889switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {11890case ABS_z_p_z:11891abs(vform, result, zn);11892break;11893case CLS_z_p_z:11894cls(vform, result, zn);11895break;11896case CLZ_z_p_z:11897clz(vform, result, zn);11898break;11899case CNOT_z_p_z:11900cnot(vform, result, zn);11901break;11902case CNT_z_p_z:11903cnt(vform, result, zn);11904break;11905case FABS_z_p_z:11906fabs_(vform, result, zn);11907break;11908case FNEG_z_p_z:11909fneg(vform, result, zn);11910break;11911case NEG_z_p_z:11912neg(vform, result, zn);11913break;11914case NOT_z_p_z:11915not_(vform, result, zn);11916break;11917case SXTB_z_p_z:11918case SXTH_z_p_z:11919case SXTW_z_p_z:11920sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));11921break;11922case UXTB_z_p_z:11923case UXTH_z_p_z:11924case UXTW_z_p_z:11925uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));11926break;11927default:11928VIXL_UNIMPLEMENTED();11929break;11930}1193111932SimVRegister& zd = ReadVRegister(instr->GetRd());11933SimPRegister& pg = ReadPRegister(instr->GetPgLow8());11934mov_merging(vform, zd, pg, result);11935}1193611937void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {11938// There is only one instruction in this group.11939VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);1194011941VectorFormat vform = instr->GetSVEVectorFormat();11942SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));11943SimVRegister& zd = ReadVRegister(instr->GetRd());1194411945if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();1194611947SimVRegister result;11948switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {11949case FCPY_z_p_i: {11950int imm8 = instr->ExtractBits(12, 5);11951uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),11952Instruction::Imm8ToFP64(imm8));11953dup_immediate(vform, result, value);11954break;11955}11956default:11957VIXL_UNIMPLEMENTED();11958break;11959}11960mov_merging(vform, zd, pg, result);11961}1196211963void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(11964const Instruction* instr) {11965VectorFormat vform = instr->GetSVEVectorFormat();11966SimVRegister& zd = ReadVRegister(instr->GetRd());11967SimVRegister scratch;1196811969uint64_t imm = instr->GetImmSVEIntWideUnsigned();11970imm <<= instr->ExtractBit(13) * 8;1197111972switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {11973case ADD_z_zi:11974add_uint(vform, zd, zd, imm);11975break;11976case SQADD_z_zi:11977add_uint(vform, zd, zd, imm).SignedSaturate(vform);11978break;11979case SQSUB_z_zi:11980sub_uint(vform, zd, zd, imm).SignedSaturate(vform);11981break;11982case SUBR_z_zi:11983dup_immediate(vform, scratch, imm);11984sub(vform, zd, scratch, zd);11985break;11986case SUB_z_zi:11987sub_uint(vform, zd, zd, imm);11988break;11989case UQADD_z_zi:11990add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);11991break;11992case UQSUB_z_zi:11993sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);11994break;11995default:11996break;11997}11998}1199912000void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {12001SimVRegister& zd = ReadVRegister(instr->GetRd());1200212003VectorFormat format = instr->GetSVEVectorFormat();12004int64_t imm = instr->GetImmSVEIntWideSigned();12005int shift = instr->ExtractBit(13) * 8;12006imm *= 1 << shift;1200712008switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {12009case DUP_z_i:12010// The encoding of byte-sized lanes with lsl #8 is undefined.12011if ((format == kFormatVnB) && (shift == 8)) {12012VIXL_UNIMPLEMENTED();12013} else {12014dup_immediate(format, zd, imm);12015}12016break;12017default:12018VIXL_UNIMPLEMENTED();12019break;12020}12021}1202212023void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {12024VectorFormat vform = instr->GetSVEVectorFormat();12025SimVRegister& zd = ReadVRegister(instr->GetRd());1202612027switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {12028case FDUP_z_i:12029switch (vform) {12030case kFormatVnH:12031dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));12032break;12033case kFormatVnS:12034dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));12035break;12036case kFormatVnD:12037dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));12038break;12039default:12040VIXL_UNIMPLEMENTED();12041}12042break;12043default:12044VIXL_UNIMPLEMENTED();12045break;12046}12047}1204812049void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(12050const Instruction* instr) {12051switch (instr->Mask(12052SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {12053case LD1H_z_p_bz_s_x32_scaled:12054case LD1SH_z_p_bz_s_x32_scaled:12055case LDFF1H_z_p_bz_s_x32_scaled:12056case LDFF1SH_z_p_bz_s_x32_scaled:12057break;12058default:12059VIXL_UNIMPLEMENTED();12060break;12061}1206212063SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;12064SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);12065}1206612067void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(12068const Instruction* instr) {12069switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {12070case LD1B_z_p_bz_s_x32_unscaled:12071case LD1H_z_p_bz_s_x32_unscaled:12072case LD1SB_z_p_bz_s_x32_unscaled:12073case LD1SH_z_p_bz_s_x32_unscaled:12074case LD1W_z_p_bz_s_x32_unscaled:12075case LDFF1B_z_p_bz_s_x32_unscaled:12076case LDFF1H_z_p_bz_s_x32_unscaled:12077case LDFF1SB_z_p_bz_s_x32_unscaled:12078case LDFF1SH_z_p_bz_s_x32_unscaled:12079case LDFF1W_z_p_bz_s_x32_unscaled:12080break;12081default:12082VIXL_UNIMPLEMENTED();12083break;12084}1208512086SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;12087SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);12088}1208912090void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(12091const Instruction* instr) {12092switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {12093case LD1B_z_p_ai_s:12094VIXL_UNIMPLEMENTED();12095break;12096case LD1H_z_p_ai_s:12097VIXL_UNIMPLEMENTED();12098break;12099case LD1SB_z_p_ai_s:12100VIXL_UNIMPLEMENTED();12101break;12102case LD1SH_z_p_ai_s:12103VIXL_UNIMPLEMENTED();12104break;12105case LD1W_z_p_ai_s:12106VIXL_UNIMPLEMENTED();12107break;12108case LDFF1B_z_p_ai_s:12109VIXL_UNIMPLEMENTED();12110break;12111case LDFF1H_z_p_ai_s:12112VIXL_UNIMPLEMENTED();12113break;12114case LDFF1SB_z_p_ai_s:12115VIXL_UNIMPLEMENTED();12116break;12117case LDFF1SH_z_p_ai_s:12118VIXL_UNIMPLEMENTED();12119break;12120case LDFF1W_z_p_ai_s:12121VIXL_UNIMPLEMENTED();12122break;12123default:12124VIXL_UNIMPLEMENTED();12125break;12126}12127}1212812129void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(12130const Instruction* instr) {12131switch (12132instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {12133case LD1W_z_p_bz_s_x32_scaled:12134case LDFF1W_z_p_bz_s_x32_scaled:12135break;12136default:12137VIXL_UNIMPLEMENTED();12138break;12139}1214012141SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;12142SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);12143}1214412145void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(12146const Instruction* instr) {12147switch (12148instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {12149// Ignore prefetch hint instructions.12150case PRFB_i_p_bz_s_x32_scaled:12151case PRFD_i_p_bz_s_x32_scaled:12152case PRFH_i_p_bz_s_x32_scaled:12153case PRFW_i_p_bz_s_x32_scaled:12154break;12155default:12156VIXL_UNIMPLEMENTED();12157break;12158}12159}1216012161void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(12162const Instruction* instr) {12163switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {12164// Ignore prefetch hint instructions.12165case PRFB_i_p_ai_s:12166case PRFD_i_p_ai_s:12167case PRFH_i_p_ai_s:12168case PRFW_i_p_ai_s:12169break;12170default:12171VIXL_UNIMPLEMENTED();12172break;12173}12174}1217512176void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(12177const Instruction* instr) {12178switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {12179// Ignore prefetch hint instructions.12180case PRFB_i_p_bi_s:12181case PRFD_i_p_bi_s:12182case PRFH_i_p_bi_s:12183case PRFW_i_p_bi_s:12184break;12185default:12186VIXL_UNIMPLEMENTED();12187break;12188}12189}1219012191void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(12192const Instruction* instr) {12193switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {12194// Ignore prefetch hint instructions.12195case PRFB_i_p_br_s:12196case PRFD_i_p_br_s:12197case PRFH_i_p_br_s:12198case PRFW_i_p_br_s:12199if (instr->GetRm() == kZeroRegCode) {12200VIXL_UNIMPLEMENTED();12201}12202break;12203default:12204VIXL_UNIMPLEMENTED();12205break;12206}12207}1220812209void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {12210bool is_signed;12211switch (instr->Mask(SVELoadAndBroadcastElementMask)) {12212case LD1RB_z_p_bi_u8:12213case LD1RB_z_p_bi_u16:12214case LD1RB_z_p_bi_u32:12215case LD1RB_z_p_bi_u64:12216case LD1RH_z_p_bi_u16:12217case LD1RH_z_p_bi_u32:12218case LD1RH_z_p_bi_u64:12219case LD1RW_z_p_bi_u32:12220case LD1RW_z_p_bi_u64:12221case LD1RD_z_p_bi_u64:12222is_signed = false;12223break;12224case LD1RSB_z_p_bi_s16:12225case LD1RSB_z_p_bi_s32:12226case LD1RSB_z_p_bi_s64:12227case LD1RSH_z_p_bi_s32:12228case LD1RSH_z_p_bi_s64:12229case LD1RSW_z_p_bi_s64:12230is_signed = true;12231break;12232default:12233// This encoding group is complete, so no other values should be possible.12234VIXL_UNREACHABLE();12235is_signed = false;12236break;12237}1223812239int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);12240int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);12241VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);12242VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);12243uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;12244uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset;12245VectorFormat unpack_vform =12246SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);12247SimVRegister temp;12248if (!ld1r(vform, unpack_vform, temp, base, is_signed)) return;12249mov_zeroing(vform,12250ReadVRegister(instr->GetRt()),12251ReadPRegister(instr->GetPgLow8()),12252temp);12253}1225412255void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {12256switch (instr->Mask(SVELoadPredicateRegisterMask)) {12257case LDR_p_bi: {12258SimPRegister& pt = ReadPRegister(instr->GetPt());12259int pl = GetPredicateLengthInBytes();12260int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);12261uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);12262uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12263uint64_t address = base + multiplier * pl;12264for (int i = 0; i < pl; i++) {12265VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address + i));12266pt.Insert(i, value);12267}12268LogPRead(instr->GetPt(), address);12269break;12270}12271default:12272VIXL_UNIMPLEMENTED();12273break;12274}12275}1227612277void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {12278switch (instr->Mask(SVELoadVectorRegisterMask)) {12279case LDR_z_bi: {12280SimVRegister& zt = ReadVRegister(instr->GetRt());12281int vl = GetVectorLengthInBytes();12282int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);12283uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);12284uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12285uint64_t address = base + multiplier * vl;12286for (int i = 0; i < vl; i++) {12287VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address + i));12288zt.Insert(i, value);12289}12290LogZRead(instr->GetRt(), address);12291break;12292}12293default:12294VIXL_UNIMPLEMENTED();12295break;12296}12297}1229812299void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(12300const Instruction* instr) {12301switch (instr->Mask(12302SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {12303case LD1D_z_p_bz_d_x32_scaled:12304case LD1H_z_p_bz_d_x32_scaled:12305case LD1SH_z_p_bz_d_x32_scaled:12306case LD1SW_z_p_bz_d_x32_scaled:12307case LD1W_z_p_bz_d_x32_scaled:12308case LDFF1H_z_p_bz_d_x32_scaled:12309case LDFF1W_z_p_bz_d_x32_scaled:12310case LDFF1D_z_p_bz_d_x32_scaled:12311case LDFF1SH_z_p_bz_d_x32_scaled:12312case LDFF1SW_z_p_bz_d_x32_scaled:12313break;12314default:12315VIXL_UNIMPLEMENTED();12316break;12317}1231812319SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;12320SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);12321}1232212323void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(12324const Instruction* instr) {12325switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {12326case LD1D_z_p_bz_d_64_scaled:12327case LD1H_z_p_bz_d_64_scaled:12328case LD1SH_z_p_bz_d_64_scaled:12329case LD1SW_z_p_bz_d_64_scaled:12330case LD1W_z_p_bz_d_64_scaled:12331case LDFF1H_z_p_bz_d_64_scaled:12332case LDFF1W_z_p_bz_d_64_scaled:12333case LDFF1D_z_p_bz_d_64_scaled:12334case LDFF1SH_z_p_bz_d_64_scaled:12335case LDFF1SW_z_p_bz_d_64_scaled:12336break;12337default:12338VIXL_UNIMPLEMENTED();12339break;12340}1234112342SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);12343}1234412345void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(12346const Instruction* instr) {12347switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {12348case LD1B_z_p_bz_d_64_unscaled:12349case LD1D_z_p_bz_d_64_unscaled:12350case LD1H_z_p_bz_d_64_unscaled:12351case LD1SB_z_p_bz_d_64_unscaled:12352case LD1SH_z_p_bz_d_64_unscaled:12353case LD1SW_z_p_bz_d_64_unscaled:12354case LD1W_z_p_bz_d_64_unscaled:12355case LDFF1B_z_p_bz_d_64_unscaled:12356case LDFF1D_z_p_bz_d_64_unscaled:12357case LDFF1H_z_p_bz_d_64_unscaled:12358case LDFF1SB_z_p_bz_d_64_unscaled:12359case LDFF1SH_z_p_bz_d_64_unscaled:12360case LDFF1SW_z_p_bz_d_64_unscaled:12361case LDFF1W_z_p_bz_d_64_unscaled:12362break;12363default:12364VIXL_UNIMPLEMENTED();12365break;12366}1236712368SVEGatherLoadScalarPlusVectorHelper(instr,12369kFormatVnD,12370NO_SVE_OFFSET_MODIFIER);12371}1237212373void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(12374const Instruction* instr) {12375switch (instr->Mask(12376SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {12377case LD1B_z_p_bz_d_x32_unscaled:12378case LD1D_z_p_bz_d_x32_unscaled:12379case LD1H_z_p_bz_d_x32_unscaled:12380case LD1SB_z_p_bz_d_x32_unscaled:12381case LD1SH_z_p_bz_d_x32_unscaled:12382case LD1SW_z_p_bz_d_x32_unscaled:12383case LD1W_z_p_bz_d_x32_unscaled:12384case LDFF1B_z_p_bz_d_x32_unscaled:12385case LDFF1H_z_p_bz_d_x32_unscaled:12386case LDFF1W_z_p_bz_d_x32_unscaled:12387case LDFF1D_z_p_bz_d_x32_unscaled:12388case LDFF1SB_z_p_bz_d_x32_unscaled:12389case LDFF1SH_z_p_bz_d_x32_unscaled:12390case LDFF1SW_z_p_bz_d_x32_unscaled:12391break;12392default:12393VIXL_UNIMPLEMENTED();12394break;12395}1239612397SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;12398SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);12399}1240012401void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(12402const Instruction* instr) {12403switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {12404case LD1B_z_p_ai_d:12405case LD1D_z_p_ai_d:12406case LD1H_z_p_ai_d:12407case LD1SB_z_p_ai_d:12408case LD1SH_z_p_ai_d:12409case LD1SW_z_p_ai_d:12410case LD1W_z_p_ai_d:12411case LDFF1B_z_p_ai_d:12412case LDFF1D_z_p_ai_d:12413case LDFF1H_z_p_ai_d:12414case LDFF1SB_z_p_ai_d:12415case LDFF1SH_z_p_ai_d:12416case LDFF1SW_z_p_ai_d:12417case LDFF1W_z_p_ai_d:12418break;12419default:12420VIXL_UNIMPLEMENTED();12421break;12422}12423bool is_signed = instr->ExtractBit(14) == 0;12424bool is_ff = instr->ExtractBit(13) == 1;12425// Note that these instructions don't use the Dtype encoding.12426int msize_in_bytes_log2 = instr->ExtractBits(24, 23);12427uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;12428LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);12429addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12430if (is_ff) {12431VIXL_UNIMPLEMENTED();12432} else {12433SVEStructuredLoadHelper(kFormatVnD,12434ReadPRegister(instr->GetPgLow8()),12435instr->GetRt(),12436addr,12437is_signed);12438}12439}1244012441void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(12442const Instruction* instr) {12443switch (12444instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {12445// Ignore prefetch hint instructions.12446case PRFB_i_p_bz_d_64_scaled:12447case PRFD_i_p_bz_d_64_scaled:12448case PRFH_i_p_bz_d_64_scaled:12449case PRFW_i_p_bz_d_64_scaled:12450break;12451default:12452VIXL_UNIMPLEMENTED();12453break;12454}12455}1245612457void Simulator::12458VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(12459const Instruction* instr) {12460switch (instr->Mask(12461SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {12462// Ignore prefetch hint instructions.12463case PRFB_i_p_bz_d_x32_scaled:12464case PRFD_i_p_bz_d_x32_scaled:12465case PRFH_i_p_bz_d_x32_scaled:12466case PRFW_i_p_bz_d_x32_scaled:12467break;12468default:12469VIXL_UNIMPLEMENTED();12470break;12471}12472}1247312474void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(12475const Instruction* instr) {12476switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {12477// Ignore prefetch hint instructions.12478case PRFB_i_p_ai_d:12479case PRFD_i_p_ai_d:12480case PRFH_i_p_ai_d:12481case PRFW_i_p_ai_d:12482break;12483default:12484VIXL_UNIMPLEMENTED();12485break;12486}12487}1248812489void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(12490const Instruction* instr) {12491bool is_signed;12492switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {12493case LDFF1B_z_p_br_u8:12494case LDFF1B_z_p_br_u16:12495case LDFF1B_z_p_br_u32:12496case LDFF1B_z_p_br_u64:12497case LDFF1H_z_p_br_u16:12498case LDFF1H_z_p_br_u32:12499case LDFF1H_z_p_br_u64:12500case LDFF1W_z_p_br_u32:12501case LDFF1W_z_p_br_u64:12502case LDFF1D_z_p_br_u64:12503is_signed = false;12504break;12505case LDFF1SB_z_p_br_s16:12506case LDFF1SB_z_p_br_s32:12507case LDFF1SB_z_p_br_s64:12508case LDFF1SH_z_p_br_s32:12509case LDFF1SH_z_p_br_s64:12510case LDFF1SW_z_p_br_s64:12511is_signed = true;12512break;12513default:12514// This encoding group is complete, so no other values should be possible.12515VIXL_UNREACHABLE();12516is_signed = false;12517break;12518}1251912520int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);12521int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);12522VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);12523VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);12524uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12525uint64_t offset = ReadXRegister(instr->GetRm());12526offset <<= msize_in_bytes_log2;12527LogicSVEAddressVector addr(base + offset);12528addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12529SVEFaultTolerantLoadHelper(vform,12530ReadPRegister(instr->GetPgLow8()),12531instr->GetRt(),12532addr,12533kSVEFirstFaultLoad,12534is_signed);12535}1253612537void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(12538const Instruction* instr) {12539bool is_signed = false;12540switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {12541case LDNF1B_z_p_bi_u16:12542case LDNF1B_z_p_bi_u32:12543case LDNF1B_z_p_bi_u64:12544case LDNF1B_z_p_bi_u8:12545case LDNF1D_z_p_bi_u64:12546case LDNF1H_z_p_bi_u16:12547case LDNF1H_z_p_bi_u32:12548case LDNF1H_z_p_bi_u64:12549case LDNF1W_z_p_bi_u32:12550case LDNF1W_z_p_bi_u64:12551break;12552case LDNF1SB_z_p_bi_s16:12553case LDNF1SB_z_p_bi_s32:12554case LDNF1SB_z_p_bi_s64:12555case LDNF1SH_z_p_bi_s32:12556case LDNF1SH_z_p_bi_s64:12557case LDNF1SW_z_p_bi_s64:12558is_signed = true;12559break;12560default:12561VIXL_UNIMPLEMENTED();12562break;12563}12564int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);12565int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);12566VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);12567VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);12568int vl = GetVectorLengthInBytes();12569int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;12570uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12571uint64_t offset =12572(instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);12573LogicSVEAddressVector addr(base + offset);12574addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12575SVEFaultTolerantLoadHelper(vform,12576ReadPRegister(instr->GetPgLow8()),12577instr->GetRt(),12578addr,12579kSVENonFaultLoad,12580is_signed);12581}1258212583void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(12584const Instruction* instr) {12585SimPRegister& pg = ReadPRegister(instr->GetPgLow8());12586VectorFormat vform = kFormatUndefined;1258712588switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {12589case LDNT1B_z_p_bi_contiguous:12590vform = kFormatVnB;12591break;12592case LDNT1D_z_p_bi_contiguous:12593vform = kFormatVnD;12594break;12595case LDNT1H_z_p_bi_contiguous:12596vform = kFormatVnH;12597break;12598case LDNT1W_z_p_bi_contiguous:12599vform = kFormatVnS;12600break;12601default:12602VIXL_UNIMPLEMENTED();12603break;12604}12605int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);12606int vl = GetVectorLengthInBytes();12607uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12608uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;12609LogicSVEAddressVector addr(base + offset);12610addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12611SVEStructuredLoadHelper(vform,12612pg,12613instr->GetRt(),12614addr,12615/* is_signed = */ false);12616}1261712618void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(12619const Instruction* instr) {12620SimPRegister& pg = ReadPRegister(instr->GetPgLow8());12621VectorFormat vform = kFormatUndefined;1262212623switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {12624case LDNT1B_z_p_br_contiguous:12625vform = kFormatVnB;12626break;12627case LDNT1D_z_p_br_contiguous:12628vform = kFormatVnD;12629break;12630case LDNT1H_z_p_br_contiguous:12631vform = kFormatVnH;12632break;12633case LDNT1W_z_p_br_contiguous:12634vform = kFormatVnS;12635break;12636default:12637VIXL_UNIMPLEMENTED();12638break;12639}12640int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);12641uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12642uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;12643LogicSVEAddressVector addr(base + offset);12644addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12645SVEStructuredLoadHelper(vform,12646pg,12647instr->GetRt(),12648addr,12649/* is_signed = */ false);12650}1265112652void Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm(12653const Instruction* instr) {12654SimVRegister& zt = ReadVRegister(instr->GetRt());12655SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1265612657uint64_t dwords = 2;12658VectorFormat vform_dst = kFormatVnQ;12659if ((form_hash_ == "ld1rob_z_p_bi_u8"_h) ||12660(form_hash_ == "ld1roh_z_p_bi_u16"_h) ||12661(form_hash_ == "ld1row_z_p_bi_u32"_h) ||12662(form_hash_ == "ld1rod_z_p_bi_u64"_h)) {12663dwords = 4;12664vform_dst = kFormatVnO;12665}1266612667uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12668uint64_t offset =12669instr->ExtractSignedBits(19, 16) * dwords * kDRegSizeInBytes;12670int msz = instr->ExtractBits(24, 23);12671VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);1267212673for (unsigned i = 0; i < dwords; i++) {12674if (!ld1(kFormatVnD, zt, i, addr + offset + (i * kDRegSizeInBytes))) return;12675}12676mov_zeroing(vform, zt, pg, zt);12677dup_element(vform_dst, zt, zt, 0);12678}1267912680void Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar(12681const Instruction* instr) {12682SimVRegister& zt = ReadVRegister(instr->GetRt());12683SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1268412685uint64_t bytes = 16;12686VectorFormat vform_dst = kFormatVnQ;12687if ((form_hash_ == "ld1rob_z_p_br_contiguous"_h) ||12688(form_hash_ == "ld1roh_z_p_br_contiguous"_h) ||12689(form_hash_ == "ld1row_z_p_br_contiguous"_h) ||12690(form_hash_ == "ld1rod_z_p_br_contiguous"_h)) {12691bytes = 32;12692vform_dst = kFormatVnO;12693}1269412695uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12696uint64_t offset = ReadXRegister(instr->GetRm());12697int msz = instr->ExtractBits(24, 23);12698VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);12699offset <<= msz;12700for (unsigned i = 0; i < bytes; i++) {12701if (!ld1(kFormatVnB, zt, i, addr + offset + i)) return;12702}12703mov_zeroing(vform, zt, pg, zt);12704dup_element(vform_dst, zt, zt, 0);12705}1270612707void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(12708const Instruction* instr) {12709switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {12710case LD2B_z_p_bi_contiguous:12711case LD2D_z_p_bi_contiguous:12712case LD2H_z_p_bi_contiguous:12713case LD2W_z_p_bi_contiguous:12714case LD3B_z_p_bi_contiguous:12715case LD3D_z_p_bi_contiguous:12716case LD3H_z_p_bi_contiguous:12717case LD3W_z_p_bi_contiguous:12718case LD4B_z_p_bi_contiguous:12719case LD4D_z_p_bi_contiguous:12720case LD4H_z_p_bi_contiguous:12721case LD4W_z_p_bi_contiguous: {12722int vl = GetVectorLengthInBytes();12723int msz = instr->ExtractBits(24, 23);12724int reg_count = instr->ExtractBits(22, 21) + 1;12725uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;12726LogicSVEAddressVector addr(12727ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);12728addr.SetMsizeInBytesLog2(msz);12729addr.SetRegCount(reg_count);12730SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),12731ReadPRegister(instr->GetPgLow8()),12732instr->GetRt(),12733addr);12734break;12735}12736default:12737VIXL_UNIMPLEMENTED();12738break;12739}12740}1274112742void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(12743const Instruction* instr) {12744switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {12745case LD2B_z_p_br_contiguous:12746case LD2D_z_p_br_contiguous:12747case LD2H_z_p_br_contiguous:12748case LD2W_z_p_br_contiguous:12749case LD3B_z_p_br_contiguous:12750case LD3D_z_p_br_contiguous:12751case LD3H_z_p_br_contiguous:12752case LD3W_z_p_br_contiguous:12753case LD4B_z_p_br_contiguous:12754case LD4D_z_p_br_contiguous:12755case LD4H_z_p_br_contiguous:12756case LD4W_z_p_br_contiguous: {12757int msz = instr->ExtractBits(24, 23);12758uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);12759VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);12760LogicSVEAddressVector addr(12761ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);12762addr.SetMsizeInBytesLog2(msz);12763addr.SetRegCount(instr->ExtractBits(22, 21) + 1);12764SVEStructuredLoadHelper(vform,12765ReadPRegister(instr->GetPgLow8()),12766instr->GetRt(),12767addr,12768false);12769break;12770}12771default:12772VIXL_UNIMPLEMENTED();12773break;12774}12775}1277612777void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(12778const Instruction* instr) {12779switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {12780case ST1H_z_p_bz_s_x32_scaled:12781case ST1W_z_p_bz_s_x32_scaled: {12782unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);12783VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);12784int scale = instr->ExtractBit(21) * msize_in_bytes_log2;12785uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12786SVEOffsetModifier mod =12787(instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;12788LogicSVEAddressVector addr(base,12789&ReadVRegister(instr->GetRm()),12790kFormatVnS,12791mod,12792scale);12793addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12794SVEStructuredStoreHelper(kFormatVnS,12795ReadPRegister(instr->GetPgLow8()),12796instr->GetRt(),12797addr);12798break;12799}12800default:12801VIXL_UNIMPLEMENTED();12802break;12803}12804}1280512806void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(12807const Instruction* instr) {12808switch (12809instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {12810case ST1B_z_p_bz_s_x32_unscaled:12811case ST1H_z_p_bz_s_x32_unscaled:12812case ST1W_z_p_bz_s_x32_unscaled: {12813unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);12814VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);12815uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12816SVEOffsetModifier mod =12817(instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;12818LogicSVEAddressVector addr(base,12819&ReadVRegister(instr->GetRm()),12820kFormatVnS,12821mod);12822addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12823SVEStructuredStoreHelper(kFormatVnS,12824ReadPRegister(instr->GetPgLow8()),12825instr->GetRt(),12826addr);12827break;12828}12829default:12830VIXL_UNIMPLEMENTED();12831break;12832}12833}1283412835void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(12836const Instruction* instr) {12837int msz = 0;12838switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {12839case ST1B_z_p_ai_s:12840msz = 0;12841break;12842case ST1H_z_p_ai_s:12843msz = 1;12844break;12845case ST1W_z_p_ai_s:12846msz = 2;12847break;12848default:12849VIXL_UNIMPLEMENTED();12850break;12851}12852uint64_t imm = instr->ExtractBits(20, 16) << msz;12853LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);12854addr.SetMsizeInBytesLog2(msz);12855SVEStructuredStoreHelper(kFormatVnS,12856ReadPRegister(instr->GetPgLow8()),12857instr->GetRt(),12858addr);12859}1286012861void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(12862const Instruction* instr) {12863switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {12864case ST1D_z_p_bz_d_64_scaled:12865case ST1H_z_p_bz_d_64_scaled:12866case ST1W_z_p_bz_d_64_scaled: {12867unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);12868VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);12869int scale = instr->ExtractBit(21) * msize_in_bytes_log2;12870uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12871LogicSVEAddressVector addr(base,12872&ReadVRegister(instr->GetRm()),12873kFormatVnD,12874SVE_LSL,12875scale);12876addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12877SVEStructuredStoreHelper(kFormatVnD,12878ReadPRegister(instr->GetPgLow8()),12879instr->GetRt(),12880addr);12881break;12882}12883default:12884VIXL_UNIMPLEMENTED();12885break;12886}12887}1288812889void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(12890const Instruction* instr) {12891switch (12892instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {12893case ST1B_z_p_bz_d_64_unscaled:12894case ST1D_z_p_bz_d_64_unscaled:12895case ST1H_z_p_bz_d_64_unscaled:12896case ST1W_z_p_bz_d_64_unscaled: {12897unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);12898VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);12899uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12900LogicSVEAddressVector addr(base,12901&ReadVRegister(instr->GetRm()),12902kFormatVnD,12903NO_SVE_OFFSET_MODIFIER);12904addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12905SVEStructuredStoreHelper(kFormatVnD,12906ReadPRegister(instr->GetPgLow8()),12907instr->GetRt(),12908addr);12909break;12910}12911default:12912VIXL_UNIMPLEMENTED();12913break;12914}12915}1291612917void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(12918const Instruction* instr) {12919switch (instr->Mask(12920SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {12921case ST1D_z_p_bz_d_x32_scaled:12922case ST1H_z_p_bz_d_x32_scaled:12923case ST1W_z_p_bz_d_x32_scaled: {12924unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);12925VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);12926int scale = instr->ExtractBit(21) * msize_in_bytes_log2;12927uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12928SVEOffsetModifier mod =12929(instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;12930LogicSVEAddressVector addr(base,12931&ReadVRegister(instr->GetRm()),12932kFormatVnD,12933mod,12934scale);12935addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12936SVEStructuredStoreHelper(kFormatVnD,12937ReadPRegister(instr->GetPgLow8()),12938instr->GetRt(),12939addr);12940break;12941}12942default:12943VIXL_UNIMPLEMENTED();12944break;12945}12946}1294712948void Simulator::12949VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(12950const Instruction* instr) {12951switch (instr->Mask(12952SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {12953case ST1B_z_p_bz_d_x32_unscaled:12954case ST1D_z_p_bz_d_x32_unscaled:12955case ST1H_z_p_bz_d_x32_unscaled:12956case ST1W_z_p_bz_d_x32_unscaled: {12957unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);12958VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);12959uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);12960SVEOffsetModifier mod =12961(instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;12962LogicSVEAddressVector addr(base,12963&ReadVRegister(instr->GetRm()),12964kFormatVnD,12965mod);12966addr.SetMsizeInBytesLog2(msize_in_bytes_log2);12967SVEStructuredStoreHelper(kFormatVnD,12968ReadPRegister(instr->GetPgLow8()),12969instr->GetRt(),12970addr);12971break;12972}12973default:12974VIXL_UNIMPLEMENTED();12975break;12976}12977}1297812979void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(12980const Instruction* instr) {12981int msz = 0;12982switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {12983case ST1B_z_p_ai_d:12984msz = 0;12985break;12986case ST1D_z_p_ai_d:12987msz = 3;12988break;12989case ST1H_z_p_ai_d:12990msz = 1;12991break;12992case ST1W_z_p_ai_d:12993msz = 2;12994break;12995default:12996VIXL_UNIMPLEMENTED();12997break;12998}12999uint64_t imm = instr->ExtractBits(20, 16) << msz;13000LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);13001addr.SetMsizeInBytesLog2(msz);13002SVEStructuredStoreHelper(kFormatVnD,13003ReadPRegister(instr->GetPgLow8()),13004instr->GetRt(),13005addr);13006}1300713008void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(13009const Instruction* instr) {13010SimPRegister& pg = ReadPRegister(instr->GetPgLow8());13011VectorFormat vform = kFormatUndefined;1301213013switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {13014case STNT1B_z_p_bi_contiguous:13015vform = kFormatVnB;13016break;13017case STNT1D_z_p_bi_contiguous:13018vform = kFormatVnD;13019break;13020case STNT1H_z_p_bi_contiguous:13021vform = kFormatVnH;13022break;13023case STNT1W_z_p_bi_contiguous:13024vform = kFormatVnS;13025break;13026default:13027VIXL_UNIMPLEMENTED();13028break;13029}13030int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);13031int vl = GetVectorLengthInBytes();13032uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);13033uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;13034LogicSVEAddressVector addr(base + offset);13035addr.SetMsizeInBytesLog2(msize_in_bytes_log2);13036SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);13037}1303813039void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(13040const Instruction* instr) {13041SimPRegister& pg = ReadPRegister(instr->GetPgLow8());13042VectorFormat vform = kFormatUndefined;1304313044switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {13045case STNT1B_z_p_br_contiguous:13046vform = kFormatVnB;13047break;13048case STNT1D_z_p_br_contiguous:13049vform = kFormatVnD;13050break;13051case STNT1H_z_p_br_contiguous:13052vform = kFormatVnH;13053break;13054case STNT1W_z_p_br_contiguous:13055vform = kFormatVnS;13056break;13057default:13058VIXL_UNIMPLEMENTED();13059break;13060}13061int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);13062uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);13063uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;13064LogicSVEAddressVector addr(base + offset);13065addr.SetMsizeInBytesLog2(msize_in_bytes_log2);13066SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);13067}1306813069void Simulator::VisitSVEContiguousStore_ScalarPlusImm(13070const Instruction* instr) {13071switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {13072case ST1B_z_p_bi:13073case ST1D_z_p_bi:13074case ST1H_z_p_bi:13075case ST1W_z_p_bi: {13076int vl = GetVectorLengthInBytes();13077int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);13078int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);13079VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);13080int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;13081uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);13082uint64_t offset =13083(instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);13084VectorFormat vform =13085SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);13086LogicSVEAddressVector addr(base + offset);13087addr.SetMsizeInBytesLog2(msize_in_bytes_log2);13088SVEStructuredStoreHelper(vform,13089ReadPRegister(instr->GetPgLow8()),13090instr->GetRt(),13091addr);13092break;13093}13094default:13095VIXL_UNIMPLEMENTED();13096break;13097}13098}1309913100void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(13101const Instruction* instr) {13102switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {13103case ST1B_z_p_br:13104case ST1D_z_p_br:13105case ST1H_z_p_br:13106case ST1W_z_p_br: {13107uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);13108uint64_t offset = ReadXRegister(instr->GetRm());13109offset <<= instr->ExtractBits(24, 23);13110VectorFormat vform =13111SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));13112LogicSVEAddressVector addr(base + offset);13113addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));13114SVEStructuredStoreHelper(vform,13115ReadPRegister(instr->GetPgLow8()),13116instr->GetRt(),13117addr);13118break;13119}13120default:13121VIXL_UNIMPLEMENTED();13122break;13123}13124}1312513126void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(13127const Instruction* instr) {13128VectorFormat vform = instr->GetSVEVectorFormat();13129SimPRegister& pg = ReadPRegister(instr->GetPgLow8());13130SimVRegister z_result;1313113132switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {13133case CPY_z_p_v:13134dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);13135mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);13136break;13137default:13138VIXL_UNIMPLEMENTED();13139break;13140}13141}1314213143void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(13144const Instruction* instr) {13145switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {13146case ST2B_z_p_bi_contiguous:13147case ST2D_z_p_bi_contiguous:13148case ST2H_z_p_bi_contiguous:13149case ST2W_z_p_bi_contiguous:13150case ST3B_z_p_bi_contiguous:13151case ST3D_z_p_bi_contiguous:13152case ST3H_z_p_bi_contiguous:13153case ST3W_z_p_bi_contiguous:13154case ST4B_z_p_bi_contiguous:13155case ST4D_z_p_bi_contiguous:13156case ST4H_z_p_bi_contiguous:13157case ST4W_z_p_bi_contiguous: {13158int vl = GetVectorLengthInBytes();13159int msz = instr->ExtractBits(24, 23);13160int reg_count = instr->ExtractBits(22, 21) + 1;13161uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;13162LogicSVEAddressVector addr(13163ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);13164addr.SetMsizeInBytesLog2(msz);13165addr.SetRegCount(reg_count);13166SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),13167ReadPRegister(instr->GetPgLow8()),13168instr->GetRt(),13169addr);13170break;13171}13172default:13173VIXL_UNIMPLEMENTED();13174break;13175}13176}1317713178void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(13179const Instruction* instr) {13180switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {13181case ST2B_z_p_br_contiguous:13182case ST2D_z_p_br_contiguous:13183case ST2H_z_p_br_contiguous:13184case ST2W_z_p_br_contiguous:13185case ST3B_z_p_br_contiguous:13186case ST3D_z_p_br_contiguous:13187case ST3H_z_p_br_contiguous:13188case ST3W_z_p_br_contiguous:13189case ST4B_z_p_br_contiguous:13190case ST4D_z_p_br_contiguous:13191case ST4H_z_p_br_contiguous:13192case ST4W_z_p_br_contiguous: {13193int msz = instr->ExtractBits(24, 23);13194uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);13195VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);13196LogicSVEAddressVector addr(13197ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);13198addr.SetMsizeInBytesLog2(msz);13199addr.SetRegCount(instr->ExtractBits(22, 21) + 1);13200SVEStructuredStoreHelper(vform,13201ReadPRegister(instr->GetPgLow8()),13202instr->GetRt(),13203addr);13204break;13205}13206default:13207VIXL_UNIMPLEMENTED();13208break;13209}13210}1321113212void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {13213switch (instr->Mask(SVEStorePredicateRegisterMask)) {13214case STR_p_bi: {13215SimPRegister& pt = ReadPRegister(instr->GetPt());13216int pl = GetPredicateLengthInBytes();13217int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);13218uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);13219uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);13220uint64_t address = base + multiplier * pl;13221for (int i = 0; i < pl; i++) {13222if (!MemWrite(address + i, pt.GetLane<uint8_t>(i))) return;13223}13224LogPWrite(instr->GetPt(), address);13225break;13226}13227default:13228VIXL_UNIMPLEMENTED();13229break;13230}13231}1323213233void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {13234switch (instr->Mask(SVEStoreVectorRegisterMask)) {13235case STR_z_bi: {13236SimVRegister& zt = ReadVRegister(instr->GetRt());13237int vl = GetVectorLengthInBytes();13238int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);13239uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);13240uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);13241uint64_t address = base + multiplier * vl;13242for (int i = 0; i < vl; i++) {13243if (!MemWrite(address + i, zt.GetLane<uint8_t>(i))) return;13244}13245LogZWrite(instr->GetRt(), address);13246break;13247}13248default:13249VIXL_UNIMPLEMENTED();13250break;13251}13252}1325313254void Simulator::VisitSVEMulIndex(const Instruction* instr) {13255VectorFormat vform = instr->GetSVEVectorFormat();13256SimVRegister& zda = ReadVRegister(instr->GetRd());13257SimVRegister& zn = ReadVRegister(instr->GetRn());13258std::pair<int, int> zm_and_index = instr->GetSVEMulZmAndIndex();13259SimVRegister zm = ReadVRegister(zm_and_index.first);13260int index = zm_and_index.second;1326113262SimVRegister temp;13263dup_elements_to_segments(vform, temp, zm, index);1326413265switch (form_hash_) {13266case "sdot_z_zzzi_d"_h:13267case "sdot_z_zzzi_s"_h:13268sdot(vform, zda, zn, temp);13269break;13270case "udot_z_zzzi_d"_h:13271case "udot_z_zzzi_s"_h:13272udot(vform, zda, zn, temp);13273break;13274case "sudot_z_zzzi_s"_h:13275usdot(vform, zda, temp, zn);13276break;13277case "usdot_z_zzzi_s"_h:13278usdot(vform, zda, zn, temp);13279break;13280default:13281VIXL_UNIMPLEMENTED();13282break;13283}13284}1328513286void Simulator::SimulateMatrixMul(const Instruction* instr) {13287VectorFormat vform = kFormatVnS;13288SimVRegister& dn = ReadVRegister(instr->GetRd());13289SimVRegister& n = ReadVRegister(instr->GetRn());13290SimVRegister& m = ReadVRegister(instr->GetRm());1329113292bool n_signed = false;13293bool m_signed = false;13294switch (form_hash_) {13295case "smmla_asimdsame2_g"_h:13296vform = kFormat4S;13297VIXL_FALLTHROUGH();13298case "smmla_z_zzz"_h:13299n_signed = m_signed = true;13300break;13301case "ummla_asimdsame2_g"_h:13302vform = kFormat4S;13303VIXL_FALLTHROUGH();13304case "ummla_z_zzz"_h:13305// Nothing to do.13306break;13307case "usmmla_asimdsame2_g"_h:13308vform = kFormat4S;13309VIXL_FALLTHROUGH();13310case "usmmla_z_zzz"_h:13311m_signed = true;13312break;13313default:13314VIXL_UNIMPLEMENTED();13315break;13316}13317matmul(vform, dn, n, m, n_signed, m_signed);13318}1331913320void Simulator::SimulateSVEFPMatrixMul(const Instruction* instr) {13321VectorFormat vform = instr->GetSVEVectorFormat();13322SimVRegister& zdn = ReadVRegister(instr->GetRd());13323SimVRegister& zn = ReadVRegister(instr->GetRn());13324SimVRegister& zm = ReadVRegister(instr->GetRm());1332513326switch (form_hash_) {13327case "fmmla_z_zzz_s"_h:13328case "fmmla_z_zzz_d"_h:13329fmatmul(vform, zdn, zn, zm);13330break;13331default:13332VIXL_UNIMPLEMENTED();13333break;13334}13335}1333613337void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {13338SimPRegister& pd = ReadPRegister(instr->GetPd());13339SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));13340SimPRegister& pn = ReadPRegister(instr->GetPn());13341SimPRegister result;1334213343switch (instr->Mask(SVEPartitionBreakConditionMask)) {13344case BRKAS_p_p_p_z:13345case BRKA_p_p_p:13346brka(result, pg, pn);13347break;13348case BRKBS_p_p_p_z:13349case BRKB_p_p_p:13350brkb(result, pg, pn);13351break;13352default:13353VIXL_UNIMPLEMENTED();13354break;13355}1335613357if (instr->ExtractBit(4) == 1) {13358mov_merging(pd, pg, result);13359} else {13360mov_zeroing(pd, pg, result);13361}1336213363// Set flag if needed.13364if (instr->ExtractBit(22) == 1) {13365PredTest(kFormatVnB, pg, pd);13366}13367}1336813369void Simulator::VisitSVEPropagateBreakToNextPartition(13370const Instruction* instr) {13371SimPRegister& pdm = ReadPRegister(instr->GetPd());13372SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));13373SimPRegister& pn = ReadPRegister(instr->GetPn());1337413375switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {13376case BRKNS_p_p_pp:13377case BRKN_p_p_pp:13378brkn(pdm, pg, pn);13379break;13380default:13381VIXL_UNIMPLEMENTED();13382break;13383}1338413385// Set flag if needed.13386if (instr->ExtractBit(22) == 1) {13387// Note that this ignores `pg`.13388PredTest(kFormatVnB, GetPTrue(), pdm);13389}13390}1339113392void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {13393SimPRegister& pd = ReadPRegister(instr->GetPd());13394SimPRegister& pn = ReadPRegister(instr->GetPn());1339513396SimVRegister temp = Simulator::ExpandToSimVRegister(pn);13397SimVRegister zero;13398dup_immediate(kFormatVnB, zero, 0);1339913400switch (instr->Mask(SVEUnpackPredicateElementsMask)) {13401case PUNPKHI_p_p:13402zip2(kFormatVnB, temp, temp, zero);13403break;13404case PUNPKLO_p_p:13405zip1(kFormatVnB, temp, temp, zero);13406break;13407default:13408VIXL_UNIMPLEMENTED();13409break;13410}13411Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);13412}1341313414void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {13415VectorFormat vform = instr->GetSVEVectorFormat();13416SimPRegister& pd = ReadPRegister(instr->GetPd());13417SimPRegister& pn = ReadPRegister(instr->GetPn());13418SimPRegister& pm = ReadPRegister(instr->GetPm());1341913420SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);13421SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);1342213423switch (instr->Mask(SVEPermutePredicateElementsMask)) {13424case TRN1_p_pp:13425trn1(vform, temp0, temp0, temp1);13426break;13427case TRN2_p_pp:13428trn2(vform, temp0, temp0, temp1);13429break;13430case UZP1_p_pp:13431uzp1(vform, temp0, temp0, temp1);13432break;13433case UZP2_p_pp:13434uzp2(vform, temp0, temp0, temp1);13435break;13436case ZIP1_p_pp:13437zip1(vform, temp0, temp0, temp1);13438break;13439case ZIP2_p_pp:13440zip2(vform, temp0, temp0, temp1);13441break;13442default:13443VIXL_UNIMPLEMENTED();13444break;13445}13446Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);13447}1344813449void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {13450switch (instr->Mask(SVEReversePredicateElementsMask)) {13451case REV_p_p: {13452VectorFormat vform = instr->GetSVEVectorFormat();13453SimPRegister& pn = ReadPRegister(instr->GetPn());13454SimPRegister& pd = ReadPRegister(instr->GetPd());13455SimVRegister temp = Simulator::ExpandToSimVRegister(pn);13456rev(vform, temp, temp);13457Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);13458break;13459}13460default:13461VIXL_UNIMPLEMENTED();13462break;13463}13464}1346513466void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {13467SimVRegister& zdn = ReadVRegister(instr->GetRd());13468// Second source register "Zm" is encoded where "Zn" would usually be.13469SimVRegister& zm = ReadVRegister(instr->GetRn());1347013471int index = instr->GetSVEExtractImmediate();13472int vl = GetVectorLengthInBytes();13473index = (index >= vl) ? 0 : index;1347413475switch (instr->Mask(SVEPermuteVectorExtractMask)) {13476case EXT_z_zi_des:13477ext(kFormatVnB, zdn, zdn, zm, index);13478break;13479default:13480VIXL_UNIMPLEMENTED();13481break;13482}13483}1348413485void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {13486VectorFormat vform = instr->GetSVEVectorFormat();13487SimVRegister& zd = ReadVRegister(instr->GetRd());13488SimVRegister& zn = ReadVRegister(instr->GetRn());13489SimVRegister& zm = ReadVRegister(instr->GetRm());1349013491switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {13492case TRN1_z_zz:13493trn1(vform, zd, zn, zm);13494break;13495case TRN2_z_zz:13496trn2(vform, zd, zn, zm);13497break;13498case UZP1_z_zz:13499uzp1(vform, zd, zn, zm);13500break;13501case UZP2_z_zz:13502uzp2(vform, zd, zn, zm);13503break;13504case ZIP1_z_zz:13505zip1(vform, zd, zn, zm);13506break;13507case ZIP2_z_zz:13508zip2(vform, zd, zn, zm);13509break;13510default:13511VIXL_UNIMPLEMENTED();13512break;13513}13514}1351513516void Simulator::VisitSVEConditionallyBroadcastElementToVector(13517const Instruction* instr) {13518VectorFormat vform = instr->GetSVEVectorFormat();13519SimVRegister& zdn = ReadVRegister(instr->GetRd());13520SimVRegister& zm = ReadVRegister(instr->GetRn());13521SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1352213523int active_offset = -1;13524switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {13525case CLASTA_z_p_zz:13526active_offset = 1;13527break;13528case CLASTB_z_p_zz:13529active_offset = 0;13530break;13531default:13532VIXL_UNIMPLEMENTED();13533break;13534}1353513536if (active_offset >= 0) {13537std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);13538if (value.first) {13539dup_immediate(vform, zdn, value.second);13540} else {13541// Trigger a line of trace for the operation, even though it doesn't13542// change the register value.13543mov(vform, zdn, zdn);13544}13545}13546}1354713548void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(13549const Instruction* instr) {13550VectorFormat vform = instr->GetSVEVectorFormat();13551SimVRegister& vdn = ReadVRegister(instr->GetRd());13552SimVRegister& zm = ReadVRegister(instr->GetRn());13553SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1355413555int active_offset = -1;13556switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {13557case CLASTA_v_p_z:13558active_offset = 1;13559break;13560case CLASTB_v_p_z:13561active_offset = 0;13562break;13563default:13564VIXL_UNIMPLEMENTED();13565break;13566}1356713568if (active_offset >= 0) {13569LogicVRegister dst(vdn);13570uint64_t src1_value = dst.Uint(vform, 0);13571std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);13572dup_immediate(vform, vdn, 0);13573dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);13574}13575}1357613577void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(13578const Instruction* instr) {13579VectorFormat vform = instr->GetSVEVectorFormat();13580SimVRegister& zm = ReadVRegister(instr->GetRn());13581SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1358213583int active_offset = -1;13584switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {13585case CLASTA_r_p_z:13586active_offset = 1;13587break;13588case CLASTB_r_p_z:13589active_offset = 0;13590break;13591default:13592VIXL_UNIMPLEMENTED();13593break;13594}1359513596if (active_offset >= 0) {13597std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);13598uint64_t masked_src = ReadXRegister(instr->GetRd()) &13599GetUintMask(LaneSizeInBitsFromFormat(vform));13600WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);13601}13602}1360313604void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(13605const Instruction* instr) {13606VectorFormat vform = instr->GetSVEVectorFormat();13607SimVRegister& vdn = ReadVRegister(instr->GetRd());13608SimVRegister& zm = ReadVRegister(instr->GetRn());13609SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1361013611int active_offset = -1;13612switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {13613case LASTA_v_p_z:13614active_offset = 1;13615break;13616case LASTB_v_p_z:13617active_offset = 0;13618break;13619default:13620VIXL_UNIMPLEMENTED();13621break;13622}1362313624if (active_offset >= 0) {13625LogicVRegister dst(vdn);13626std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);13627dup_immediate(vform, vdn, 0);13628dst.SetUint(vform, 0, value.second);13629}13630}1363113632void Simulator::VisitSVEExtractElementToGeneralRegister(13633const Instruction* instr) {13634VectorFormat vform = instr->GetSVEVectorFormat();13635SimVRegister& zm = ReadVRegister(instr->GetRn());13636SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1363713638int active_offset = -1;13639switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {13640case LASTA_r_p_z:13641active_offset = 1;13642break;13643case LASTB_r_p_z:13644active_offset = 0;13645break;13646default:13647VIXL_UNIMPLEMENTED();13648break;13649}1365013651if (active_offset >= 0) {13652std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);13653WriteXRegister(instr->GetRd(), value.second);13654}13655}1365613657void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {13658VectorFormat vform = instr->GetSVEVectorFormat();13659SimVRegister& zd = ReadVRegister(instr->GetRd());13660SimVRegister& zn = ReadVRegister(instr->GetRn());13661SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1366213663switch (instr->Mask(SVECompressActiveElementsMask)) {13664case COMPACT_z_p_z:13665compact(vform, zd, pg, zn);13666break;13667default:13668VIXL_UNIMPLEMENTED();13669break;13670}13671}1367213673void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(13674const Instruction* instr) {13675VectorFormat vform = instr->GetSVEVectorFormat();13676SimPRegister& pg = ReadPRegister(instr->GetPgLow8());13677SimVRegister z_result;1367813679switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {13680case CPY_z_p_r:13681dup_immediate(vform,13682z_result,13683ReadXRegister(instr->GetRn(), Reg31IsStackPointer));13684mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);13685break;13686default:13687VIXL_UNIMPLEMENTED();13688break;13689}13690}1369113692void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {13693VectorFormat vform = instr->GetSVEVectorFormat();13694SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));13695SimVRegister& zd = ReadVRegister(instr->GetRd());1369613697SimVRegister result;13698switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {13699case CPY_z_p_i: {13700// Use unsigned arithmetic to avoid undefined behaviour during the shift.13701uint64_t imm8 = instr->GetImmSVEIntWideSigned();13702dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));13703break;13704}13705default:13706VIXL_UNIMPLEMENTED();13707break;13708}1370913710if (instr->ExtractBit(14) != 0) {13711mov_merging(vform, zd, pg, result);13712} else {13713mov_zeroing(vform, zd, pg, result);13714}13715}1371613717void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {13718SimVRegister& zd = ReadVRegister(instr->GetRd());13719SimVRegister& zn = ReadVRegister(instr->GetRn());13720SimPRegister& pg = ReadPRegister(instr->GetPgLow8());13721SimVRegister result;1372213723// In NEON, the chunk size in which elements are REVersed is in the13724// instruction mnemonic, and the element size attached to the register.13725// SVE reverses the semantics; the mapping to logic functions below is to13726// account for this.13727VectorFormat chunk_form = instr->GetSVEVectorFormat();13728VectorFormat element_form = kFormatUndefined;1372913730switch (instr->Mask(SVEReverseWithinElementsMask)) {13731case RBIT_z_p_z:13732rbit(chunk_form, result, zn);13733break;13734case REVB_z_z:13735VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||13736(chunk_form == kFormatVnD));13737element_form = kFormatVnB;13738break;13739case REVH_z_z:13740VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));13741element_form = kFormatVnH;13742break;13743case REVW_z_z:13744VIXL_ASSERT(chunk_form == kFormatVnD);13745element_form = kFormatVnS;13746break;13747default:13748VIXL_UNIMPLEMENTED();13749break;13750}1375113752if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {13753VIXL_ASSERT(element_form != kFormatUndefined);13754switch (chunk_form) {13755case kFormatVnH:13756rev16(element_form, result, zn);13757break;13758case kFormatVnS:13759rev32(element_form, result, zn);13760break;13761case kFormatVnD:13762rev64(element_form, result, zn);13763break;13764default:13765VIXL_UNIMPLEMENTED();13766}13767}1376813769mov_merging(chunk_form, zd, pg, result);13770}1377113772void Simulator::VisitSVEVectorSplice(const Instruction* instr) {13773VectorFormat vform = instr->GetSVEVectorFormat();13774SimVRegister& zd = ReadVRegister(instr->GetRd());13775SimVRegister& zn = ReadVRegister(instr->GetRn());13776SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);13777SimPRegister& pg = ReadPRegister(instr->GetPgLow8());1377813779switch (form_hash_) {13780case "splice_z_p_zz_des"_h:13781splice(vform, zd, pg, zd, zn);13782break;13783case "splice_z_p_zz_con"_h:13784splice(vform, zd, pg, zn, zn2);13785break;13786default:13787VIXL_UNIMPLEMENTED();13788break;13789}13790}1379113792void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {13793SimVRegister& zd = ReadVRegister(instr->GetRd());13794switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {13795case DUP_z_r:13796dup_immediate(instr->GetSVEVectorFormat(),13797zd,13798ReadXRegister(instr->GetRn(), Reg31IsStackPointer));13799break;13800default:13801VIXL_UNIMPLEMENTED();13802break;13803}13804}1380513806void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {13807SimVRegister& zd = ReadVRegister(instr->GetRd());13808VectorFormat vform = instr->GetSVEVectorFormat();13809switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {13810case INSR_z_v:13811insr(vform, zd, ReadDRegisterBits(instr->GetRn()));13812break;13813default:13814VIXL_UNIMPLEMENTED();13815break;13816}13817}1381813819void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {13820SimVRegister& zd = ReadVRegister(instr->GetRd());13821VectorFormat vform = instr->GetSVEVectorFormat();13822switch (instr->Mask(SVEInsertGeneralRegisterMask)) {13823case INSR_z_r:13824insr(vform, zd, ReadXRegister(instr->GetRn()));13825break;13826default:13827VIXL_UNIMPLEMENTED();13828break;13829}13830}1383113832void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {13833SimVRegister& zd = ReadVRegister(instr->GetRd());13834switch (instr->Mask(SVEBroadcastIndexElementMask)) {13835case DUP_z_zi: {13836std::pair<int, int> index_and_lane_size =13837instr->GetSVEPermuteIndexAndLaneSizeLog2();13838int index = index_and_lane_size.first;13839int lane_size_in_bytes_log_2 = index_and_lane_size.second;13840VectorFormat vform =13841SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);13842if ((index < 0) || (index >= LaneCountFromFormat(vform))) {13843// Out of bounds, set the destination register to zero.13844dup_immediate(kFormatVnD, zd, 0);13845} else {13846dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);13847}13848return;13849}13850default:13851VIXL_UNIMPLEMENTED();13852break;13853}13854}1385513856void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {13857SimVRegister& zd = ReadVRegister(instr->GetRd());13858VectorFormat vform = instr->GetSVEVectorFormat();13859switch (instr->Mask(SVEReverseVectorElementsMask)) {13860case REV_z_z:13861rev(vform, zd, ReadVRegister(instr->GetRn()));13862break;13863default:13864VIXL_UNIMPLEMENTED();13865break;13866}13867}1386813869void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {13870SimVRegister& zd = ReadVRegister(instr->GetRd());13871VectorFormat vform = instr->GetSVEVectorFormat();13872switch (instr->Mask(SVEUnpackVectorElementsMask)) {13873case SUNPKHI_z_z:13874unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);13875break;13876case SUNPKLO_z_z:13877unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);13878break;13879case UUNPKHI_z_z:13880unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);13881break;13882case UUNPKLO_z_z:13883unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);13884break;13885default:13886VIXL_UNIMPLEMENTED();13887break;13888}13889}1389013891void Simulator::VisitSVETableLookup(const Instruction* instr) {13892VectorFormat vform = instr->GetSVEVectorFormat();13893SimVRegister& zd = ReadVRegister(instr->GetRd());13894SimVRegister& zn = ReadVRegister(instr->GetRn());13895SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);13896SimVRegister& zm = ReadVRegister(instr->GetRm());1389713898switch (form_hash_) {13899case "tbl_z_zz_1"_h:13900tbl(vform, zd, zn, zm);13901break;13902case "tbl_z_zz_2"_h:13903tbl(vform, zd, zn, zn2, zm);13904break;13905case "tbx_z_zz"_h:13906tbx(vform, zd, zn, zm);13907break;13908default:13909VIXL_UNIMPLEMENTED();13910break;13911}13912}1391313914void Simulator::VisitSVEPredicateCount(const Instruction* instr) {13915VectorFormat vform = instr->GetSVEVectorFormat();13916SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));13917SimPRegister& pn = ReadPRegister(instr->GetPn());1391813919switch (instr->Mask(SVEPredicateCountMask)) {13920case CNTP_r_p_p: {13921WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));13922break;13923}13924default:13925VIXL_UNIMPLEMENTED();13926break;13927}13928}1392913930void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {13931Instr op = instr->Mask(SVEPredicateLogicalMask);13932SimPRegister& pd = ReadPRegister(instr->GetPd());13933SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));13934SimPRegister& pn = ReadPRegister(instr->GetPn());13935SimPRegister& pm = ReadPRegister(instr->GetPm());13936SimPRegister result;13937switch (op) {13938case ANDS_p_p_pp_z:13939case AND_p_p_pp_z:13940case BICS_p_p_pp_z:13941case BIC_p_p_pp_z:13942case EORS_p_p_pp_z:13943case EOR_p_p_pp_z:13944case NANDS_p_p_pp_z:13945case NAND_p_p_pp_z:13946case NORS_p_p_pp_z:13947case NOR_p_p_pp_z:13948case ORNS_p_p_pp_z:13949case ORN_p_p_pp_z:13950case ORRS_p_p_pp_z:13951case ORR_p_p_pp_z:13952SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),13953result,13954pn,13955pm);13956break;13957case SEL_p_p_pp:13958sel(pd, pg, pn, pm);13959return;13960default:13961VIXL_UNIMPLEMENTED();13962break;13963}1396413965mov_zeroing(pd, pg, result);13966if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {13967PredTest(kFormatVnB, pg, pd);13968}13969}1397013971void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {13972LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));13973LogicPRegister pdn = ReadPRegister(instr->GetPd());13974switch (instr->Mask(SVEPredicateFirstActiveMask)) {13975case PFIRST_p_p_p:13976pfirst(pdn, pg, pdn);13977// TODO: Is this broken when pg == pdn?13978PredTest(kFormatVnB, pg, pdn);13979break;13980default:13981VIXL_UNIMPLEMENTED();13982break;13983}13984}1398513986void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {13987// This group only contains PTRUE{S}, and there are no unallocated encodings.13988VIXL_STATIC_ASSERT(13989SVEPredicateInitializeMask ==13990(SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));13991VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||13992(instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));1399313994LogicPRegister pdn = ReadPRegister(instr->GetPd());13995VectorFormat vform = instr->GetSVEVectorFormat();1399613997ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());13998if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);13999}1400014001void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {14002// This group only contains PNEXT, and there are no unallocated encodings.14003VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);14004VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);1400514006LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));14007LogicPRegister pdn = ReadPRegister(instr->GetPd());14008VectorFormat vform = instr->GetSVEVectorFormat();1400914010pnext(vform, pdn, pg, pdn);14011// TODO: Is this broken when pg == pdn?14012PredTest(vform, pg, pdn);14013}1401414015void Simulator::VisitSVEPredicateReadFromFFR_Predicated(14016const Instruction* instr) {14017LogicPRegister pd(ReadPRegister(instr->GetPd()));14018LogicPRegister pg(ReadPRegister(instr->GetPn()));14019FlagsUpdate flags = LeaveFlags;14020switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {14021case RDFFR_p_p_f:14022// Do nothing.14023break;14024case RDFFRS_p_p_f:14025flags = SetFlags;14026break;14027default:14028VIXL_UNIMPLEMENTED();14029break;14030}1403114032LogicPRegister ffr(ReadFFR());14033mov_zeroing(pd, pg, ffr);1403414035if (flags == SetFlags) {14036PredTest(kFormatVnB, pg, pd);14037}14038}1403914040void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(14041const Instruction* instr) {14042LogicPRegister pd(ReadPRegister(instr->GetPd()));14043LogicPRegister ffr(ReadFFR());14044switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {14045case RDFFR_p_f:14046mov(pd, ffr);14047break;14048default:14049VIXL_UNIMPLEMENTED();14050break;14051}14052}1405314054void Simulator::VisitSVEPredicateTest(const Instruction* instr) {14055switch (instr->Mask(SVEPredicateTestMask)) {14056case PTEST_p_p:14057PredTest(kFormatVnB,14058ReadPRegister(instr->ExtractBits(13, 10)),14059ReadPRegister(instr->GetPn()));14060break;14061default:14062VIXL_UNIMPLEMENTED();14063break;14064}14065}1406614067void Simulator::VisitSVEPredicateZero(const Instruction* instr) {14068switch (instr->Mask(SVEPredicateZeroMask)) {14069case PFALSE_p:14070pfalse(ReadPRegister(instr->GetPd()));14071break;14072default:14073VIXL_UNIMPLEMENTED();14074break;14075}14076}1407714078void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {14079SimPRegister& pd = ReadPRegister(instr->GetPd());14080SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));14081SimPRegister& pn = ReadPRegister(instr->GetPn());14082SimPRegister& pm = ReadPRegister(instr->GetPm());1408314084bool set_flags = false;14085switch (instr->Mask(SVEPropagateBreakMask)) {14086case BRKPAS_p_p_pp:14087set_flags = true;14088VIXL_FALLTHROUGH();14089case BRKPA_p_p_pp:14090brkpa(pd, pg, pn, pm);14091break;14092case BRKPBS_p_p_pp:14093set_flags = true;14094VIXL_FALLTHROUGH();14095case BRKPB_p_p_pp:14096brkpb(pd, pg, pn, pm);14097break;14098default:14099VIXL_UNIMPLEMENTED();14100break;14101}1410214103if (set_flags) {14104PredTest(kFormatVnB, pg, pd);14105}14106}1410714108void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {14109uint64_t length = 0;14110switch (instr->Mask(SVEStackFrameAdjustmentMask)) {14111case ADDPL_r_ri:14112length = GetPredicateLengthInBytes();14113break;14114case ADDVL_r_ri:14115length = GetVectorLengthInBytes();14116break;14117default:14118VIXL_UNIMPLEMENTED();14119}14120uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);14121WriteXRegister(instr->GetRd(),14122base + (length * instr->GetImmSVEVLScale()),14123LogRegWrites,14124Reg31IsStackPointer);14125}1412614127void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {14128int64_t scale = instr->GetImmSVEVLScale();1412914130switch (instr->Mask(SVEStackFrameSizeMask)) {14131case RDVL_r_i:14132WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);14133break;14134default:14135VIXL_UNIMPLEMENTED();14136}14137}1413814139void Simulator::VisitSVEVectorSelect(const Instruction* instr) {14140// The only instruction in this group is `sel`, and there are no unused14141// encodings.14142VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);1414314144VectorFormat vform = instr->GetSVEVectorFormat();14145SimVRegister& zd = ReadVRegister(instr->GetRd());14146SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));14147SimVRegister& zn = ReadVRegister(instr->GetRn());14148SimVRegister& zm = ReadVRegister(instr->GetRm());1414914150sel(vform, zd, pg, zn, zm);14151}1415214153void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {14154switch (instr->Mask(SVEFFRInitialiseMask)) {14155case SETFFR_f: {14156LogicPRegister ffr(ReadFFR());14157ffr.SetAllBits();14158break;14159}14160default:14161VIXL_UNIMPLEMENTED();14162break;14163}14164}1416514166void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {14167switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {14168case WRFFR_f_p: {14169SimPRegister pn(ReadPRegister(instr->GetPn()));14170bool last_active = true;14171for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {14172bool active = pn.GetBit(i);14173if (active && !last_active) {14174// `pn` is non-monotonic. This is UNPREDICTABLE.14175VIXL_ABORT();14176}14177last_active = active;14178}14179mov(ReadFFR(), pn);14180break;14181}14182default:14183VIXL_UNIMPLEMENTED();14184break;14185}14186}1418714188void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {14189bool is_signed;14190switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {14191case LD1B_z_p_bi_u8:14192case LD1B_z_p_bi_u16:14193case LD1B_z_p_bi_u32:14194case LD1B_z_p_bi_u64:14195case LD1H_z_p_bi_u16:14196case LD1H_z_p_bi_u32:14197case LD1H_z_p_bi_u64:14198case LD1W_z_p_bi_u32:14199case LD1W_z_p_bi_u64:14200case LD1D_z_p_bi_u64:14201is_signed = false;14202break;14203case LD1SB_z_p_bi_s16:14204case LD1SB_z_p_bi_s32:14205case LD1SB_z_p_bi_s64:14206case LD1SH_z_p_bi_s32:14207case LD1SH_z_p_bi_s64:14208case LD1SW_z_p_bi_s64:14209is_signed = true;14210break;14211default:14212// This encoding group is complete, so no other values should be possible.14213VIXL_UNREACHABLE();14214is_signed = false;14215break;14216}1421714218int vl = GetVectorLengthInBytes();14219int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);14220int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);14221VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);14222int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;14223uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);14224uint64_t offset =14225(instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);14226VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);14227LogicSVEAddressVector addr(base + offset);14228addr.SetMsizeInBytesLog2(msize_in_bytes_log2);14229SVEStructuredLoadHelper(vform,14230ReadPRegister(instr->GetPgLow8()),14231instr->GetRt(),14232addr,14233is_signed);14234}1423514236void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(14237const Instruction* instr) {14238bool is_signed;14239switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {14240case LD1B_z_p_br_u8:14241case LD1B_z_p_br_u16:14242case LD1B_z_p_br_u32:14243case LD1B_z_p_br_u64:14244case LD1H_z_p_br_u16:14245case LD1H_z_p_br_u32:14246case LD1H_z_p_br_u64:14247case LD1W_z_p_br_u32:14248case LD1W_z_p_br_u64:14249case LD1D_z_p_br_u64:14250is_signed = false;14251break;14252case LD1SB_z_p_br_s16:14253case LD1SB_z_p_br_s32:14254case LD1SB_z_p_br_s64:14255case LD1SH_z_p_br_s32:14256case LD1SH_z_p_br_s64:14257case LD1SW_z_p_br_s64:14258is_signed = true;14259break;14260default:14261// This encoding group is complete, so no other values should be possible.14262VIXL_UNREACHABLE();14263is_signed = false;14264break;14265}1426614267int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);14268int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);14269VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);14270VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);14271uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);14272uint64_t offset = ReadXRegister(instr->GetRm());14273offset <<= msize_in_bytes_log2;14274LogicSVEAddressVector addr(base + offset);14275addr.SetMsizeInBytesLog2(msize_in_bytes_log2);14276SVEStructuredLoadHelper(vform,14277ReadPRegister(instr->GetPgLow8()),14278instr->GetRt(),14279addr,14280is_signed);14281}1428214283void Simulator::DoUnreachable(const Instruction* instr) {14284VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&14285(instr->GetImmException() == kUnreachableOpcode));1428614287fprintf(stream_,14288"Hit UNREACHABLE marker at pc=%p.\n",14289reinterpret_cast<const void*>(instr));14290abort();14291}1429214293void Simulator::Simulate_XdSP_XnSP_Xm(const Instruction* instr) {14294VIXL_ASSERT(form_hash_ == Hash("irg_64i_dp_2src"));14295uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);14296uint64_t rm = ReadXRegister(instr->GetRm());14297uint64_t tag = GenerateRandomTag(rm & 0xffff);14298uint64_t new_val = GetAddressWithAllocationTag(rn, tag);14299WriteXRegister(instr->GetRd(), new_val, LogRegWrites, Reg31IsStackPointer);14300}1430114302void Simulator::SimulateMTEAddSubTag(const Instruction* instr) {14303uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);14304uint64_t rn_tag = GetAllocationTagFromAddress(rn);14305uint64_t tag_offset = instr->ExtractBits(13, 10);14306// TODO: implement GCR_EL1.Exclude to provide a tag exclusion list.14307uint64_t new_tag = ChooseNonExcludedTag(rn_tag, tag_offset);1430814309uint64_t offset = instr->ExtractBits(21, 16) * kMTETagGranuleInBytes;14310int carry = 0;14311if (form_hash_ == Hash("subg_64_addsub_immtags")) {14312offset = ~offset;14313carry = 1;14314} else {14315VIXL_ASSERT(form_hash_ == Hash("addg_64_addsub_immtags"));14316}14317uint64_t new_val =14318AddWithCarry(kXRegSize, /* set_flags = */ false, rn, offset, carry);14319new_val = GetAddressWithAllocationTag(new_val, new_tag);14320WriteXRegister(instr->GetRd(), new_val, LogRegWrites, Reg31IsStackPointer);14321}1432214323void Simulator::SimulateMTETagMaskInsert(const Instruction* instr) {14324VIXL_ASSERT(form_hash_ == Hash("gmi_64g_dp_2src"));14325uint64_t mask = ReadXRegister(instr->GetRm());14326uint64_t tag = GetAllocationTagFromAddress(14327ReadXRegister(instr->GetRn(), Reg31IsStackPointer));14328uint64_t mask_bit = 1 << tag;14329WriteXRegister(instr->GetRd(), mask | mask_bit);14330}1433114332void Simulator::SimulateMTESubPointer(const Instruction* instr) {14333uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);14334uint64_t rm = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);1433514336VIXL_ASSERT((form_hash_ == Hash("subps_64s_dp_2src")) ||14337(form_hash_ == Hash("subp_64s_dp_2src")));14338bool set_flags = (form_hash_ == Hash("subps_64s_dp_2src"));1433914340rn = ExtractSignedBitfield64(55, 0, rn);14341rm = ExtractSignedBitfield64(55, 0, rm);14342uint64_t new_val = AddWithCarry(kXRegSize, set_flags, rn, ~rm, 1);14343WriteXRegister(instr->GetRd(), new_val);14344}1434514346void Simulator::SimulateMTEStoreTagPair(const Instruction* instr) {14347uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);14348uint64_t rt = ReadXRegister(instr->GetRt());14349uint64_t rt2 = ReadXRegister(instr->GetRt2());14350int offset = instr->GetImmLSPair() * static_cast<int>(kMTETagGranuleInBytes);1435114352AddrMode addr_mode = Offset;14353switch (form_hash_) {14354case Hash("stgp_64_ldstpair_off"):14355// Default is the offset mode.14356break;14357case Hash("stgp_64_ldstpair_post"):14358addr_mode = PostIndex;14359break;14360case Hash("stgp_64_ldstpair_pre"):14361addr_mode = PreIndex;14362break;14363default:14364VIXL_UNIMPLEMENTED();14365}1436614367uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addr_mode);14368if (!IsAligned(address, kMTETagGranuleInBytes)) {14369VIXL_ALIGNMENT_EXCEPTION();14370}1437114372int tag = GetAllocationTagFromAddress(rn);14373meta_data_.SetMTETag(address, tag);1437414375if (!MemWrite<uint64_t>(address, rt)) return;14376if (!MemWrite<uint64_t>(address + kXRegSizeInBytes, rt2)) return;14377}1437814379void Simulator::SimulateMTEStoreTag(const Instruction* instr) {14380uint64_t rt = ReadXRegister(instr->GetRt(), Reg31IsStackPointer);14381int offset = instr->GetImmLS() * static_cast<int>(kMTETagGranuleInBytes);1438214383AddrMode addr_mode = Offset;14384switch (form_hash_) {14385case Hash("st2g_64soffset_ldsttags"):14386case Hash("stg_64soffset_ldsttags"):14387case Hash("stz2g_64soffset_ldsttags"):14388case Hash("stzg_64soffset_ldsttags"):14389// Default is the offset mode.14390break;14391case Hash("st2g_64spost_ldsttags"):14392case Hash("stg_64spost_ldsttags"):14393case Hash("stz2g_64spost_ldsttags"):14394case Hash("stzg_64spost_ldsttags"):14395addr_mode = PostIndex;14396break;14397case Hash("st2g_64spre_ldsttags"):14398case Hash("stg_64spre_ldsttags"):14399case Hash("stz2g_64spre_ldsttags"):14400case Hash("stzg_64spre_ldsttags"):14401addr_mode = PreIndex;14402break;14403default:14404VIXL_UNIMPLEMENTED();14405}1440614407bool is_pair = false;14408switch (form_hash_) {14409case Hash("st2g_64soffset_ldsttags"):14410case Hash("st2g_64spost_ldsttags"):14411case Hash("st2g_64spre_ldsttags"):14412case Hash("stz2g_64soffset_ldsttags"):14413case Hash("stz2g_64spost_ldsttags"):14414case Hash("stz2g_64spre_ldsttags"):14415is_pair = true;14416break;14417default:14418break;14419}1442014421bool is_zeroing = false;14422switch (form_hash_) {14423case Hash("stz2g_64soffset_ldsttags"):14424case Hash("stz2g_64spost_ldsttags"):14425case Hash("stz2g_64spre_ldsttags"):14426case Hash("stzg_64soffset_ldsttags"):14427case Hash("stzg_64spost_ldsttags"):14428case Hash("stzg_64spre_ldsttags"):14429is_zeroing = true;14430break;14431default:14432break;14433}1443414435uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addr_mode);1443614437if (is_zeroing) {14438if (!IsAligned(reinterpret_cast<uintptr_t>(address),14439kMTETagGranuleInBytes)) {14440VIXL_ALIGNMENT_EXCEPTION();14441}14442VIXL_STATIC_ASSERT(kMTETagGranuleInBytes >= sizeof(uint64_t));14443VIXL_STATIC_ASSERT(kMTETagGranuleInBytes % sizeof(uint64_t) == 0);1444414445size_t fill_size = kMTETagGranuleInBytes;14446if (is_pair) {14447fill_size += kMTETagGranuleInBytes;14448}1444914450size_t fill_offset = 0;14451while (fill_offset < fill_size) {14452if (!MemWrite<uint64_t>(address + fill_offset, 0)) return;14453fill_offset += sizeof(uint64_t);14454}14455}1445614457int tag = GetAllocationTagFromAddress(rt);14458meta_data_.SetMTETag(address, tag, instr);14459if (is_pair) {14460meta_data_.SetMTETag(address + kMTETagGranuleInBytes, tag, instr);14461}14462}1446314464void Simulator::SimulateMTELoadTag(const Instruction* instr) {14465uint64_t rt = ReadXRegister(instr->GetRt());14466int offset = instr->GetImmLS() * static_cast<int>(kMTETagGranuleInBytes);1446714468switch (form_hash_) {14469case Hash("ldg_64loffset_ldsttags"):14470break;14471default:14472VIXL_UNIMPLEMENTED();14473}1447414475uintptr_t address = AddressModeHelper(instr->GetRn(), offset, Offset);14476address = AlignDown(address, kMTETagGranuleInBytes);14477uint64_t tag = meta_data_.GetMTETag(address, instr);14478WriteXRegister(instr->GetRt(), GetAddressWithAllocationTag(rt, tag));14479}1448014481void Simulator::SimulateCpyFP(const Instruction* instr) {14482MOPSPHelper<"cpy"_h>(instr);14483LogSystemRegister(NZCV);14484}1448514486void Simulator::SimulateCpyP(const Instruction* instr) {14487MOPSPHelper<"cpy"_h>(instr);1448814489int d = instr->GetRd();14490int n = instr->GetRn();14491int s = instr->GetRs();1449214493// Determine copy direction. For cases in which direction is implementation14494// defined, use forward.14495bool is_backwards = false;14496uint64_t xs = ReadXRegister(s);14497uint64_t xd = ReadXRegister(d);14498uint64_t xn = ReadXRegister(n);1449914500// Ignore the top byte of addresses for comparisons. We can use xn as is,14501// as it should have zero in bits 63:55.14502uint64_t xs_tbi = ExtractUnsignedBitfield64(55, 0, xs);14503uint64_t xd_tbi = ExtractUnsignedBitfield64(55, 0, xd);14504VIXL_ASSERT(ExtractUnsignedBitfield64(63, 55, xn) == 0);14505if ((xs_tbi < xd_tbi) && ((xs_tbi + xn) > xd_tbi)) {14506is_backwards = true;14507WriteXRegister(s, xs + xn);14508WriteXRegister(d, xd + xn);14509}1451014511ReadNzcv().SetN(is_backwards ? 1 : 0);14512LogSystemRegister(NZCV);14513}1451414515void Simulator::SimulateCpyM(const Instruction* instr) {14516VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"cpy"_h>());14517VIXL_ASSERT(instr->IsMOPSMainOf(GetLastExecutedInstruction(), "cpy"_h));1451814519int d = instr->GetRd();14520int n = instr->GetRn();14521int s = instr->GetRs();1452214523uint64_t xd = ReadXRegister(d);14524uint64_t xn = ReadXRegister(n);14525uint64_t xs = ReadXRegister(s);14526bool is_backwards = ReadN();1452714528int step = 1;14529if (is_backwards) {14530step = -1;14531xs--;14532xd--;14533}1453414535while (xn--) {14536VIXL_DEFINE_OR_RETURN(temp, MemRead<uint8_t>(xs));14537if (!MemWrite<uint8_t>(xd, temp)) return;14538LogMemTransfer(xd, xs, temp);14539xs += step;14540xd += step;14541}1454214543if (is_backwards) {14544xs++;14545xd++;14546}1454714548WriteXRegister(d, xd);14549WriteXRegister(n, 0);14550WriteXRegister(s, xs);14551}1455214553void Simulator::SimulateCpyE(const Instruction* instr) {14554USE(instr);14555VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"cpy"_h>());14556VIXL_ASSERT(instr->IsMOPSEpilogueOf(GetLastExecutedInstruction(), "cpy"_h));14557// This implementation does nothing in the epilogue; all copying is completed14558// in the "main" part.14559}1456014561void Simulator::SimulateSetP(const Instruction* instr) {14562MOPSPHelper<"set"_h>(instr);14563LogSystemRegister(NZCV);14564}1456514566void Simulator::SimulateSetM(const Instruction* instr) {14567VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"set"_h>());14568VIXL_ASSERT(instr->IsMOPSMainOf(GetLastExecutedInstruction(), "set"_h));1456914570uint64_t xd = ReadXRegister(instr->GetRd());14571uint64_t xn = ReadXRegister(instr->GetRn());14572uint64_t xs = ReadXRegister(instr->GetRs());1457314574while (xn--) {14575LogWrite(instr->GetRs(), GetPrintRegPartial(kPrintRegLaneSizeB), xd);14576if (!MemWrite<uint8_t>(xd++, xs)) return;14577}14578WriteXRegister(instr->GetRd(), xd);14579WriteXRegister(instr->GetRn(), 0);14580}1458114582void Simulator::SimulateSetE(const Instruction* instr) {14583USE(instr);14584VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"set"_h>());14585VIXL_ASSERT(instr->IsMOPSEpilogueOf(GetLastExecutedInstruction(), "set"_h));14586// This implementation does nothing in the epilogue; all setting is completed14587// in the "main" part.14588}1458914590void Simulator::SimulateSetGP(const Instruction* instr) {14591MOPSPHelper<"setg"_h>(instr);1459214593uint64_t xd = ReadXRegister(instr->GetRd());14594uint64_t xn = ReadXRegister(instr->GetRn());1459514596if ((xn > 0) && !IsAligned(xd, kMTETagGranuleInBytes)) {14597VIXL_ALIGNMENT_EXCEPTION();14598}1459914600if (!IsAligned(xn, kMTETagGranuleInBytes)) {14601VIXL_ALIGNMENT_EXCEPTION();14602}1460314604LogSystemRegister(NZCV);14605}1460614607void Simulator::SimulateSetGM(const Instruction* instr) {14608uint64_t xd = ReadXRegister(instr->GetRd());14609uint64_t xn = ReadXRegister(instr->GetRn());1461014611int tag = GetAllocationTagFromAddress(xd);14612while (xn) {14613meta_data_.SetMTETag(xd, tag);14614xd += 16;14615xn -= 16;14616}14617SimulateSetM(instr);14618}1461914620void Simulator::DoTrace(const Instruction* instr) {14621VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&14622(instr->GetImmException() == kTraceOpcode));1462314624// Read the arguments encoded inline in the instruction stream.14625uint32_t parameters;14626uint32_t command;1462714628VIXL_STATIC_ASSERT(sizeof(*instr) == 1);14629memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters));14630memcpy(&command, instr + kTraceCommandOffset, sizeof(command));1463114632switch (command) {14633case TRACE_ENABLE:14634SetTraceParameters(GetTraceParameters() | parameters);14635break;14636case TRACE_DISABLE:14637SetTraceParameters(GetTraceParameters() & ~parameters);14638break;14639default:14640VIXL_UNREACHABLE();14641}1464214643WritePc(instr->GetInstructionAtOffset(kTraceLength));14644}146451464614647void Simulator::DoLog(const Instruction* instr) {14648VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&14649(instr->GetImmException() == kLogOpcode));1465014651// Read the arguments encoded inline in the instruction stream.14652uint32_t parameters;1465314654VIXL_STATIC_ASSERT(sizeof(*instr) == 1);14655memcpy(¶meters, instr + kTraceParamsOffset, sizeof(parameters));1465614657// We don't support a one-shot LOG_DISASM.14658VIXL_ASSERT((parameters & LOG_DISASM) == 0);14659// Print the requested information.14660if (parameters & LOG_SYSREGS) PrintSystemRegisters();14661if (parameters & LOG_REGS) PrintRegisters();14662if (parameters & LOG_VREGS) PrintVRegisters();1466314664WritePc(instr->GetInstructionAtOffset(kLogLength));14665}146661466714668void Simulator::DoPrintf(const Instruction* instr) {14669VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&14670(instr->GetImmException() == kPrintfOpcode));1467114672// Read the arguments encoded inline in the instruction stream.14673uint32_t arg_count;14674uint32_t arg_pattern_list;14675VIXL_STATIC_ASSERT(sizeof(*instr) == 1);14676memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));14677memcpy(&arg_pattern_list,14678instr + kPrintfArgPatternListOffset,14679sizeof(arg_pattern_list));1468014681VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);14682VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);1468314684// We need to call the host printf function with a set of arguments defined by14685// arg_pattern_list. Because we don't know the types and sizes of the14686// arguments, this is very difficult to do in a robust and portable way. To14687// work around the problem, we pick apart the format string, and print one14688// format placeholder at a time.1468914690// Allocate space for the format string. We take a copy, so we can modify it.14691// Leave enough space for one extra character per expected argument (plus the14692// '\0' termination).14693const char* format_base = ReadRegister<const char*>(0);14694VIXL_ASSERT(format_base != NULL);14695size_t length = strlen(format_base) + 1;14696char* const format = new char[length + arg_count];1469714698// A list of chunks, each with exactly one format placeholder.14699const char* chunks[kPrintfMaxArgCount];1470014701// Copy the format string and search for format placeholders.14702uint32_t placeholder_count = 0;14703char* format_scratch = format;14704for (size_t i = 0; i < length; i++) {14705if (format_base[i] != '%') {14706*format_scratch++ = format_base[i];14707} else {14708if (format_base[i + 1] == '%') {14709// Ignore explicit "%%" sequences.14710*format_scratch++ = format_base[i];14711i++;14712// Chunks after the first are passed as format strings to printf, so we14713// need to escape '%' characters in those chunks.14714if (placeholder_count > 0) *format_scratch++ = format_base[i];14715} else {14716VIXL_CHECK(placeholder_count < arg_count);14717// Insert '\0' before placeholders, and store their locations.14718*format_scratch++ = '\0';14719chunks[placeholder_count++] = format_scratch;14720*format_scratch++ = format_base[i];14721}14722}14723}14724VIXL_CHECK(placeholder_count == arg_count);1472514726// Finally, call printf with each chunk, passing the appropriate register14727// argument. Normally, printf returns the number of bytes transmitted, so we14728// can emulate a single printf call by adding the result from each chunk. If14729// any call returns a negative (error) value, though, just return that value.1473014731printf("%s", clr_printf);1473214733// Because '\0' is inserted before each placeholder, the first string in14734// 'format' contains no format placeholders and should be printed literally.14735int result = printf("%s", format);14736int pcs_r = 1; // Start at x1. x0 holds the format string.14737int pcs_f = 0; // Start at d0.14738if (result >= 0) {14739for (uint32_t i = 0; i < placeholder_count; i++) {14740int part_result = -1;1474114742uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);14743arg_pattern &= (1 << kPrintfArgPatternBits) - 1;14744switch (arg_pattern) {14745case kPrintfArgW:14746part_result = printf(chunks[i], ReadWRegister(pcs_r++));14747break;14748case kPrintfArgX:14749part_result = printf(chunks[i], ReadXRegister(pcs_r++));14750break;14751case kPrintfArgD:14752part_result = printf(chunks[i], ReadDRegister(pcs_f++));14753break;14754default:14755VIXL_UNREACHABLE();14756}1475714758if (part_result < 0) {14759// Handle error values.14760result = part_result;14761break;14762}1476314764result += part_result;14765}14766}1476714768printf("%s", clr_normal);1476914770// Printf returns its result in x0 (just like the C library's printf).14771WriteXRegister(0, result);1477214773// The printf parameters are inlined in the code, so skip them.14774WritePc(instr->GetInstructionAtOffset(kPrintfLength));1477514776// Set LR as if we'd just called a native printf function.14777WriteLr(ReadPc());1477814779delete[] format;14780}147811478214783#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT14784void Simulator::DoRuntimeCall(const Instruction* instr) {14785VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));14786// The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function14787// to call are passed inlined in the assembly.14788VIXL_DEFINE_OR_RETURN(call_wrapper_address,14789MemRead<uintptr_t>(instr + kRuntimeCallWrapperOffset));14790VIXL_DEFINE_OR_RETURN(function_address,14791MemRead<uintptr_t>(instr + kRuntimeCallFunctionOffset));14792VIXL_DEFINE_OR_RETURN(call_type,14793MemRead<uint32_t>(instr + kRuntimeCallTypeOffset));14794auto runtime_call_wrapper =14795reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);1479614797if (static_cast<RuntimeCallType>(call_type) == kCallRuntime) {14798WriteRegister(kLinkRegCode,14799instr->GetInstructionAtOffset(kRuntimeCallLength));14800}14801runtime_call_wrapper(this, function_address);14802// Read the return address from `lr` and write it into `pc`.14803WritePc(ReadRegister<Instruction*>(kLinkRegCode));14804}14805#else14806void Simulator::DoRuntimeCall(const Instruction* instr) {14807USE(instr);14808VIXL_UNREACHABLE();14809}14810#endif148111481214813void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {14814VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);1481514816typedef ConfigureCPUFeaturesElementType ElementType;14817VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <14818std::numeric_limits<ElementType>::max());1481914820// k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.1482114822size_t element_size = sizeof(ElementType);14823size_t offset = kConfigureCPUFeaturesListOffset;1482414825// Read the kNone-terminated list of features.14826CPUFeatures parameters;14827while (true) {14828VIXL_DEFINE_OR_RETURN(feature, MemRead<ElementType>(instr + offset));14829offset += element_size;14830if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;14831parameters.Combine(static_cast<CPUFeatures::Feature>(feature));14832}1483314834switch (instr->GetImmException()) {14835case kSetCPUFeaturesOpcode:14836SetCPUFeatures(parameters);14837break;14838case kEnableCPUFeaturesOpcode:14839GetCPUFeatures()->Combine(parameters);14840break;14841case kDisableCPUFeaturesOpcode:14842GetCPUFeatures()->Remove(parameters);14843break;14844default:14845VIXL_UNREACHABLE();14846break;14847}1484814849WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));14850}148511485214853void Simulator::DoSaveCPUFeatures(const Instruction* instr) {14854VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&14855(instr->GetImmException() == kSaveCPUFeaturesOpcode));14856USE(instr);1485714858saved_cpu_features_.push_back(*GetCPUFeatures());14859}148601486114862void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {14863VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&14864(instr->GetImmException() == kRestoreCPUFeaturesOpcode));14865USE(instr);1486614867SetCPUFeatures(saved_cpu_features_.back());14868saved_cpu_features_.pop_back();14869}1487014871void* Simulator::Mmap(14872void* address, size_t length, int prot, int flags, int fd, off_t offset) {14873// The underlying system `mmap` in the simulated environment doesn't recognize14874// PROT_BTI and PROT_MTE. Although the kernel probably just ignores the bits14875// it doesn't know, mask those protections out before calling is safer.14876int intenal_prot = prot;14877prot &= ~(PROT_BTI | PROT_MTE);1487814879uint64_t address2 = reinterpret_cast<uint64_t>(14880mmap(address, length, prot, flags, fd, offset));1488114882if (intenal_prot & PROT_MTE) {14883// The returning address of `mmap` isn't tagged.14884int tag = static_cast<int>(GenerateRandomTag());14885SetGranuleTag(address2, tag, length);14886address2 = GetAddressWithAllocationTag(address2, tag);14887}1488814889return reinterpret_cast<void*>(address2);14890}148911489214893int Simulator::Munmap(void* address, size_t length, int prot) {14894if (prot & PROT_MTE) {14895// Untag the address since `munmap` doesn't recognize the memory tagging14896// managed by the Simulator.14897address = AddressUntag(address);14898CleanGranuleTag(reinterpret_cast<char*>(address), length);14899}1490014901return munmap(address, length);14902}149031490414905} // namespace aarch6414906} // namespace vixl1490714908#endif // VIXL_INCLUDE_SIMULATOR_AARCH64149091491014911