• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015, VIXL authors
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 //   * Redistributions of source code must retain the above copyright notice,
8 //     this list of conditions and the following disclaimer.
9 //   * Redistributions in binary form must reproduce the above copyright notice,
10 //     this list of conditions and the following disclaimer in the documentation
11 //     and/or other materials provided with the distribution.
12 //   * Neither the name of ARM Limited nor the names of its contributors may be
13 //     used to endorse or promote products derived from this software without
14 //     specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 
27 #ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
28 
29 #include <errno.h>
30 #include <unistd.h>
31 
32 #include <cmath>
33 #include <cstring>
34 #include <limits>
35 
36 #include "simulator-aarch64.h"
37 
38 namespace vixl {
39 namespace aarch64 {
40 
41 using vixl::internal::SimFloat16;
42 
43 const Instruction* Simulator::kEndOfSimAddress = NULL;
44 
SetBits(int msb,int lsb,uint32_t bits)45 void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
46   int width = msb - lsb + 1;
47   VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
48 
49   bits <<= lsb;
50   uint32_t mask = ((1 << width) - 1) << lsb;
51   VIXL_ASSERT((mask & write_ignore_mask_) == 0);
52 
53   value_ = (value_ & ~mask) | (bits & mask);
54 }
55 
56 
DefaultValueFor(SystemRegister id)57 SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
58   switch (id) {
59     case NZCV:
60       return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
61     case FPCR:
62       return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
63     default:
64       VIXL_UNREACHABLE();
65       return SimSystemRegister();
66   }
67 }
68 
69 
GetFormToVisitorFnMap()70 const Simulator::FormToVisitorFnMap* Simulator::GetFormToVisitorFnMap() {
71   static const FormToVisitorFnMap form_to_visitor = {
72       DEFAULT_FORM_TO_VISITOR_MAP(Simulator),
73       SIM_AUD_VISITOR_MAP(Simulator),
74       {"smlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
75       {"smlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
76       {"smull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
77       {"sqdmlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
78       {"sqdmlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
79       {"sqdmull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
80       {"umlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
81       {"umlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
82       {"umull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
83       {"fcmla_asimdelem_c_h"_h, &Simulator::SimulateNEONComplexMulByElement},
84       {"fcmla_asimdelem_c_s"_h, &Simulator::SimulateNEONComplexMulByElement},
85       {"fmlal2_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},
86       {"fmlal_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},
87       {"fmlsl2_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},
88       {"fmlsl_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},
89       {"fmla_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},
90       {"fmls_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},
91       {"fmulx_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},
92       {"fmul_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},
93       {"fmla_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},
94       {"fmls_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},
95       {"fmulx_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},
96       {"fmul_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},
97       {"sdot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},
98       {"udot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},
99       {"adclb_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},
100       {"adclt_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},
101       {"addhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
102       {"addhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
103       {"addp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
104       {"bcax_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
105       {"bdep_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
106       {"bext_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
107       {"bgrp_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
108       {"bsl1n_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
109       {"bsl2n_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
110       {"bsl_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
111       {"cadd_z_zz"_h, &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},
112       {"cdot_z_zzz"_h, &Simulator::SimulateSVEComplexDotProduct},
113       {"cdot_z_zzzi_d"_h, &Simulator::SimulateSVEComplexDotProduct},
114       {"cdot_z_zzzi_s"_h, &Simulator::SimulateSVEComplexDotProduct},
115       {"cmla_z_zzz"_h, &Simulator::SimulateSVEComplexIntMulAdd},
116       {"cmla_z_zzzi_h"_h, &Simulator::SimulateSVEComplexIntMulAdd},
117       {"cmla_z_zzzi_s"_h, &Simulator::SimulateSVEComplexIntMulAdd},
118       {"eor3_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
119       {"eorbt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
120       {"eortb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
121       {"ext_z_zi_con"_h, &Simulator::Simulate_ZdB_Zn1B_Zn2B_imm},
122       {"faddp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
123       {"fcvtlt_z_p_z_h2s"_h, &Simulator::SimulateSVEFPConvertLong},
124       {"fcvtlt_z_p_z_s2d"_h, &Simulator::SimulateSVEFPConvertLong},
125       {"fcvtnt_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD},
126       {"fcvtnt_z_p_z_s2h"_h, &Simulator::Simulate_ZdH_PgM_ZnS},
127       {"fcvtx_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD},
128       {"fcvtxnt_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD},
129       {"flogb_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT},
130       {"fmaxnmp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
131       {"fmaxp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
132       {"fminnmp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
133       {"fminp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
134       {"fmlalb_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},
135       {"fmlalb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
136       {"fmlalt_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},
137       {"fmlalt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
138       {"fmlslb_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},
139       {"fmlslb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
140       {"fmlslt_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},
141       {"fmlslt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
142       {"histcnt_z_p_zz"_h, &Simulator::Simulate_ZdT_PgZ_ZnT_ZmT},
143       {"histseg_z_zz"_h, &Simulator::Simulate_ZdB_ZnB_ZmB},
144       {"ldnt1b_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
145       {"ldnt1b_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
146       {"ldnt1d_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
147       {"ldnt1h_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
148       {"ldnt1h_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
149       {"ldnt1sb_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
150       {"ldnt1sb_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
151       {"ldnt1sh_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
152       {"ldnt1sh_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
153       {"ldnt1sw_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
154       {"ldnt1w_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
155       {"ldnt1w_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
156       {"match_p_p_zz"_h, &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},
157       {"mla_z_zzzi_d"_h, &Simulator::SimulateSVEMlaMlsIndex},
158       {"mla_z_zzzi_h"_h, &Simulator::SimulateSVEMlaMlsIndex},
159       {"mla_z_zzzi_s"_h, &Simulator::SimulateSVEMlaMlsIndex},
160       {"mls_z_zzzi_d"_h, &Simulator::SimulateSVEMlaMlsIndex},
161       {"mls_z_zzzi_h"_h, &Simulator::SimulateSVEMlaMlsIndex},
162       {"mls_z_zzzi_s"_h, &Simulator::SimulateSVEMlaMlsIndex},
163       {"mul_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
164       {"mul_z_zzi_d"_h, &Simulator::SimulateSVEMulIndex},
165       {"mul_z_zzi_h"_h, &Simulator::SimulateSVEMulIndex},
166       {"mul_z_zzi_s"_h, &Simulator::SimulateSVEMulIndex},
167       {"nbsl_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
168       {"nmatch_p_p_zz"_h, &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},
169       {"pmul_z_zz"_h, &Simulator::Simulate_ZdB_ZnB_ZmB},
170       {"pmullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
171       {"pmullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
172       {"raddhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
173       {"raddhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
174       {"rshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
175       {"rshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
176       {"rsubhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
177       {"rsubhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
178       {"saba_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnT_ZmT},
179       {"sabalb_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},
180       {"sabalt_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},
181       {"sabdlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
182       {"sabdlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
183       {"sadalp_z_p_z"_h, &Simulator::Simulate_ZdaT_PgM_ZnTb},
184       {"saddlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
185       {"saddlbt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
186       {"saddlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
187       {"saddwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
188       {"saddwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
189       {"sbclb_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},
190       {"sbclt_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},
191       {"shadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
192       {"shrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
193       {"shrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
194       {"shsub_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
195       {"shsubr_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
196       {"sli_z_zzi"_h, &Simulator::Simulate_ZdT_ZnT_const},
197       {"smaxp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
198       {"sminp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
199       {"smlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
200       {"smlalb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
201       {"smlalb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
202       {"smlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
203       {"smlalt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
204       {"smlalt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
205       {"smlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
206       {"smlslb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
207       {"smlslb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
208       {"smlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
209       {"smlslt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
210       {"smlslt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
211       {"smulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
212       {"smullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
213       {"smullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
214       {"smullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
215       {"smullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
216       {"smullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
217       {"smullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
218       {"splice_z_p_zz_con"_h, &Simulator::VisitSVEVectorSplice},
219       {"sqabs_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT},
220       {"sqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
221       {"sqcadd_z_zz"_h, &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},
222       {"sqdmlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
223       {"sqdmlalb_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
224       {"sqdmlalb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
225       {"sqdmlalbt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
226       {"sqdmlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
227       {"sqdmlalt_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
228       {"sqdmlalt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
229       {"sqdmlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
230       {"sqdmlslb_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
231       {"sqdmlslb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
232       {"sqdmlslbt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
233       {"sqdmlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
234       {"sqdmlslt_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
235       {"sqdmlslt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
236       {"sqdmulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
237       {"sqdmulh_z_zzi_d"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
238       {"sqdmulh_z_zzi_h"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
239       {"sqdmulh_z_zzi_s"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
240       {"sqdmullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
241       {"sqdmullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
242       {"sqdmullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
243       {"sqdmullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
244       {"sqdmullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
245       {"sqdmullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
246       {"sqneg_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT},
247       {"sqrdcmlah_z_zzz"_h, &Simulator::SimulateSVEComplexIntMulAdd},
248       {"sqrdcmlah_z_zzzi_h"_h, &Simulator::SimulateSVEComplexIntMulAdd},
249       {"sqrdcmlah_z_zzzi_s"_h, &Simulator::SimulateSVEComplexIntMulAdd},
250       {"sqrdmlah_z_zzz"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
251       {"sqrdmlah_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
252       {"sqrdmlah_z_zzzi_h"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
253       {"sqrdmlah_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
254       {"sqrdmlsh_z_zzz"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
255       {"sqrdmlsh_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
256       {"sqrdmlsh_z_zzzi_h"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
257       {"sqrdmlsh_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
258       {"sqrdmulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
259       {"sqrdmulh_z_zzi_d"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
260       {"sqrdmulh_z_zzi_h"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
261       {"sqrdmulh_z_zzi_s"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
262       {"sqrshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
263       {"sqrshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
264       {"sqrshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
265       {"sqrshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
266       {"sqrshrunb_z_zi"_h, &Simulator::SimulateSVENarrow},
267       {"sqrshrunt_z_zi"_h, &Simulator::SimulateSVENarrow},
268       {"sqshl_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
269       {"sqshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
270       {"sqshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
271       {"sqshlu_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
272       {"sqshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
273       {"sqshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
274       {"sqshrunb_z_zi"_h, &Simulator::SimulateSVENarrow},
275       {"sqshrunt_z_zi"_h, &Simulator::SimulateSVENarrow},
276       {"sqsub_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
277       {"sqsubr_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
278       {"sqxtnb_z_zz"_h, &Simulator::SimulateSVENarrow},
279       {"sqxtnt_z_zz"_h, &Simulator::SimulateSVENarrow},
280       {"sqxtunb_z_zz"_h, &Simulator::SimulateSVENarrow},
281       {"sqxtunt_z_zz"_h, &Simulator::SimulateSVENarrow},
282       {"srhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
283       {"sri_z_zzi"_h, &Simulator::Simulate_ZdT_ZnT_const},
284       {"srshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
285       {"srshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
286       {"srshr_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
287       {"srsra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},
288       {"sshllb_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},
289       {"sshllt_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},
290       {"ssra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},
291       {"ssublb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
292       {"ssublbt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
293       {"ssublt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
294       {"ssubltb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
295       {"ssubwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
296       {"ssubwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
297       {"stnt1b_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
298       {"stnt1b_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
299       {"stnt1d_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
300       {"stnt1h_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
301       {"stnt1h_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
302       {"stnt1w_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
303       {"stnt1w_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
304       {"subhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
305       {"subhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
306       {"suqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
307       {"tbl_z_zz_2"_h, &Simulator::VisitSVETableLookup},
308       {"tbx_z_zz"_h, &Simulator::VisitSVETableLookup},
309       {"uaba_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnT_ZmT},
310       {"uabalb_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},
311       {"uabalt_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},
312       {"uabdlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
313       {"uabdlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
314       {"uadalp_z_p_z"_h, &Simulator::Simulate_ZdaT_PgM_ZnTb},
315       {"uaddlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
316       {"uaddlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
317       {"uaddwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
318       {"uaddwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
319       {"uhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
320       {"uhsub_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
321       {"uhsubr_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
322       {"umaxp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
323       {"uminp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
324       {"umlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
325       {"umlalb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
326       {"umlalb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
327       {"umlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
328       {"umlalt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
329       {"umlalt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
330       {"umlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
331       {"umlslb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
332       {"umlslb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
333       {"umlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
334       {"umlslt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
335       {"umlslt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
336       {"umulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
337       {"umullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
338       {"umullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
339       {"umullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
340       {"umullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
341       {"umullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
342       {"umullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
343       {"uqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
344       {"uqrshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
345       {"uqrshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
346       {"uqrshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
347       {"uqrshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
348       {"uqshl_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
349       {"uqshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
350       {"uqshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
351       {"uqshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
352       {"uqshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
353       {"uqsub_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
354       {"uqsubr_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
355       {"uqxtnb_z_zz"_h, &Simulator::SimulateSVENarrow},
356       {"uqxtnt_z_zz"_h, &Simulator::SimulateSVENarrow},
357       {"urecpe_z_p_z"_h, &Simulator::Simulate_ZdS_PgM_ZnS},
358       {"urhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
359       {"urshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
360       {"urshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
361       {"urshr_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
362       {"ursqrte_z_p_z"_h, &Simulator::Simulate_ZdS_PgM_ZnS},
363       {"ursra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},
364       {"ushllb_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},
365       {"ushllt_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},
366       {"usqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
367       {"usra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},
368       {"usublb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
369       {"usublt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
370       {"usubwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
371       {"usubwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
372       {"whilege_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},
373       {"whilegt_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},
374       {"whilehi_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},
375       {"whilehs_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},
376       {"whilerw_p_rr"_h, &Simulator::Simulate_PdT_Xn_Xm},
377       {"whilewr_p_rr"_h, &Simulator::Simulate_PdT_Xn_Xm},
378       {"xar_z_zzi"_h, &Simulator::SimulateSVEExclusiveOrRotate},
379       {"smmla_z_zzz"_h, &Simulator::SimulateMatrixMul},
380       {"ummla_z_zzz"_h, &Simulator::SimulateMatrixMul},
381       {"usmmla_z_zzz"_h, &Simulator::SimulateMatrixMul},
382       {"smmla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul},
383       {"ummla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul},
384       {"usmmla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul},
385       {"fmmla_z_zzz_s"_h, &Simulator::SimulateSVEFPMatrixMul},
386       {"fmmla_z_zzz_d"_h, &Simulator::SimulateSVEFPMatrixMul},
387       {"ld1row_z_p_bi_u32"_h,
388        &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
389       {"ld1row_z_p_br_contiguous"_h,
390        &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
391       {"ld1rod_z_p_bi_u64"_h,
392        &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
393       {"ld1rod_z_p_br_contiguous"_h,
394        &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
395       {"ld1rob_z_p_bi_u8"_h,
396        &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
397       {"ld1rob_z_p_br_contiguous"_h,
398        &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
399       {"ld1roh_z_p_bi_u16"_h,
400        &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
401       {"ld1roh_z_p_br_contiguous"_h,
402        &Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
403       {"usdot_z_zzz_s"_h, &Simulator::VisitSVEIntMulAddUnpredicated},
404       {"sudot_z_zzzi_s"_h, &Simulator::VisitSVEMulIndex},
405       {"usdot_z_zzzi_s"_h, &Simulator::VisitSVEMulIndex},
406       {"usdot_asimdsame2_d"_h, &Simulator::VisitNEON3SameExtra},
407       {"sudot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},
408       {"usdot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},
409   };
410   return &form_to_visitor;
411 }
412 
Simulator(Decoder * decoder,FILE * stream,SimStack::Allocated stack)413 Simulator::Simulator(Decoder* decoder, FILE* stream, SimStack::Allocated stack)
414     : memory_(std::move(stack)),
415       last_instr_(NULL),
416       cpu_features_auditor_(decoder, CPUFeatures::All()) {
417   // Ensure that shift operations act as the simulator expects.
418   VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
419   VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
420 
421   // Set up a placeholder pipe for CanReadMemory.
422   VIXL_CHECK(pipe(placeholder_pipe_fd_) == 0);
423 
424   // Set up the decoder.
425   decoder_ = decoder;
426   decoder_->AppendVisitor(this);
427 
428   stream_ = stream;
429 
430   print_disasm_ = new PrintDisassembler(stream_);
431   // The Simulator and Disassembler share the same available list, held by the
432   // auditor. The Disassembler only annotates instructions with features that
433   // are _not_ available, so registering the auditor should have no effect
434   // unless the simulator is about to abort (due to missing features). In
435   // practice, this means that with trace enabled, the simulator will crash just
436   // after the disassembler prints the instruction, with the missing features
437   // enumerated.
438   print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);
439 
440   SetColouredTrace(false);
441   trace_parameters_ = LOG_NONE;
442 
443   // We have to configure the SVE vector register length before calling
444   // ResetState().
445   SetVectorLengthInBits(kZRegMinSize);
446 
447   ResetState();
448 
449   // Print a warning about exclusive-access instructions, but only the first
450   // time they are encountered. This warning can be silenced using
451   // SilenceExclusiveAccessWarning().
452   print_exclusive_access_warning_ = true;
453 
454   guard_pages_ = false;
455 
456   // Initialize the common state of RNDR and RNDRRS.
457   uint16_t seed[3] = {11, 22, 33};
458   VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rand_state_));
459   memcpy(rand_state_, seed, sizeof(rand_state_));
460 
461   // Initialize all bits of pseudo predicate register to true.
462   LogicPRegister ones(pregister_all_true_);
463   ones.SetAllBits();
464 }
465 
ResetSystemRegisters()466 void Simulator::ResetSystemRegisters() {
467   // Reset the system registers.
468   nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
469   fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
470   ResetFFR();
471 }
472 
ResetRegisters()473 void Simulator::ResetRegisters() {
474   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
475     WriteXRegister(i, 0xbadbeef);
476   }
477   // Returning to address 0 exits the Simulator.
478   WriteLr(kEndOfSimAddress);
479 }
480 
ResetVRegisters()481 void Simulator::ResetVRegisters() {
482   // Set SVE/FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
483   VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
484   int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
485   for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
486     VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
487     vregisters_[i].NotifyAccessAsZ();
488     for (int lane = 0; lane < lane_count; lane++) {
489       // Encode the register number and (D-sized) lane into each NaN, to
490       // make them easier to trace.
491       uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
492                           (0x0000000000000001 * lane);
493       VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
494       VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
495       vregisters_[i].Insert(lane, nan_bits);
496     }
497   }
498 }
499 
ResetPRegisters()500 void Simulator::ResetPRegisters() {
501   VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
502   int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
503   // Ensure the register configuration fits in this bit encoding.
504   VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
505   VIXL_ASSERT(lane_count <= UINT8_MAX);
506   for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
507     VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
508     for (int lane = 0; lane < lane_count; lane++) {
509       // Encode the register number and (H-sized) lane into each lane slot.
510       uint16_t bits = (0x0100 * lane) | i;
511       pregisters_[i].Insert(lane, bits);
512     }
513   }
514 }
515 
ResetFFR()516 void Simulator::ResetFFR() {
517   VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
518   int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes;
519   ffr_register_.Write(static_cast<uint16_t>(GetUintMask(default_active_lanes)));
520 }
521 
ResetState()522 void Simulator::ResetState() {
523   ResetSystemRegisters();
524   ResetRegisters();
525   ResetVRegisters();
526   ResetPRegisters();
527 
528   WriteSp(memory_.GetStack().GetBase());
529 
530   pc_ = NULL;
531   pc_modified_ = false;
532 
533   // BTI state.
534   btype_ = DefaultBType;
535   next_btype_ = DefaultBType;
536 }
537 
SetVectorLengthInBits(unsigned vector_length)538 void Simulator::SetVectorLengthInBits(unsigned vector_length) {
539   VIXL_ASSERT((vector_length >= kZRegMinSize) &&
540               (vector_length <= kZRegMaxSize));
541   VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
542   vector_length_ = vector_length;
543 
544   for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
545     vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
546   }
547   for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
548     pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
549   }
550 
551   ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes());
552 
553   ResetVRegisters();
554   ResetPRegisters();
555   ResetFFR();
556 }
557 
~Simulator()558 Simulator::~Simulator() {
559   // The decoder may outlive the simulator.
560   decoder_->RemoveVisitor(print_disasm_);
561   delete print_disasm_;
562   close(placeholder_pipe_fd_[0]);
563   close(placeholder_pipe_fd_[1]);
564 }
565 
566 
Run()567 void Simulator::Run() {
568   // Flush any written registers before executing anything, so that
569   // manually-set registers are logged _before_ the first instruction.
570   LogAllWrittenRegisters();
571 
572   while (pc_ != kEndOfSimAddress) {
573     ExecuteInstruction();
574   }
575 }
576 
577 
RunFrom(const Instruction * first)578 void Simulator::RunFrom(const Instruction* first) {
579   WritePc(first, NoBranchLog);
580   Run();
581 }
582 
583 
584 // clang-format off
585 const char* Simulator::xreg_names[] = {"x0",  "x1",  "x2",  "x3",  "x4",  "x5",
586                                        "x6",  "x7",  "x8",  "x9",  "x10", "x11",
587                                        "x12", "x13", "x14", "x15", "x16", "x17",
588                                        "x18", "x19", "x20", "x21", "x22", "x23",
589                                        "x24", "x25", "x26", "x27", "x28", "x29",
590                                        "lr",  "xzr", "sp"};
591 
592 const char* Simulator::wreg_names[] = {"w0",  "w1",  "w2",  "w3",  "w4",  "w5",
593                                        "w6",  "w7",  "w8",  "w9",  "w10", "w11",
594                                        "w12", "w13", "w14", "w15", "w16", "w17",
595                                        "w18", "w19", "w20", "w21", "w22", "w23",
596                                        "w24", "w25", "w26", "w27", "w28", "w29",
597                                        "w30", "wzr", "wsp"};
598 
599 const char* Simulator::breg_names[] = {"b0",  "b1",  "b2",  "b3",  "b4",  "b5",
600                                        "b6",  "b7",  "b8",  "b9",  "b10", "b11",
601                                        "b12", "b13", "b14", "b15", "b16", "b17",
602                                        "b18", "b19", "b20", "b21", "b22", "b23",
603                                        "b24", "b25", "b26", "b27", "b28", "b29",
604                                        "b30", "b31"};
605 
606 const char* Simulator::hreg_names[] = {"h0",  "h1",  "h2",  "h3",  "h4",  "h5",
607                                        "h6",  "h7",  "h8",  "h9",  "h10", "h11",
608                                        "h12", "h13", "h14", "h15", "h16", "h17",
609                                        "h18", "h19", "h20", "h21", "h22", "h23",
610                                        "h24", "h25", "h26", "h27", "h28", "h29",
611                                        "h30", "h31"};
612 
613 const char* Simulator::sreg_names[] = {"s0",  "s1",  "s2",  "s3",  "s4",  "s5",
614                                        "s6",  "s7",  "s8",  "s9",  "s10", "s11",
615                                        "s12", "s13", "s14", "s15", "s16", "s17",
616                                        "s18", "s19", "s20", "s21", "s22", "s23",
617                                        "s24", "s25", "s26", "s27", "s28", "s29",
618                                        "s30", "s31"};
619 
620 const char* Simulator::dreg_names[] = {"d0",  "d1",  "d2",  "d3",  "d4",  "d5",
621                                        "d6",  "d7",  "d8",  "d9",  "d10", "d11",
622                                        "d12", "d13", "d14", "d15", "d16", "d17",
623                                        "d18", "d19", "d20", "d21", "d22", "d23",
624                                        "d24", "d25", "d26", "d27", "d28", "d29",
625                                        "d30", "d31"};
626 
627 const char* Simulator::vreg_names[] = {"v0",  "v1",  "v2",  "v3",  "v4",  "v5",
628                                        "v6",  "v7",  "v8",  "v9",  "v10", "v11",
629                                        "v12", "v13", "v14", "v15", "v16", "v17",
630                                        "v18", "v19", "v20", "v21", "v22", "v23",
631                                        "v24", "v25", "v26", "v27", "v28", "v29",
632                                        "v30", "v31"};
633 
634 const char* Simulator::zreg_names[] = {"z0",  "z1",  "z2",  "z3",  "z4",  "z5",
635                                        "z6",  "z7",  "z8",  "z9",  "z10", "z11",
636                                        "z12", "z13", "z14", "z15", "z16", "z17",
637                                        "z18", "z19", "z20", "z21", "z22", "z23",
638                                        "z24", "z25", "z26", "z27", "z28", "z29",
639                                        "z30", "z31"};
640 
641 const char* Simulator::preg_names[] = {"p0",  "p1",  "p2",  "p3",  "p4",  "p5",
642                                        "p6",  "p7",  "p8",  "p9",  "p10", "p11",
643                                        "p12", "p13", "p14", "p15"};
644 // clang-format on
645 
646 
WRegNameForCode(unsigned code,Reg31Mode mode)647 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
648   // If the code represents the stack pointer, index the name after zr.
649   if ((code == kSPRegInternalCode) ||
650       ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
651     code = kZeroRegCode + 1;
652   }
653   VIXL_ASSERT(code < ArrayLength(wreg_names));
654   return wreg_names[code];
655 }
656 
657 
XRegNameForCode(unsigned code,Reg31Mode mode)658 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
659   // If the code represents the stack pointer, index the name after zr.
660   if ((code == kSPRegInternalCode) ||
661       ((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
662     code = kZeroRegCode + 1;
663   }
664   VIXL_ASSERT(code < ArrayLength(xreg_names));
665   return xreg_names[code];
666 }
667 
668 
BRegNameForCode(unsigned code)669 const char* Simulator::BRegNameForCode(unsigned code) {
670   VIXL_ASSERT(code < kNumberOfVRegisters);
671   return breg_names[code];
672 }
673 
674 
HRegNameForCode(unsigned code)675 const char* Simulator::HRegNameForCode(unsigned code) {
676   VIXL_ASSERT(code < kNumberOfVRegisters);
677   return hreg_names[code];
678 }
679 
680 
SRegNameForCode(unsigned code)681 const char* Simulator::SRegNameForCode(unsigned code) {
682   VIXL_ASSERT(code < kNumberOfVRegisters);
683   return sreg_names[code];
684 }
685 
686 
DRegNameForCode(unsigned code)687 const char* Simulator::DRegNameForCode(unsigned code) {
688   VIXL_ASSERT(code < kNumberOfVRegisters);
689   return dreg_names[code];
690 }
691 
692 
VRegNameForCode(unsigned code)693 const char* Simulator::VRegNameForCode(unsigned code) {
694   VIXL_ASSERT(code < kNumberOfVRegisters);
695   return vreg_names[code];
696 }
697 
698 
ZRegNameForCode(unsigned code)699 const char* Simulator::ZRegNameForCode(unsigned code) {
700   VIXL_ASSERT(code < kNumberOfZRegisters);
701   return zreg_names[code];
702 }
703 
704 
PRegNameForCode(unsigned code)705 const char* Simulator::PRegNameForCode(unsigned code) {
706   VIXL_ASSERT(code < kNumberOfPRegisters);
707   return preg_names[code];
708 }
709 
ExpandToSimVRegister(const SimPRegister & pg)710 SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) {
711   SimVRegister ones, result;
712   dup_immediate(kFormatVnB, ones, 0xff);
713   mov_zeroing(kFormatVnB, result, pg, ones);
714   return result;
715 }
716 
ExtractFromSimVRegister(VectorFormat vform,SimPRegister & pd,SimVRegister vreg)717 void Simulator::ExtractFromSimVRegister(VectorFormat vform,
718                                         SimPRegister& pd,
719                                         SimVRegister vreg) {
720   SimVRegister zero;
721   dup_immediate(kFormatVnB, zero, 0);
722   SVEIntCompareVectorsHelper(ne,
723                              vform,
724                              pd,
725                              GetPTrue(),
726                              vreg,
727                              zero,
728                              false,
729                              LeaveFlags);
730 }
731 
732 #define COLOUR(colour_code) "\033[0;" colour_code "m"
733 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
734 #define COLOUR_HIGHLIGHT "\033[43m"
735 #define NORMAL ""
736 #define GREY "30"
737 #define RED "31"
738 #define GREEN "32"
739 #define YELLOW "33"
740 #define BLUE "34"
741 #define MAGENTA "35"
742 #define CYAN "36"
743 #define WHITE "37"
SetColouredTrace(bool value)744 void Simulator::SetColouredTrace(bool value) {
745   coloured_trace_ = value;
746 
747   clr_normal = value ? COLOUR(NORMAL) : "";
748   clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
749   clr_flag_value = value ? COLOUR(NORMAL) : "";
750   clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
751   clr_reg_value = value ? COLOUR(CYAN) : "";
752   clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
753   clr_vreg_value = value ? COLOUR(MAGENTA) : "";
754   clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";
755   clr_preg_value = value ? COLOUR(GREEN) : "";
756   clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
757   clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
758   clr_warning_message = value ? COLOUR(YELLOW) : "";
759   clr_printf = value ? COLOUR(GREEN) : "";
760   clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
761 
762   if (value) {
763     print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
764     print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
765   } else {
766     print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
767     print_disasm_->SetCPUFeaturesSuffix("");
768   }
769 }
770 
771 
SetTraceParameters(int parameters)772 void Simulator::SetTraceParameters(int parameters) {
773   bool disasm_before = trace_parameters_ & LOG_DISASM;
774   trace_parameters_ = parameters;
775   bool disasm_after = trace_parameters_ & LOG_DISASM;
776 
777   if (disasm_before != disasm_after) {
778     if (disasm_after) {
779       decoder_->InsertVisitorBefore(print_disasm_, this);
780     } else {
781       decoder_->RemoveVisitor(print_disasm_);
782     }
783   }
784 }
785 
786 // Helpers ---------------------------------------------------------------------
AddWithCarry(unsigned reg_size,bool set_flags,uint64_t left,uint64_t right,int carry_in)787 uint64_t Simulator::AddWithCarry(unsigned reg_size,
788                                  bool set_flags,
789                                  uint64_t left,
790                                  uint64_t right,
791                                  int carry_in) {
792   std::pair<uint64_t, uint8_t> result_and_flags =
793       AddWithCarry(reg_size, left, right, carry_in);
794   if (set_flags) {
795     uint8_t flags = result_and_flags.second;
796     ReadNzcv().SetN((flags >> 3) & 1);
797     ReadNzcv().SetZ((flags >> 2) & 1);
798     ReadNzcv().SetC((flags >> 1) & 1);
799     ReadNzcv().SetV((flags >> 0) & 1);
800     LogSystemRegister(NZCV);
801   }
802   return result_and_flags.first;
803 }
804 
AddWithCarry(unsigned reg_size,uint64_t left,uint64_t right,int carry_in)805 std::pair<uint64_t, uint8_t> Simulator::AddWithCarry(unsigned reg_size,
806                                                      uint64_t left,
807                                                      uint64_t right,
808                                                      int carry_in) {
809   VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
810   VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
811 
812   uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
813   uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
814   uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
815 
816   left &= reg_mask;
817   right &= reg_mask;
818   uint64_t result = (left + right + carry_in) & reg_mask;
819 
820   // NZCV bits, ordered N in bit 3 to V in bit 0.
821   uint8_t nzcv = CalcNFlag(result, reg_size) ? 8 : 0;
822   nzcv |= CalcZFlag(result) ? 4 : 0;
823 
824   // Compute the C flag by comparing the result to the max unsigned integer.
825   uint64_t max_uint_2op = max_uint - carry_in;
826   bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
827   nzcv |= C ? 2 : 0;
828 
829   // Overflow iff the sign bit is the same for the two inputs and different
830   // for the result.
831   uint64_t left_sign = left & sign_mask;
832   uint64_t right_sign = right & sign_mask;
833   uint64_t result_sign = result & sign_mask;
834   bool V = (left_sign == right_sign) && (left_sign != result_sign);
835   nzcv |= V ? 1 : 0;
836 
837   return std::make_pair(result, nzcv);
838 }
839 
840 using vixl_uint128_t = std::pair<uint64_t, uint64_t>;
841 
Add128(vixl_uint128_t x,vixl_uint128_t y)842 vixl_uint128_t Simulator::Add128(vixl_uint128_t x, vixl_uint128_t y) {
843   std::pair<uint64_t, uint8_t> sum_lo =
844       AddWithCarry(kXRegSize, x.second, y.second, 0);
845   int carry_in = (sum_lo.second & 0x2) >> 1;  // C flag in NZCV result.
846   std::pair<uint64_t, uint8_t> sum_hi =
847       AddWithCarry(kXRegSize, x.first, y.first, carry_in);
848   return std::make_pair(sum_hi.first, sum_lo.first);
849 }
850 
Neg128(vixl_uint128_t x)851 vixl_uint128_t Simulator::Neg128(vixl_uint128_t x) {
852   // Negate the integer value. Throw an assertion when the input is INT128_MIN.
853   VIXL_ASSERT((x.first != GetSignMask(64)) || (x.second != 0));
854   x.first = ~x.first;
855   x.second = ~x.second;
856   return Add128(x, {0, 1});
857 }
858 
Mul64(uint64_t x,uint64_t y)859 vixl_uint128_t Simulator::Mul64(uint64_t x, uint64_t y) {
860   bool neg_result = false;
861   if ((x >> 63) == 1) {
862     x = -x;
863     neg_result = !neg_result;
864   }
865   if ((y >> 63) == 1) {
866     y = -y;
867     neg_result = !neg_result;
868   }
869 
870   uint64_t x_lo = x & 0xffffffff;
871   uint64_t x_hi = x >> 32;
872   uint64_t y_lo = y & 0xffffffff;
873   uint64_t y_hi = y >> 32;
874 
875   uint64_t t1 = x_lo * y_hi;
876   uint64_t t2 = x_hi * y_lo;
877   vixl_uint128_t a = std::make_pair(0, x_lo * y_lo);
878   vixl_uint128_t b = std::make_pair(t1 >> 32, t1 << 32);
879   vixl_uint128_t c = std::make_pair(t2 >> 32, t2 << 32);
880   vixl_uint128_t d = std::make_pair(x_hi * y_hi, 0);
881 
882   vixl_uint128_t result = Add128(a, b);
883   result = Add128(result, c);
884   result = Add128(result, d);
885   return neg_result ? std::make_pair(-result.first - 1, -result.second)
886                     : result;
887 }
888 
ShiftOperand(unsigned reg_size,uint64_t uvalue,Shift shift_type,unsigned amount) const889 int64_t Simulator::ShiftOperand(unsigned reg_size,
890                                 uint64_t uvalue,
891                                 Shift shift_type,
892                                 unsigned amount) const {
893   VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
894               (reg_size == kSRegSize) || (reg_size == kDRegSize));
895   if (amount > 0) {
896     uint64_t mask = GetUintMask(reg_size);
897     bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
898     // The behavior is undefined in c++ if the shift amount greater than or
899     // equal to the register lane size. Work out the shifted result based on
900     // architectural behavior before performing the c++ type shfit operations.
901     switch (shift_type) {
902       case LSL:
903         if (amount >= reg_size) {
904           return UINT64_C(0);
905         }
906         uvalue <<= amount;
907         break;
908       case LSR:
909         if (amount >= reg_size) {
910           return UINT64_C(0);
911         }
912         uvalue >>= amount;
913         break;
914       case ASR:
915         if (amount >= reg_size) {
916           return is_negative ? ~UINT64_C(0) : UINT64_C(0);
917         }
918         uvalue >>= amount;
919         if (is_negative) {
920           // Simulate sign-extension to 64 bits.
921           uvalue |= ~UINT64_C(0) << (reg_size - amount);
922         }
923         break;
924       case ROR: {
925         uvalue = RotateRight(uvalue, amount, reg_size);
926         break;
927       }
928       default:
929         VIXL_UNIMPLEMENTED();
930         return 0;
931     }
932     uvalue &= mask;
933   }
934 
935   int64_t result;
936   memcpy(&result, &uvalue, sizeof(result));
937   return result;
938 }
939 
940 
ExtendValue(unsigned reg_size,int64_t value,Extend extend_type,unsigned left_shift) const941 int64_t Simulator::ExtendValue(unsigned reg_size,
942                                int64_t value,
943                                Extend extend_type,
944                                unsigned left_shift) const {
945   switch (extend_type) {
946     case UXTB:
947       value &= kByteMask;
948       break;
949     case UXTH:
950       value &= kHalfWordMask;
951       break;
952     case UXTW:
953       value &= kWordMask;
954       break;
955     case SXTB:
956       value &= kByteMask;
957       if ((value & 0x80) != 0) {
958         value |= ~UINT64_C(0) << 8;
959       }
960       break;
961     case SXTH:
962       value &= kHalfWordMask;
963       if ((value & 0x8000) != 0) {
964         value |= ~UINT64_C(0) << 16;
965       }
966       break;
967     case SXTW:
968       value &= kWordMask;
969       if ((value & 0x80000000) != 0) {
970         value |= ~UINT64_C(0) << 32;
971       }
972       break;
973     case UXTX:
974     case SXTX:
975       break;
976     default:
977       VIXL_UNREACHABLE();
978   }
979   return ShiftOperand(reg_size, value, LSL, left_shift);
980 }
981 
982 
FPCompare(double val0,double val1,FPTrapFlags trap)983 void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
984   AssertSupportedFPCR();
985 
986   // TODO: This assumes that the C++ implementation handles comparisons in the
987   // way that we expect (as per AssertSupportedFPCR()).
988   bool process_exception = false;
989   if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
990     ReadNzcv().SetRawValue(FPUnorderedFlag);
991     if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
992         (trap == EnableTrap)) {
993       process_exception = true;
994     }
995   } else if (val0 < val1) {
996     ReadNzcv().SetRawValue(FPLessThanFlag);
997   } else if (val0 > val1) {
998     ReadNzcv().SetRawValue(FPGreaterThanFlag);
999   } else if (val0 == val1) {
1000     ReadNzcv().SetRawValue(FPEqualFlag);
1001   } else {
1002     VIXL_UNREACHABLE();
1003   }
1004   LogSystemRegister(NZCV);
1005   if (process_exception) FPProcessException();
1006 }
1007 
1008 
ComputeMemOperandAddress(const MemOperand & mem_op) const1009 uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
1010   VIXL_ASSERT(mem_op.IsValid());
1011   int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
1012   if (mem_op.IsImmediateOffset()) {
1013     return base + mem_op.GetOffset();
1014   } else {
1015     VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
1016     int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
1017     unsigned shift_amount = mem_op.GetShiftAmount();
1018     if (mem_op.GetShift() != NO_SHIFT) {
1019       offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
1020     }
1021     if (mem_op.GetExtend() != NO_EXTEND) {
1022       offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
1023     }
1024     return static_cast<uint64_t>(base + offset);
1025   }
1026 }
1027 
1028 
GetPrintRegisterFormatForSize(unsigned reg_size,unsigned lane_size)1029 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
1030     unsigned reg_size, unsigned lane_size) {
1031   VIXL_ASSERT(reg_size >= lane_size);
1032 
1033   uint32_t format = 0;
1034   if (reg_size != lane_size) {
1035     switch (reg_size) {
1036       default:
1037         VIXL_UNREACHABLE();
1038         break;
1039       case kQRegSizeInBytes:
1040         format = kPrintRegAsQVector;
1041         break;
1042       case kDRegSizeInBytes:
1043         format = kPrintRegAsDVector;
1044         break;
1045     }
1046   }
1047 
1048   switch (lane_size) {
1049     default:
1050       VIXL_UNREACHABLE();
1051       break;
1052     case kQRegSizeInBytes:
1053       format |= kPrintReg1Q;
1054       break;
1055     case kDRegSizeInBytes:
1056       format |= kPrintReg1D;
1057       break;
1058     case kSRegSizeInBytes:
1059       format |= kPrintReg1S;
1060       break;
1061     case kHRegSizeInBytes:
1062       format |= kPrintReg1H;
1063       break;
1064     case kBRegSizeInBytes:
1065       format |= kPrintReg1B;
1066       break;
1067   }
1068   // These sizes would be duplicate case labels.
1069   VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
1070   VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
1071   VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
1072   VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
1073 
1074   return static_cast<PrintRegisterFormat>(format);
1075 }
1076 
1077 
GetPrintRegisterFormat(VectorFormat vform)1078 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
1079     VectorFormat vform) {
1080   switch (vform) {
1081     default:
1082       VIXL_UNREACHABLE();
1083       return kPrintReg16B;
1084     case kFormat16B:
1085       return kPrintReg16B;
1086     case kFormat8B:
1087       return kPrintReg8B;
1088     case kFormat8H:
1089       return kPrintReg8H;
1090     case kFormat4H:
1091       return kPrintReg4H;
1092     case kFormat4S:
1093       return kPrintReg4S;
1094     case kFormat2S:
1095       return kPrintReg2S;
1096     case kFormat2D:
1097       return kPrintReg2D;
1098     case kFormat1D:
1099       return kPrintReg1D;
1100 
1101     case kFormatB:
1102       return kPrintReg1B;
1103     case kFormatH:
1104       return kPrintReg1H;
1105     case kFormatS:
1106       return kPrintReg1S;
1107     case kFormatD:
1108       return kPrintReg1D;
1109 
1110     case kFormatVnB:
1111       return kPrintRegVnB;
1112     case kFormatVnH:
1113       return kPrintRegVnH;
1114     case kFormatVnS:
1115       return kPrintRegVnS;
1116     case kFormatVnD:
1117       return kPrintRegVnD;
1118   }
1119 }
1120 
1121 
GetPrintRegisterFormatFP(VectorFormat vform)1122 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
1123     VectorFormat vform) {
1124   switch (vform) {
1125     default:
1126       VIXL_UNREACHABLE();
1127       return kPrintReg16B;
1128     case kFormat8H:
1129       return kPrintReg8HFP;
1130     case kFormat4H:
1131       return kPrintReg4HFP;
1132     case kFormat4S:
1133       return kPrintReg4SFP;
1134     case kFormat2S:
1135       return kPrintReg2SFP;
1136     case kFormat2D:
1137       return kPrintReg2DFP;
1138     case kFormat1D:
1139       return kPrintReg1DFP;
1140     case kFormatH:
1141       return kPrintReg1HFP;
1142     case kFormatS:
1143       return kPrintReg1SFP;
1144     case kFormatD:
1145       return kPrintReg1DFP;
1146   }
1147 }
1148 
PrintRegisters()1149 void Simulator::PrintRegisters() {
1150   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1151     if (i == kSpRegCode) i = kSPRegInternalCode;
1152     PrintRegister(i);
1153   }
1154 }
1155 
PrintVRegisters()1156 void Simulator::PrintVRegisters() {
1157   for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1158     PrintVRegister(i);
1159   }
1160 }
1161 
PrintZRegisters()1162 void Simulator::PrintZRegisters() {
1163   for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
1164     PrintZRegister(i);
1165   }
1166 }
1167 
PrintWrittenRegisters()1168 void Simulator::PrintWrittenRegisters() {
1169   for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1170     if (registers_[i].WrittenSinceLastLog()) {
1171       if (i == kSpRegCode) i = kSPRegInternalCode;
1172       PrintRegister(i);
1173     }
1174   }
1175 }
1176 
PrintWrittenVRegisters()1177 void Simulator::PrintWrittenVRegisters() {
1178   bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
1179   for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1180     if (vregisters_[i].WrittenSinceLastLog()) {
1181       // Z registers are initialised in the constructor before the user can
1182       // configure the CPU features, so we must also check for SVE here.
1183       if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
1184         PrintZRegister(i);
1185       } else {
1186         PrintVRegister(i);
1187       }
1188     }
1189   }
1190 }
1191 
PrintWrittenPRegisters()1192 void Simulator::PrintWrittenPRegisters() {
1193   // P registers are initialised in the constructor before the user can
1194   // configure the CPU features, so we must check for SVE here.
1195   if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
1196   for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
1197     if (pregisters_[i].WrittenSinceLastLog()) {
1198       PrintPRegister(i);
1199     }
1200   }
1201   if (ReadFFR().WrittenSinceLastLog()) PrintFFR();
1202 }
1203 
PrintSystemRegisters()1204 void Simulator::PrintSystemRegisters() {
1205   PrintSystemRegister(NZCV);
1206   PrintSystemRegister(FPCR);
1207 }
1208 
PrintRegisterValue(const uint8_t * value,int value_size,PrintRegisterFormat format)1209 void Simulator::PrintRegisterValue(const uint8_t* value,
1210                                    int value_size,
1211                                    PrintRegisterFormat format) {
1212   int print_width = GetPrintRegSizeInBytes(format);
1213   VIXL_ASSERT(print_width <= value_size);
1214   for (int i = value_size - 1; i >= print_width; i--) {
1215     // Pad with spaces so that values align vertically.
1216     fprintf(stream_, "  ");
1217     // If we aren't explicitly printing a partial value, ensure that the
1218     // unprinted bits are zero.
1219     VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));
1220   }
1221   fprintf(stream_, "0x");
1222   for (int i = print_width - 1; i >= 0; i--) {
1223     fprintf(stream_, "%02x", value[i]);
1224   }
1225 }
1226 
PrintRegisterValueFPAnnotations(const uint8_t * value,uint16_t lane_mask,PrintRegisterFormat format)1227 void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,
1228                                                 uint16_t lane_mask,
1229                                                 PrintRegisterFormat format) {
1230   VIXL_ASSERT((format & kPrintRegAsFP) != 0);
1231   int lane_size = GetPrintRegLaneSizeInBytes(format);
1232   fprintf(stream_, " (");
1233   bool last_inactive = false;
1234   const char* sep = "";
1235   for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {
1236     bool access = (lane_mask & (1 << (i * lane_size))) != 0;
1237     if (access) {
1238       // Read the lane as a double, so we can format all FP types in the same
1239       // way. We squash NaNs, and a double can exactly represent any other value
1240       // that the smaller types can represent, so this is lossless.
1241       double element;
1242       switch (lane_size) {
1243         case kHRegSizeInBytes: {
1244           Float16 element_fp16;
1245           VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);
1246           memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));
1247           element = FPToDouble(element_fp16, kUseDefaultNaN);
1248           break;
1249         }
1250         case kSRegSizeInBytes: {
1251           float element_fp32;
1252           memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));
1253           element = static_cast<double>(element_fp32);
1254           break;
1255         }
1256         case kDRegSizeInBytes: {
1257           memcpy(&element, &value[i * lane_size], sizeof(element));
1258           break;
1259         }
1260         default:
1261           VIXL_UNREACHABLE();
1262           fprintf(stream_, "{UnknownFPValue}");
1263           continue;
1264       }
1265       if (IsNaN(element)) {
1266         // The fprintf behaviour for NaNs is implementation-defined. Always
1267         // print "nan", so that traces are consistent.
1268         fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);
1269       } else {
1270         fprintf(stream_,
1271                 "%s%s%#.4g%s",
1272                 sep,
1273                 clr_vreg_value,
1274                 element,
1275                 clr_normal);
1276       }
1277       last_inactive = false;
1278     } else if (!last_inactive) {
1279       // Replace each contiguous sequence of inactive lanes with "...".
1280       fprintf(stream_, "%s...", sep);
1281       last_inactive = true;
1282     }
1283   }
1284   fprintf(stream_, ")");
1285 }
1286 
PrintRegister(int code,PrintRegisterFormat format,const char * suffix)1287 void Simulator::PrintRegister(int code,
1288                               PrintRegisterFormat format,
1289                               const char* suffix) {
1290   VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||
1291               (static_cast<unsigned>(code) == kSPRegInternalCode));
1292   VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);
1293   VIXL_ASSERT((format & kPrintRegAsFP) == 0);
1294 
1295   SimRegister* reg;
1296   SimRegister zero;
1297   if (code == kZeroRegCode) {
1298     reg = &zero;
1299   } else {
1300     // registers_[31] holds the SP.
1301     VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
1302     reg = &registers_[code % kNumberOfRegisters];
1303   }
1304 
1305   // We trace register writes as whole register values, implying that any
1306   // unprinted bits are all zero:
1307   //   "#       x{code}: 0x{-----value----}"
1308   //   "#       w{code}:         0x{-value}"
1309   // Stores trace partial register values, implying nothing about the unprinted
1310   // bits:
1311   //   "# x{code}<63:0>: 0x{-----value----}"
1312   //   "# x{code}<31:0>:         0x{-value}"
1313   //   "# x{code}<15:0>:             0x{--}"
1314   //   "#  x{code}<7:0>:               0x{}"
1315 
1316   bool is_partial = (format & kPrintRegPartial) != 0;
1317   unsigned print_reg_size = GetPrintRegSizeInBits(format);
1318   std::stringstream name;
1319   if (is_partial) {
1320     name << XRegNameForCode(code) << GetPartialRegSuffix(format);
1321   } else {
1322     // Notify the register that it has been logged, but only if we're printing
1323     // all of it.
1324     reg->NotifyRegisterLogged();
1325     switch (print_reg_size) {
1326       case kWRegSize:
1327         name << WRegNameForCode(code);
1328         break;
1329       case kXRegSize:
1330         name << XRegNameForCode(code);
1331         break;
1332       default:
1333         VIXL_UNREACHABLE();
1334         return;
1335     }
1336   }
1337 
1338   fprintf(stream_,
1339           "# %s%*s: %s",
1340           clr_reg_name,
1341           kPrintRegisterNameFieldWidth,
1342           name.str().c_str(),
1343           clr_reg_value);
1344   PrintRegisterValue(*reg, format);
1345   fprintf(stream_, "%s%s", clr_normal, suffix);
1346 }
1347 
PrintVRegister(int code,PrintRegisterFormat format,const char * suffix)1348 void Simulator::PrintVRegister(int code,
1349                                PrintRegisterFormat format,
1350                                const char* suffix) {
1351   VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);
1352   VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||
1353               ((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||
1354               ((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));
1355 
1356   // We trace register writes as whole register values, implying that any
1357   // unprinted bits are all zero:
1358   //   "#        v{code}: 0x{-------------value------------}"
1359   //   "#        d{code}:                 0x{-----value----}"
1360   //   "#        s{code}:                         0x{-value}"
1361   //   "#        h{code}:                             0x{--}"
1362   //   "#        b{code}:                               0x{}"
1363   // Stores trace partial register values, implying nothing about the unprinted
1364   // bits:
1365   //   "# v{code}<127:0>: 0x{-------------value------------}"
1366   //   "#  v{code}<63:0>:                 0x{-----value----}"
1367   //   "#  v{code}<31:0>:                         0x{-value}"
1368   //   "#  v{code}<15:0>:                             0x{--}"
1369   //   "#   v{code}<7:0>:                               0x{}"
1370 
1371   bool is_partial = ((format & kPrintRegPartial) != 0);
1372   std::stringstream name;
1373   unsigned print_reg_size = GetPrintRegSizeInBits(format);
1374   if (is_partial) {
1375     name << VRegNameForCode(code) << GetPartialRegSuffix(format);
1376   } else {
1377     // Notify the register that it has been logged, but only if we're printing
1378     // all of it.
1379     vregisters_[code].NotifyRegisterLogged();
1380     switch (print_reg_size) {
1381       case kBRegSize:
1382         name << BRegNameForCode(code);
1383         break;
1384       case kHRegSize:
1385         name << HRegNameForCode(code);
1386         break;
1387       case kSRegSize:
1388         name << SRegNameForCode(code);
1389         break;
1390       case kDRegSize:
1391         name << DRegNameForCode(code);
1392         break;
1393       case kQRegSize:
1394         name << VRegNameForCode(code);
1395         break;
1396       default:
1397         VIXL_UNREACHABLE();
1398         return;
1399     }
1400   }
1401 
1402   fprintf(stream_,
1403           "# %s%*s: %s",
1404           clr_vreg_name,
1405           kPrintRegisterNameFieldWidth,
1406           name.str().c_str(),
1407           clr_vreg_value);
1408   PrintRegisterValue(vregisters_[code], format);
1409   fprintf(stream_, "%s", clr_normal);
1410   if ((format & kPrintRegAsFP) != 0) {
1411     PrintRegisterValueFPAnnotations(vregisters_[code], format);
1412   }
1413   fprintf(stream_, "%s", suffix);
1414 }
1415 
PrintVRegistersForStructuredAccess(int rt_code,int reg_count,uint16_t focus_mask,PrintRegisterFormat format)1416 void Simulator::PrintVRegistersForStructuredAccess(int rt_code,
1417                                                    int reg_count,
1418                                                    uint16_t focus_mask,
1419                                                    PrintRegisterFormat format) {
1420   bool print_fp = (format & kPrintRegAsFP) != 0;
1421   // Suppress FP formatting, so we can specify the lanes we're interested in.
1422   PrintRegisterFormat format_no_fp =
1423       static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1424 
1425   for (int r = 0; r < reg_count; r++) {
1426     int code = (rt_code + r) % kNumberOfVRegisters;
1427     PrintVRegister(code, format_no_fp, "");
1428     if (print_fp) {
1429       PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);
1430     }
1431     fprintf(stream_, "\n");
1432   }
1433 }
1434 
PrintZRegistersForStructuredAccess(int rt_code,int q_index,int reg_count,uint16_t focus_mask,PrintRegisterFormat format)1435 void Simulator::PrintZRegistersForStructuredAccess(int rt_code,
1436                                                    int q_index,
1437                                                    int reg_count,
1438                                                    uint16_t focus_mask,
1439                                                    PrintRegisterFormat format) {
1440   bool print_fp = (format & kPrintRegAsFP) != 0;
1441   // Suppress FP formatting, so we can specify the lanes we're interested in.
1442   PrintRegisterFormat format_no_fp =
1443       static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1444 
1445   PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);
1446 
1447   const unsigned size = kQRegSizeInBytes;
1448   unsigned byte_index = q_index * size;
1449   const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;
1450   VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());
1451 
1452   for (int r = 0; r < reg_count; r++) {
1453     int code = (rt_code + r) % kNumberOfZRegisters;
1454     PrintPartialZRegister(code, q_index, format_no_fp, "");
1455     if (print_fp) {
1456       PrintRegisterValueFPAnnotations(value, focus_mask, format_q);
1457     }
1458     fprintf(stream_, "\n");
1459   }
1460 }
1461 
PrintZRegister(int code,PrintRegisterFormat format)1462 void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {
1463   // We're going to print the register in parts, so force a partial format.
1464   format = GetPrintRegPartial(format);
1465   VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1466   int vl = GetVectorLengthInBits();
1467   VIXL_ASSERT((vl % kQRegSize) == 0);
1468   for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1469     PrintPartialZRegister(code, i, format);
1470   }
1471   vregisters_[code].NotifyRegisterLogged();
1472 }
1473 
PrintPRegister(int code,PrintRegisterFormat format)1474 void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {
1475   // We're going to print the register in parts, so force a partial format.
1476   format = GetPrintRegPartial(format);
1477   VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1478   int vl = GetVectorLengthInBits();
1479   VIXL_ASSERT((vl % kQRegSize) == 0);
1480   for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1481     PrintPartialPRegister(code, i, format);
1482   }
1483   pregisters_[code].NotifyRegisterLogged();
1484 }
1485 
PrintFFR(PrintRegisterFormat format)1486 void Simulator::PrintFFR(PrintRegisterFormat format) {
1487   // We're going to print the register in parts, so force a partial format.
1488   format = GetPrintRegPartial(format);
1489   VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1490   int vl = GetVectorLengthInBits();
1491   VIXL_ASSERT((vl % kQRegSize) == 0);
1492   SimPRegister& ffr = ReadFFR();
1493   for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1494     PrintPartialPRegister("FFR", ffr, i, format);
1495   }
1496   ffr.NotifyRegisterLogged();
1497 }
1498 
PrintPartialZRegister(int code,int q_index,PrintRegisterFormat format,const char * suffix)1499 void Simulator::PrintPartialZRegister(int code,
1500                                       int q_index,
1501                                       PrintRegisterFormat format,
1502                                       const char* suffix) {
1503   VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);
1504   VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1505   VIXL_ASSERT((format & kPrintRegPartial) != 0);
1506   VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1507 
1508   // We _only_ trace partial Z register values in Q-sized chunks, because
1509   // they're often too large to reasonably fit on a single line. Each line
1510   // implies nothing about the unprinted bits.
1511   //   "# z{code}<127:0>: 0x{-------------value------------}"
1512 
1513   format = GetPrintRegAsQChunkOfSVE(format);
1514 
1515   const unsigned size = kQRegSizeInBytes;
1516   unsigned byte_index = q_index * size;
1517   const uint8_t* value = vregisters_[code].GetBytes() + byte_index;
1518   VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());
1519 
1520   int lsb = q_index * kQRegSize;
1521   int msb = lsb + kQRegSize - 1;
1522   std::stringstream name;
1523   name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
1524 
1525   fprintf(stream_,
1526           "# %s%*s: %s",
1527           clr_vreg_name,
1528           kPrintRegisterNameFieldWidth,
1529           name.str().c_str(),
1530           clr_vreg_value);
1531   PrintRegisterValue(value, size, format);
1532   fprintf(stream_, "%s", clr_normal);
1533   if ((format & kPrintRegAsFP) != 0) {
1534     PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);
1535   }
1536   fprintf(stream_, "%s", suffix);
1537 }
1538 
PrintPartialPRegister(const char * name,const SimPRegister & reg,int q_index,PrintRegisterFormat format,const char * suffix)1539 void Simulator::PrintPartialPRegister(const char* name,
1540                                       const SimPRegister& reg,
1541                                       int q_index,
1542                                       PrintRegisterFormat format,
1543                                       const char* suffix) {
1544   VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1545   VIXL_ASSERT((format & kPrintRegPartial) != 0);
1546   VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1547 
1548   // We don't currently use the format for anything here.
1549   USE(format);
1550 
1551   // We _only_ trace partial P register values, because they're often too large
1552   // to reasonably fit on a single line. Each line implies nothing about the
1553   // unprinted bits.
1554   //
1555   // We print values in binary, with spaces between each bit, in order for the
1556   // bits to align with the Z register bytes that they predicate.
1557   //   "# {name}<15:0>: 0b{-------------value------------}"
1558 
1559   int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;
1560   int lsb = q_index * print_size_in_bits;
1561   int msb = lsb + print_size_in_bits - 1;
1562   std::stringstream prefix;
1563   prefix << name << '<' << msb << ':' << lsb << '>';
1564 
1565   fprintf(stream_,
1566           "# %s%*s: %s0b",
1567           clr_preg_name,
1568           kPrintRegisterNameFieldWidth,
1569           prefix.str().c_str(),
1570           clr_preg_value);
1571   for (int i = msb; i >= lsb; i--) {
1572     fprintf(stream_, " %c", reg.GetBit(i) ? '1' : '0');
1573   }
1574   fprintf(stream_, "%s%s", clr_normal, suffix);
1575 }
1576 
PrintPartialPRegister(int code,int q_index,PrintRegisterFormat format,const char * suffix)1577 void Simulator::PrintPartialPRegister(int code,
1578                                       int q_index,
1579                                       PrintRegisterFormat format,
1580                                       const char* suffix) {
1581   VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);
1582   PrintPartialPRegister(PRegNameForCode(code),
1583                         pregisters_[code],
1584                         q_index,
1585                         format,
1586                         suffix);
1587 }
1588 
PrintSystemRegister(SystemRegister id)1589 void Simulator::PrintSystemRegister(SystemRegister id) {
1590   switch (id) {
1591     case NZCV:
1592       fprintf(stream_,
1593               "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1594               clr_flag_name,
1595               clr_flag_value,
1596               ReadNzcv().GetN(),
1597               ReadNzcv().GetZ(),
1598               ReadNzcv().GetC(),
1599               ReadNzcv().GetV(),
1600               clr_normal);
1601       break;
1602     case FPCR: {
1603       static const char* rmode[] = {"0b00 (Round to Nearest)",
1604                                     "0b01 (Round towards Plus Infinity)",
1605                                     "0b10 (Round towards Minus Infinity)",
1606                                     "0b11 (Round towards Zero)"};
1607       VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
1608       fprintf(stream_,
1609               "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1610               clr_flag_name,
1611               clr_flag_value,
1612               ReadFpcr().GetAHP(),
1613               ReadFpcr().GetDN(),
1614               ReadFpcr().GetFZ(),
1615               rmode[ReadFpcr().GetRMode()],
1616               clr_normal);
1617       break;
1618     }
1619     default:
1620       VIXL_UNREACHABLE();
1621   }
1622 }
1623 
PrintPartialAccess(uint16_t access_mask,uint16_t future_access_mask,int struct_element_count,int lane_size_in_bytes,const char * op,uintptr_t address,int reg_size_in_bytes)1624 uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,
1625                                        uint16_t future_access_mask,
1626                                        int struct_element_count,
1627                                        int lane_size_in_bytes,
1628                                        const char* op,
1629                                        uintptr_t address,
1630                                        int reg_size_in_bytes) {
1631   // We want to assume that we'll access at least one lane.
1632   VIXL_ASSERT(access_mask != 0);
1633   VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||
1634               (reg_size_in_bytes == kQRegSizeInBytes));
1635   bool started_annotation = false;
1636   // Indent to match the register field, the fixed formatting, and the value
1637   // prefix ("0x"): "# {name}: 0x"
1638   fprintf(stream_, "# %*s    ", kPrintRegisterNameFieldWidth, "");
1639   // First, annotate the lanes (byte by byte).
1640   for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {
1641     bool access = (access_mask & (1 << lane)) != 0;
1642     bool future = (future_access_mask & (1 << lane)) != 0;
1643     if (started_annotation) {
1644       // If we've started an annotation, draw a horizontal line in addition to
1645       // any other symbols.
1646       if (access) {
1647         fprintf(stream_, "─╨");
1648       } else if (future) {
1649         fprintf(stream_, "─║");
1650       } else {
1651         fprintf(stream_, "──");
1652       }
1653     } else {
1654       if (access) {
1655         started_annotation = true;
1656         fprintf(stream_, " ╙");
1657       } else if (future) {
1658         fprintf(stream_, " ║");
1659       } else {
1660         fprintf(stream_, "  ");
1661       }
1662     }
1663   }
1664   VIXL_ASSERT(started_annotation);
1665   fprintf(stream_, "─ 0x");
1666   int lane_size_in_nibbles = lane_size_in_bytes * 2;
1667   // Print the most-significant struct element first.
1668   const char* sep = "";
1669   for (int i = struct_element_count - 1; i >= 0; i--) {
1670     int offset = lane_size_in_bytes * i;
1671     uint64_t nibble = MemReadUint(lane_size_in_bytes, address + offset);
1672     fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, nibble);
1673     sep = "'";
1674   }
1675   fprintf(stream_,
1676           " %s %s0x%016" PRIxPTR "%s\n",
1677           op,
1678           clr_memory_address,
1679           address,
1680           clr_normal);
1681   return future_access_mask & ~access_mask;
1682 }
1683 
PrintAccess(int code,PrintRegisterFormat format,const char * op,uintptr_t address)1684 void Simulator::PrintAccess(int code,
1685                             PrintRegisterFormat format,
1686                             const char* op,
1687                             uintptr_t address) {
1688   VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1689   VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1690   if ((format & kPrintRegPartial) == 0) {
1691     registers_[code].NotifyRegisterLogged();
1692   }
1693   // Scalar-format accesses use a simple format:
1694   //   "# {reg}: 0x{value} -> {address}"
1695 
1696   // Suppress the newline, so the access annotation goes on the same line.
1697   PrintRegister(code, format, "");
1698   fprintf(stream_,
1699           " %s %s0x%016" PRIxPTR "%s\n",
1700           op,
1701           clr_memory_address,
1702           address,
1703           clr_normal);
1704 }
1705 
PrintVAccess(int code,PrintRegisterFormat format,const char * op,uintptr_t address)1706 void Simulator::PrintVAccess(int code,
1707                              PrintRegisterFormat format,
1708                              const char* op,
1709                              uintptr_t address) {
1710   VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1711 
1712   // Scalar-format accesses use a simple format:
1713   //   "# v{code}: 0x{value} -> {address}"
1714 
1715   // Suppress the newline, so the access annotation goes on the same line.
1716   PrintVRegister(code, format, "");
1717   fprintf(stream_,
1718           " %s %s0x%016" PRIxPTR "%s\n",
1719           op,
1720           clr_memory_address,
1721           address,
1722           clr_normal);
1723 }
1724 
PrintVStructAccess(int rt_code,int reg_count,PrintRegisterFormat format,const char * op,uintptr_t address)1725 void Simulator::PrintVStructAccess(int rt_code,
1726                                    int reg_count,
1727                                    PrintRegisterFormat format,
1728                                    const char* op,
1729                                    uintptr_t address) {
1730   VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1731 
1732   // For example:
1733   //   "# v{code}: 0x{value}"
1734   //   "#     ...: 0x{value}"
1735   //   "#              ║   ╙─ {struct_value} -> {lowest_address}"
1736   //   "#              ╙───── {struct_value} -> {highest_address}"
1737 
1738   uint16_t lane_mask = GetPrintRegLaneMask(format);
1739   PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1740 
1741   int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1742   int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1743   for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {
1744     uint16_t access_mask = 1 << i;
1745     VIXL_ASSERT((lane_mask & access_mask) != 0);
1746     lane_mask = PrintPartialAccess(access_mask,
1747                                    lane_mask,
1748                                    reg_count,
1749                                    lane_size_in_bytes,
1750                                    op,
1751                                    address + (i * reg_count));
1752   }
1753 }
1754 
PrintVSingleStructAccess(int rt_code,int reg_count,int lane,PrintRegisterFormat format,const char * op,uintptr_t address)1755 void Simulator::PrintVSingleStructAccess(int rt_code,
1756                                          int reg_count,
1757                                          int lane,
1758                                          PrintRegisterFormat format,
1759                                          const char* op,
1760                                          uintptr_t address) {
1761   VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1762 
1763   // For example:
1764   //   "# v{code}: 0x{value}"
1765   //   "#     ...: 0x{value}"
1766   //   "#              ╙───── {struct_value} -> {address}"
1767 
1768   int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1769   uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);
1770   PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1771   PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1772 }
1773 
PrintVReplicatingStructAccess(int rt_code,int reg_count,PrintRegisterFormat format,const char * op,uintptr_t address)1774 void Simulator::PrintVReplicatingStructAccess(int rt_code,
1775                                               int reg_count,
1776                                               PrintRegisterFormat format,
1777                                               const char* op,
1778                                               uintptr_t address) {
1779   VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1780 
1781   // For example:
1782   //   "# v{code}: 0x{value}"
1783   //   "#     ...: 0x{value}"
1784   //   "#            ╙─╨─╨─╨─ {struct_value} -> {address}"
1785 
1786   int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1787   uint16_t lane_mask = GetPrintRegLaneMask(format);
1788   PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1789   PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1790 }
1791 
PrintZAccess(int rt_code,const char * op,uintptr_t address)1792 void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {
1793   VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1794 
1795   // Scalar-format accesses are split into separate chunks, each of which uses a
1796   // simple format:
1797   //   "#   z{code}<127:0>: 0x{value} -> {address}"
1798   //   "# z{code}<255:128>: 0x{value} -> {address + 16}"
1799   //   "# z{code}<383:256>: 0x{value} -> {address + 32}"
1800   // etc
1801 
1802   int vl = GetVectorLengthInBits();
1803   VIXL_ASSERT((vl % kQRegSize) == 0);
1804   for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1805     // Suppress the newline, so the access annotation goes on the same line.
1806     PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");
1807     fprintf(stream_,
1808             " %s %s0x%016" PRIxPTR "%s\n",
1809             op,
1810             clr_memory_address,
1811             address,
1812             clr_normal);
1813     address += kQRegSizeInBytes;
1814   }
1815 }
1816 
PrintZStructAccess(int rt_code,int reg_count,const LogicPRegister & pg,PrintRegisterFormat format,int msize_in_bytes,const char * op,const LogicSVEAddressVector & addr)1817 void Simulator::PrintZStructAccess(int rt_code,
1818                                    int reg_count,
1819                                    const LogicPRegister& pg,
1820                                    PrintRegisterFormat format,
1821                                    int msize_in_bytes,
1822                                    const char* op,
1823                                    const LogicSVEAddressVector& addr) {
1824   VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1825 
1826   // For example:
1827   //   "# z{code}<255:128>: 0x{value}"
1828   //   "#     ...<255:128>: 0x{value}"
1829   //   "#                       ║   ╙─ {struct_value} -> {first_address}"
1830   //   "#                       ╙───── {struct_value} -> {last_address}"
1831 
1832   // We're going to print the register in parts, so force a partial format.
1833   bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;
1834   format = GetPrintRegPartial(format);
1835 
1836   int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);
1837   int vl = GetVectorLengthInBits();
1838   VIXL_ASSERT((vl % kQRegSize) == 0);
1839   int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;
1840   for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1841     uint16_t pred =
1842         pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);
1843     if ((pred == 0) && skip_inactive_chunks) continue;
1844 
1845     PrintZRegistersForStructuredAccess(rt_code,
1846                                        q_index,
1847                                        reg_count,
1848                                        pred,
1849                                        format);
1850     if (pred == 0) {
1851       // This register chunk has no active lanes. The loop below would print
1852       // nothing, so leave a blank line to keep structures grouped together.
1853       fprintf(stream_, "#\n");
1854       continue;
1855     }
1856     for (int i = 0; i < lanes_per_q; i++) {
1857       uint16_t access = 1 << (i * esize_in_bytes);
1858       int lane = (q_index * lanes_per_q) + i;
1859       // Skip inactive lanes.
1860       if ((pred & access) == 0) continue;
1861       pred = PrintPartialAccess(access,
1862                                 pred,
1863                                 reg_count,
1864                                 msize_in_bytes,
1865                                 op,
1866                                 addr.GetStructAddress(lane));
1867     }
1868   }
1869 
1870   // We print the whole register, even for stores.
1871   for (int i = 0; i < reg_count; i++) {
1872     vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();
1873   }
1874 }
1875 
PrintPAccess(int code,const char * op,uintptr_t address)1876 void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {
1877   VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1878 
1879   // Scalar-format accesses are split into separate chunks, each of which uses a
1880   // simple format:
1881   //   "#  p{code}<15:0>: 0b{value} -> {address}"
1882   //   "# p{code}<31:16>: 0b{value} -> {address + 2}"
1883   //   "# p{code}<47:32>: 0b{value} -> {address + 4}"
1884   // etc
1885 
1886   int vl = GetVectorLengthInBits();
1887   VIXL_ASSERT((vl % kQRegSize) == 0);
1888   for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1889     // Suppress the newline, so the access annotation goes on the same line.
1890     PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");
1891     fprintf(stream_,
1892             " %s %s0x%016" PRIxPTR "%s\n",
1893             op,
1894             clr_memory_address,
1895             address,
1896             clr_normal);
1897     address += kQRegSizeInBytes;
1898   }
1899 }
1900 
PrintRead(int rt_code,PrintRegisterFormat format,uintptr_t address)1901 void Simulator::PrintRead(int rt_code,
1902                           PrintRegisterFormat format,
1903                           uintptr_t address) {
1904   VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1905   registers_[rt_code].NotifyRegisterLogged();
1906   PrintAccess(rt_code, format, "<-", address);
1907 }
1908 
PrintExtendingRead(int rt_code,PrintRegisterFormat format,int access_size_in_bytes,uintptr_t address)1909 void Simulator::PrintExtendingRead(int rt_code,
1910                                    PrintRegisterFormat format,
1911                                    int access_size_in_bytes,
1912                                    uintptr_t address) {
1913   int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1914   if (access_size_in_bytes == reg_size_in_bytes) {
1915     // There is no extension here, so print a simple load.
1916     PrintRead(rt_code, format, address);
1917     return;
1918   }
1919   VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);
1920 
1921   // For sign- and zero-extension, make it clear that the resulting register
1922   // value is different from what is loaded from memory.
1923   VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1924   registers_[rt_code].NotifyRegisterLogged();
1925   PrintRegister(rt_code, format);
1926   PrintPartialAccess(1,
1927                      0,
1928                      1,
1929                      access_size_in_bytes,
1930                      "<-",
1931                      address,
1932                      kXRegSizeInBytes);
1933 }
1934 
PrintVRead(int rt_code,PrintRegisterFormat format,uintptr_t address)1935 void Simulator::PrintVRead(int rt_code,
1936                            PrintRegisterFormat format,
1937                            uintptr_t address) {
1938   VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1939   vregisters_[rt_code].NotifyRegisterLogged();
1940   PrintVAccess(rt_code, format, "<-", address);
1941 }
1942 
PrintWrite(int rt_code,PrintRegisterFormat format,uintptr_t address)1943 void Simulator::PrintWrite(int rt_code,
1944                            PrintRegisterFormat format,
1945                            uintptr_t address) {
1946   // Because this trace doesn't represent a change to the source register's
1947   // value, only print the relevant part of the value.
1948   format = GetPrintRegPartial(format);
1949   VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1950   registers_[rt_code].NotifyRegisterLogged();
1951   PrintAccess(rt_code, format, "->", address);
1952 }
1953 
PrintVWrite(int rt_code,PrintRegisterFormat format,uintptr_t address)1954 void Simulator::PrintVWrite(int rt_code,
1955                             PrintRegisterFormat format,
1956                             uintptr_t address) {
1957   // Because this trace doesn't represent a change to the source register's
1958   // value, only print the relevant part of the value.
1959   format = GetPrintRegPartial(format);
1960   // It only makes sense to write scalar values here. Vectors are handled by
1961   // PrintVStructAccess.
1962   VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1963   PrintVAccess(rt_code, format, "->", address);
1964 }
1965 
PrintTakenBranch(const Instruction * target)1966 void Simulator::PrintTakenBranch(const Instruction* target) {
1967   fprintf(stream_,
1968           "# %sBranch%s to 0x%016" PRIx64 ".\n",
1969           clr_branch_marker,
1970           clr_normal,
1971           reinterpret_cast<uint64_t>(target));
1972 }
1973 
1974 // Visitors---------------------------------------------------------------------
1975 
1976 
Visit(Metadata * metadata,const Instruction * instr)1977 void Simulator::Visit(Metadata* metadata, const Instruction* instr) {
1978   VIXL_ASSERT(metadata->count("form") > 0);
1979   std::string form = (*metadata)["form"];
1980   form_hash_ = Hash(form.c_str());
1981   const FormToVisitorFnMap* fv = Simulator::GetFormToVisitorFnMap();
1982   FormToVisitorFnMap::const_iterator it = fv->find(form_hash_);
1983   if (it == fv->end()) {
1984     VisitUnimplemented(instr);
1985   } else {
1986     (it->second)(this, instr);
1987   }
1988 }
1989 
Simulate_PdT_PgZ_ZnT_ZmT(const Instruction * instr)1990 void Simulator::Simulate_PdT_PgZ_ZnT_ZmT(const Instruction* instr) {
1991   VectorFormat vform = instr->GetSVEVectorFormat();
1992   SimPRegister& pd = ReadPRegister(instr->GetPd());
1993   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
1994   SimVRegister& zm = ReadVRegister(instr->GetRm());
1995   SimVRegister& zn = ReadVRegister(instr->GetRn());
1996 
1997   switch (form_hash_) {
1998     case "match_p_p_zz"_h:
1999       match(vform, pd, zn, zm, /* negate_match = */ false);
2000       break;
2001     case "nmatch_p_p_zz"_h:
2002       match(vform, pd, zn, zm, /* negate_match = */ true);
2003       break;
2004     default:
2005       VIXL_UNIMPLEMENTED();
2006   }
2007   mov_zeroing(pd, pg, pd);
2008   PredTest(vform, pg, pd);
2009 }
2010 
Simulate_PdT_Xn_Xm(const Instruction * instr)2011 void Simulator::Simulate_PdT_Xn_Xm(const Instruction* instr) {
2012   VectorFormat vform = instr->GetSVEVectorFormat();
2013   SimPRegister& pd = ReadPRegister(instr->GetPd());
2014   uint64_t src1 = ReadXRegister(instr->GetRn());
2015   uint64_t src2 = ReadXRegister(instr->GetRm());
2016 
2017   uint64_t absdiff = (src1 > src2) ? (src1 - src2) : (src2 - src1);
2018   absdiff >>= LaneSizeInBytesLog2FromFormat(vform);
2019 
2020   bool no_conflict = false;
2021   switch (form_hash_) {
2022     case "whilerw_p_rr"_h:
2023       no_conflict = (absdiff == 0);
2024       break;
2025     case "whilewr_p_rr"_h:
2026       no_conflict = (absdiff == 0) || (src2 <= src1);
2027       break;
2028     default:
2029       VIXL_UNIMPLEMENTED();
2030   }
2031 
2032   LogicPRegister dst(pd);
2033   for (int i = 0; i < LaneCountFromFormat(vform); i++) {
2034     dst.SetActive(vform,
2035                   i,
2036                   no_conflict || (static_cast<uint64_t>(i) < absdiff));
2037   }
2038 
2039   PredTest(vform, GetPTrue(), pd);
2040 }
2041 
Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction * instr)2042 void Simulator::Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction* instr) {
2043   VIXL_ASSERT(form_hash_ == "ext_z_zi_con"_h);
2044 
2045   SimVRegister& zd = ReadVRegister(instr->GetRd());
2046   SimVRegister& zn = ReadVRegister(instr->GetRn());
2047   SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
2048 
2049   int index = instr->GetSVEExtractImmediate();
2050   int vl = GetVectorLengthInBytes();
2051   index = (index >= vl) ? 0 : index;
2052 
2053   ext(kFormatVnB, zd, zn, zn2, index);
2054 }
2055 
Simulate_ZdB_ZnB_ZmB(const Instruction * instr)2056 void Simulator::Simulate_ZdB_ZnB_ZmB(const Instruction* instr) {
2057   SimVRegister& zd = ReadVRegister(instr->GetRd());
2058   SimVRegister& zm = ReadVRegister(instr->GetRm());
2059   SimVRegister& zn = ReadVRegister(instr->GetRn());
2060 
2061   switch (form_hash_) {
2062     case "histseg_z_zz"_h:
2063       if (instr->GetSVEVectorFormat() == kFormatVnB) {
2064         histogram(kFormatVnB,
2065                   zd,
2066                   GetPTrue(),
2067                   zn,
2068                   zm,
2069                   /* do_segmented = */ true);
2070       } else {
2071         VIXL_UNIMPLEMENTED();
2072       }
2073       break;
2074     case "pmul_z_zz"_h:
2075       pmul(kFormatVnB, zd, zn, zm);
2076       break;
2077     default:
2078       VIXL_UNIMPLEMENTED();
2079   }
2080 }
2081 
SimulateSVEMulIndex(const Instruction * instr)2082 void Simulator::SimulateSVEMulIndex(const Instruction* instr) {
2083   VectorFormat vform = instr->GetSVEVectorFormat();
2084   SimVRegister& zd = ReadVRegister(instr->GetRd());
2085   SimVRegister& zn = ReadVRegister(instr->GetRn());
2086 
2087   // The encoding for B and H-sized lanes are redefined to encode the most
2088   // significant bit of index for H-sized lanes. B-sized lanes are not
2089   // supported.
2090   if (vform == kFormatVnB) vform = kFormatVnH;
2091 
2092   VIXL_ASSERT((form_hash_ == "mul_z_zzi_d"_h) ||
2093               (form_hash_ == "mul_z_zzi_h"_h) ||
2094               (form_hash_ == "mul_z_zzi_s"_h));
2095 
2096   SimVRegister temp;
2097   dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2098   mul(vform, zd, zn, temp);
2099 }
2100 
SimulateSVEMlaMlsIndex(const Instruction * instr)2101 void Simulator::SimulateSVEMlaMlsIndex(const Instruction* instr) {
2102   VectorFormat vform = instr->GetSVEVectorFormat();
2103   SimVRegister& zda = ReadVRegister(instr->GetRd());
2104   SimVRegister& zn = ReadVRegister(instr->GetRn());
2105 
2106   // The encoding for B and H-sized lanes are redefined to encode the most
2107   // significant bit of index for H-sized lanes. B-sized lanes are not
2108   // supported.
2109   if (vform == kFormatVnB) vform = kFormatVnH;
2110 
2111   VIXL_ASSERT(
2112       (form_hash_ == "mla_z_zzzi_d"_h) || (form_hash_ == "mla_z_zzzi_h"_h) ||
2113       (form_hash_ == "mla_z_zzzi_s"_h) || (form_hash_ == "mls_z_zzzi_d"_h) ||
2114       (form_hash_ == "mls_z_zzzi_h"_h) || (form_hash_ == "mls_z_zzzi_s"_h));
2115 
2116   SimVRegister temp;
2117   dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2118   if (instr->ExtractBit(10) == 0) {
2119     mla(vform, zda, zda, zn, temp);
2120   } else {
2121     mls(vform, zda, zda, zn, temp);
2122   }
2123 }
2124 
SimulateSVESaturatingMulHighIndex(const Instruction * instr)2125 void Simulator::SimulateSVESaturatingMulHighIndex(const Instruction* instr) {
2126   VectorFormat vform = instr->GetSVEVectorFormat();
2127   SimVRegister& zd = ReadVRegister(instr->GetRd());
2128   SimVRegister& zn = ReadVRegister(instr->GetRn());
2129 
2130   // The encoding for B and H-sized lanes are redefined to encode the most
2131   // significant bit of index for H-sized lanes. B-sized lanes are not
2132   // supported.
2133   if (vform == kFormatVnB) {
2134     vform = kFormatVnH;
2135   }
2136 
2137   SimVRegister temp;
2138   dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2139   switch (form_hash_) {
2140     case "sqdmulh_z_zzi_h"_h:
2141     case "sqdmulh_z_zzi_s"_h:
2142     case "sqdmulh_z_zzi_d"_h:
2143       sqdmulh(vform, zd, zn, temp);
2144       break;
2145     case "sqrdmulh_z_zzi_h"_h:
2146     case "sqrdmulh_z_zzi_s"_h:
2147     case "sqrdmulh_z_zzi_d"_h:
2148       sqrdmulh(vform, zd, zn, temp);
2149       break;
2150     default:
2151       VIXL_UNIMPLEMENTED();
2152   }
2153 }
2154 
SimulateSVESaturatingIntMulLongIdx(const Instruction * instr)2155 void Simulator::SimulateSVESaturatingIntMulLongIdx(const Instruction* instr) {
2156   VectorFormat vform = instr->GetSVEVectorFormat();
2157   SimVRegister& zd = ReadVRegister(instr->GetRd());
2158   SimVRegister& zn = ReadVRegister(instr->GetRn());
2159 
2160   SimVRegister temp, zm_idx, zn_b, zn_t;
2161   // Instead of calling the indexed form of the instruction logic, we call the
2162   // vector form, which can reuse existing function logic without modification.
2163   // Select the specified elements based on the index input and than pack them
2164   // to the corresponding position.
2165   VectorFormat vform_half = VectorFormatHalfWidth(vform);
2166   dup_elements_to_segments(vform_half, temp, instr->GetSVEMulLongZmAndIndex());
2167   pack_even_elements(vform_half, zm_idx, temp);
2168 
2169   pack_even_elements(vform_half, zn_b, zn);
2170   pack_odd_elements(vform_half, zn_t, zn);
2171 
2172   switch (form_hash_) {
2173     case "smullb_z_zzi_s"_h:
2174     case "smullb_z_zzi_d"_h:
2175       smull(vform, zd, zn_b, zm_idx);
2176       break;
2177     case "smullt_z_zzi_s"_h:
2178     case "smullt_z_zzi_d"_h:
2179       smull(vform, zd, zn_t, zm_idx);
2180       break;
2181     case "sqdmullb_z_zzi_d"_h:
2182       sqdmull(vform, zd, zn_b, zm_idx);
2183       break;
2184     case "sqdmullt_z_zzi_d"_h:
2185       sqdmull(vform, zd, zn_t, zm_idx);
2186       break;
2187     case "umullb_z_zzi_s"_h:
2188     case "umullb_z_zzi_d"_h:
2189       umull(vform, zd, zn_b, zm_idx);
2190       break;
2191     case "umullt_z_zzi_s"_h:
2192     case "umullt_z_zzi_d"_h:
2193       umull(vform, zd, zn_t, zm_idx);
2194       break;
2195     case "sqdmullb_z_zzi_s"_h:
2196       sqdmull(vform, zd, zn_b, zm_idx);
2197       break;
2198     case "sqdmullt_z_zzi_s"_h:
2199       sqdmull(vform, zd, zn_t, zm_idx);
2200       break;
2201     case "smlalb_z_zzzi_s"_h:
2202     case "smlalb_z_zzzi_d"_h:
2203       smlal(vform, zd, zn_b, zm_idx);
2204       break;
2205     case "smlalt_z_zzzi_s"_h:
2206     case "smlalt_z_zzzi_d"_h:
2207       smlal(vform, zd, zn_t, zm_idx);
2208       break;
2209     case "smlslb_z_zzzi_s"_h:
2210     case "smlslb_z_zzzi_d"_h:
2211       smlsl(vform, zd, zn_b, zm_idx);
2212       break;
2213     case "smlslt_z_zzzi_s"_h:
2214     case "smlslt_z_zzzi_d"_h:
2215       smlsl(vform, zd, zn_t, zm_idx);
2216       break;
2217     case "umlalb_z_zzzi_s"_h:
2218     case "umlalb_z_zzzi_d"_h:
2219       umlal(vform, zd, zn_b, zm_idx);
2220       break;
2221     case "umlalt_z_zzzi_s"_h:
2222     case "umlalt_z_zzzi_d"_h:
2223       umlal(vform, zd, zn_t, zm_idx);
2224       break;
2225     case "umlslb_z_zzzi_s"_h:
2226     case "umlslb_z_zzzi_d"_h:
2227       umlsl(vform, zd, zn_b, zm_idx);
2228       break;
2229     case "umlslt_z_zzzi_s"_h:
2230     case "umlslt_z_zzzi_d"_h:
2231       umlsl(vform, zd, zn_t, zm_idx);
2232       break;
2233     default:
2234       VIXL_UNIMPLEMENTED();
2235   }
2236 }
2237 
Simulate_ZdH_PgM_ZnS(const Instruction * instr)2238 void Simulator::Simulate_ZdH_PgM_ZnS(const Instruction* instr) {
2239   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2240   SimVRegister& zd = ReadVRegister(instr->GetRd());
2241   SimVRegister& zn = ReadVRegister(instr->GetRn());
2242   SimVRegister result, zd_b;
2243 
2244   pack_even_elements(kFormatVnH, zd_b, zd);
2245 
2246   switch (form_hash_) {
2247     case "fcvtnt_z_p_z_s2h"_h:
2248       fcvt(kFormatVnH, kFormatVnS, result, pg, zn);
2249       pack_even_elements(kFormatVnH, result, result);
2250       zip1(kFormatVnH, result, zd_b, result);
2251       break;
2252     default:
2253       VIXL_UNIMPLEMENTED();
2254   }
2255   mov_merging(kFormatVnS, zd, pg, result);
2256 }
2257 
Simulate_ZdS_PgM_ZnD(const Instruction * instr)2258 void Simulator::Simulate_ZdS_PgM_ZnD(const Instruction* instr) {
2259   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2260   SimVRegister& zd = ReadVRegister(instr->GetRd());
2261   SimVRegister& zn = ReadVRegister(instr->GetRn());
2262   SimVRegister result, zero, zd_b;
2263 
2264   zero.Clear();
2265   pack_even_elements(kFormatVnS, zd_b, zd);
2266 
2267   switch (form_hash_) {
2268     case "fcvtnt_z_p_z_d2s"_h:
2269       fcvt(kFormatVnS, kFormatVnD, result, pg, zn);
2270       pack_even_elements(kFormatVnS, result, result);
2271       zip1(kFormatVnS, result, zd_b, result);
2272       break;
2273     case "fcvtx_z_p_z_d2s"_h:
2274       fcvtxn(kFormatVnS, result, zn);
2275       zip1(kFormatVnS, result, result, zero);
2276       break;
2277     case "fcvtxnt_z_p_z_d2s"_h:
2278       fcvtxn(kFormatVnS, result, zn);
2279       zip1(kFormatVnS, result, zd_b, result);
2280       break;
2281     default:
2282       VIXL_UNIMPLEMENTED();
2283   }
2284   mov_merging(kFormatVnD, zd, pg, result);
2285 }
2286 
SimulateSVEFPConvertLong(const Instruction * instr)2287 void Simulator::SimulateSVEFPConvertLong(const Instruction* instr) {
2288   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2289   SimVRegister& zd = ReadVRegister(instr->GetRd());
2290   SimVRegister& zn = ReadVRegister(instr->GetRn());
2291   SimVRegister result;
2292 
2293   switch (form_hash_) {
2294     case "fcvtlt_z_p_z_h2s"_h:
2295       ext(kFormatVnB, result, zn, zn, kHRegSizeInBytes);
2296       fcvt(kFormatVnS, kFormatVnH, zd, pg, result);
2297       break;
2298     case "fcvtlt_z_p_z_s2d"_h:
2299       ext(kFormatVnB, result, zn, zn, kSRegSizeInBytes);
2300       fcvt(kFormatVnD, kFormatVnS, zd, pg, result);
2301       break;
2302     default:
2303       VIXL_UNIMPLEMENTED();
2304   }
2305 }
2306 
Simulate_ZdS_PgM_ZnS(const Instruction * instr)2307 void Simulator::Simulate_ZdS_PgM_ZnS(const Instruction* instr) {
2308   VectorFormat vform = instr->GetSVEVectorFormat();
2309   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2310   SimVRegister& zd = ReadVRegister(instr->GetRd());
2311   SimVRegister& zn = ReadVRegister(instr->GetRn());
2312   SimVRegister result;
2313 
2314   if (vform != kFormatVnS) {
2315     VIXL_UNIMPLEMENTED();
2316   }
2317 
2318   switch (form_hash_) {
2319     case "urecpe_z_p_z"_h:
2320       urecpe(vform, result, zn);
2321       break;
2322     case "ursqrte_z_p_z"_h:
2323       ursqrte(vform, result, zn);
2324       break;
2325     default:
2326       VIXL_UNIMPLEMENTED();
2327   }
2328   mov_merging(vform, zd, pg, result);
2329 }
2330 
Simulate_ZdT_PgM_ZnT(const Instruction * instr)2331 void Simulator::Simulate_ZdT_PgM_ZnT(const Instruction* instr) {
2332   VectorFormat vform = instr->GetSVEVectorFormat();
2333   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2334   SimVRegister& zd = ReadVRegister(instr->GetRd());
2335   SimVRegister& zn = ReadVRegister(instr->GetRn());
2336   SimVRegister result;
2337 
2338   switch (form_hash_) {
2339     case "flogb_z_p_z"_h:
2340       vform = instr->GetSVEVectorFormat(17);
2341       flogb(vform, result, zn);
2342       break;
2343     case "sqabs_z_p_z"_h:
2344       abs(vform, result, zn).SignedSaturate(vform);
2345       break;
2346     case "sqneg_z_p_z"_h:
2347       neg(vform, result, zn).SignedSaturate(vform);
2348       break;
2349     default:
2350       VIXL_UNIMPLEMENTED();
2351   }
2352   mov_merging(vform, zd, pg, result);
2353 }
2354 
Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction * instr)2355 void Simulator::Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr) {
2356   VectorFormat vform = instr->GetSVEVectorFormat();
2357   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2358   SimVRegister& zd = ReadVRegister(instr->GetRd());
2359   SimVRegister& zm = ReadVRegister(instr->GetRm());
2360   SimVRegister& zn = ReadVRegister(instr->GetRn());
2361   SimVRegister result;
2362 
2363   VIXL_ASSERT(form_hash_ == "histcnt_z_p_zz"_h);
2364   if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
2365     histogram(vform, result, pg, zn, zm);
2366     mov_zeroing(vform, zd, pg, result);
2367   } else {
2368     VIXL_UNIMPLEMENTED();
2369   }
2370 }
2371 
Simulate_ZdT_ZnT_ZmT(const Instruction * instr)2372 void Simulator::Simulate_ZdT_ZnT_ZmT(const Instruction* instr) {
2373   VectorFormat vform = instr->GetSVEVectorFormat();
2374   SimVRegister& zd = ReadVRegister(instr->GetRd());
2375   SimVRegister& zm = ReadVRegister(instr->GetRm());
2376   SimVRegister& zn = ReadVRegister(instr->GetRn());
2377   SimVRegister result;
2378   bool do_bext = false;
2379 
2380   switch (form_hash_) {
2381     case "bdep_z_zz"_h:
2382       bdep(vform, zd, zn, zm);
2383       break;
2384     case "bext_z_zz"_h:
2385       do_bext = true;
2386       VIXL_FALLTHROUGH();
2387     case "bgrp_z_zz"_h:
2388       bgrp(vform, zd, zn, zm, do_bext);
2389       break;
2390     case "eorbt_z_zz"_h:
2391       rotate_elements_right(vform, result, zm, 1);
2392       SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2393       mov_alternating(vform, zd, result, 0);
2394       break;
2395     case "eortb_z_zz"_h:
2396       rotate_elements_right(vform, result, zm, -1);
2397       SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2398       mov_alternating(vform, zd, result, 1);
2399       break;
2400     case "mul_z_zz"_h:
2401       mul(vform, zd, zn, zm);
2402       break;
2403     case "smulh_z_zz"_h:
2404       smulh(vform, zd, zn, zm);
2405       break;
2406     case "sqdmulh_z_zz"_h:
2407       sqdmulh(vform, zd, zn, zm);
2408       break;
2409     case "sqrdmulh_z_zz"_h:
2410       sqrdmulh(vform, zd, zn, zm);
2411       break;
2412     case "umulh_z_zz"_h:
2413       umulh(vform, zd, zn, zm);
2414       break;
2415     default:
2416       VIXL_UNIMPLEMENTED();
2417   }
2418 }
2419 
Simulate_ZdT_ZnT_ZmTb(const Instruction * instr)2420 void Simulator::Simulate_ZdT_ZnT_ZmTb(const Instruction* instr) {
2421   VectorFormat vform = instr->GetSVEVectorFormat();
2422   SimVRegister& zd = ReadVRegister(instr->GetRd());
2423   SimVRegister& zm = ReadVRegister(instr->GetRm());
2424   SimVRegister& zn = ReadVRegister(instr->GetRn());
2425 
2426   SimVRegister zm_b, zm_t;
2427   VectorFormat vform_half = VectorFormatHalfWidth(vform);
2428   pack_even_elements(vform_half, zm_b, zm);
2429   pack_odd_elements(vform_half, zm_t, zm);
2430 
2431   switch (form_hash_) {
2432     case "saddwb_z_zz"_h:
2433       saddw(vform, zd, zn, zm_b);
2434       break;
2435     case "saddwt_z_zz"_h:
2436       saddw(vform, zd, zn, zm_t);
2437       break;
2438     case "ssubwb_z_zz"_h:
2439       ssubw(vform, zd, zn, zm_b);
2440       break;
2441     case "ssubwt_z_zz"_h:
2442       ssubw(vform, zd, zn, zm_t);
2443       break;
2444     case "uaddwb_z_zz"_h:
2445       uaddw(vform, zd, zn, zm_b);
2446       break;
2447     case "uaddwt_z_zz"_h:
2448       uaddw(vform, zd, zn, zm_t);
2449       break;
2450     case "usubwb_z_zz"_h:
2451       usubw(vform, zd, zn, zm_b);
2452       break;
2453     case "usubwt_z_zz"_h:
2454       usubw(vform, zd, zn, zm_t);
2455       break;
2456     default:
2457       VIXL_UNIMPLEMENTED();
2458   }
2459 }
2460 
Simulate_ZdT_ZnT_const(const Instruction * instr)2461 void Simulator::Simulate_ZdT_ZnT_const(const Instruction* instr) {
2462   SimVRegister& zd = ReadVRegister(instr->GetRd());
2463   SimVRegister& zn = ReadVRegister(instr->GetRn());
2464 
2465   std::pair<int, int> shift_and_lane_size =
2466       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2467   int lane_size = shift_and_lane_size.second;
2468   VIXL_ASSERT((lane_size >= 0) &&
2469               (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2470   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
2471   int shift_dist = shift_and_lane_size.first;
2472 
2473   switch (form_hash_) {
2474     case "sli_z_zzi"_h:
2475       // Shift distance is computed differently for left shifts. Convert the
2476       // result.
2477       shift_dist = (8 << lane_size) - shift_dist;
2478       sli(vform, zd, zn, shift_dist);
2479       break;
2480     case "sri_z_zzi"_h:
2481       sri(vform, zd, zn, shift_dist);
2482       break;
2483     default:
2484       VIXL_UNIMPLEMENTED();
2485   }
2486 }
2487 
SimulateSVENarrow(const Instruction * instr)2488 void Simulator::SimulateSVENarrow(const Instruction* instr) {
2489   SimVRegister& zd = ReadVRegister(instr->GetRd());
2490   SimVRegister& zn = ReadVRegister(instr->GetRn());
2491   SimVRegister result;
2492 
2493   std::pair<int, int> shift_and_lane_size =
2494       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2495   int lane_size = shift_and_lane_size.second;
2496   VIXL_ASSERT((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
2497               (lane_size <= static_cast<int>(kSRegSizeInBytesLog2)));
2498   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
2499   int right_shift_dist = shift_and_lane_size.first;
2500   bool top = false;
2501 
2502   switch (form_hash_) {
2503     case "sqxtnt_z_zz"_h:
2504       top = true;
2505       VIXL_FALLTHROUGH();
2506     case "sqxtnb_z_zz"_h:
2507       sqxtn(vform, result, zn);
2508       break;
2509     case "sqxtunt_z_zz"_h:
2510       top = true;
2511       VIXL_FALLTHROUGH();
2512     case "sqxtunb_z_zz"_h:
2513       sqxtun(vform, result, zn);
2514       break;
2515     case "uqxtnt_z_zz"_h:
2516       top = true;
2517       VIXL_FALLTHROUGH();
2518     case "uqxtnb_z_zz"_h:
2519       uqxtn(vform, result, zn);
2520       break;
2521     case "rshrnt_z_zi"_h:
2522       top = true;
2523       VIXL_FALLTHROUGH();
2524     case "rshrnb_z_zi"_h:
2525       rshrn(vform, result, zn, right_shift_dist);
2526       break;
2527     case "shrnt_z_zi"_h:
2528       top = true;
2529       VIXL_FALLTHROUGH();
2530     case "shrnb_z_zi"_h:
2531       shrn(vform, result, zn, right_shift_dist);
2532       break;
2533     case "sqrshrnt_z_zi"_h:
2534       top = true;
2535       VIXL_FALLTHROUGH();
2536     case "sqrshrnb_z_zi"_h:
2537       sqrshrn(vform, result, zn, right_shift_dist);
2538       break;
2539     case "sqrshrunt_z_zi"_h:
2540       top = true;
2541       VIXL_FALLTHROUGH();
2542     case "sqrshrunb_z_zi"_h:
2543       sqrshrun(vform, result, zn, right_shift_dist);
2544       break;
2545     case "sqshrnt_z_zi"_h:
2546       top = true;
2547       VIXL_FALLTHROUGH();
2548     case "sqshrnb_z_zi"_h:
2549       sqshrn(vform, result, zn, right_shift_dist);
2550       break;
2551     case "sqshrunt_z_zi"_h:
2552       top = true;
2553       VIXL_FALLTHROUGH();
2554     case "sqshrunb_z_zi"_h:
2555       sqshrun(vform, result, zn, right_shift_dist);
2556       break;
2557     case "uqrshrnt_z_zi"_h:
2558       top = true;
2559       VIXL_FALLTHROUGH();
2560     case "uqrshrnb_z_zi"_h:
2561       uqrshrn(vform, result, zn, right_shift_dist);
2562       break;
2563     case "uqshrnt_z_zi"_h:
2564       top = true;
2565       VIXL_FALLTHROUGH();
2566     case "uqshrnb_z_zi"_h:
2567       uqshrn(vform, result, zn, right_shift_dist);
2568       break;
2569     default:
2570       VIXL_UNIMPLEMENTED();
2571   }
2572 
2573   if (top) {
2574     // Keep even elements, replace odd elements with the results.
2575     xtn(vform, zd, zd);
2576     zip1(vform, zd, zd, result);
2577   } else {
2578     // Zero odd elements, replace even elements with the results.
2579     SimVRegister zero;
2580     zero.Clear();
2581     zip1(vform, zd, result, zero);
2582   }
2583 }
2584 
SimulateSVEInterleavedArithLong(const Instruction * instr)2585 void Simulator::SimulateSVEInterleavedArithLong(const Instruction* instr) {
2586   VectorFormat vform = instr->GetSVEVectorFormat();
2587   SimVRegister& zd = ReadVRegister(instr->GetRd());
2588   SimVRegister& zm = ReadVRegister(instr->GetRm());
2589   SimVRegister& zn = ReadVRegister(instr->GetRn());
2590   SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2591 
2592   // Construct temporary registers containing the even (bottom) and odd (top)
2593   // elements.
2594   VectorFormat vform_half = VectorFormatHalfWidth(vform);
2595   pack_even_elements(vform_half, zn_b, zn);
2596   pack_even_elements(vform_half, zm_b, zm);
2597   pack_odd_elements(vform_half, zn_t, zn);
2598   pack_odd_elements(vform_half, zm_t, zm);
2599 
2600   switch (form_hash_) {
2601     case "sabdlb_z_zz"_h:
2602       sabdl(vform, zd, zn_b, zm_b);
2603       break;
2604     case "sabdlt_z_zz"_h:
2605       sabdl(vform, zd, zn_t, zm_t);
2606       break;
2607     case "saddlb_z_zz"_h:
2608       saddl(vform, zd, zn_b, zm_b);
2609       break;
2610     case "saddlbt_z_zz"_h:
2611       saddl(vform, zd, zn_b, zm_t);
2612       break;
2613     case "saddlt_z_zz"_h:
2614       saddl(vform, zd, zn_t, zm_t);
2615       break;
2616     case "ssublb_z_zz"_h:
2617       ssubl(vform, zd, zn_b, zm_b);
2618       break;
2619     case "ssublbt_z_zz"_h:
2620       ssubl(vform, zd, zn_b, zm_t);
2621       break;
2622     case "ssublt_z_zz"_h:
2623       ssubl(vform, zd, zn_t, zm_t);
2624       break;
2625     case "ssubltb_z_zz"_h:
2626       ssubl(vform, zd, zn_t, zm_b);
2627       break;
2628     case "uabdlb_z_zz"_h:
2629       uabdl(vform, zd, zn_b, zm_b);
2630       break;
2631     case "uabdlt_z_zz"_h:
2632       uabdl(vform, zd, zn_t, zm_t);
2633       break;
2634     case "uaddlb_z_zz"_h:
2635       uaddl(vform, zd, zn_b, zm_b);
2636       break;
2637     case "uaddlt_z_zz"_h:
2638       uaddl(vform, zd, zn_t, zm_t);
2639       break;
2640     case "usublb_z_zz"_h:
2641       usubl(vform, zd, zn_b, zm_b);
2642       break;
2643     case "usublt_z_zz"_h:
2644       usubl(vform, zd, zn_t, zm_t);
2645       break;
2646     case "sabalb_z_zzz"_h:
2647       sabal(vform, zd, zn_b, zm_b);
2648       break;
2649     case "sabalt_z_zzz"_h:
2650       sabal(vform, zd, zn_t, zm_t);
2651       break;
2652     case "uabalb_z_zzz"_h:
2653       uabal(vform, zd, zn_b, zm_b);
2654       break;
2655     case "uabalt_z_zzz"_h:
2656       uabal(vform, zd, zn_t, zm_t);
2657       break;
2658     default:
2659       VIXL_UNIMPLEMENTED();
2660   }
2661 }
2662 
SimulateSVEIntMulLongVec(const Instruction * instr)2663 void Simulator::SimulateSVEIntMulLongVec(const Instruction* instr) {
2664   VectorFormat vform = instr->GetSVEVectorFormat();
2665   SimVRegister& zd = ReadVRegister(instr->GetRd());
2666   SimVRegister& zm = ReadVRegister(instr->GetRm());
2667   SimVRegister& zn = ReadVRegister(instr->GetRn());
2668   SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2669   VectorFormat vform_half = VectorFormatHalfWidth(vform);
2670   pack_even_elements(vform_half, zn_b, zn);
2671   pack_even_elements(vform_half, zm_b, zm);
2672   pack_odd_elements(vform_half, zn_t, zn);
2673   pack_odd_elements(vform_half, zm_t, zm);
2674 
2675   switch (form_hash_) {
2676     case "pmullb_z_zz"_h:
2677       // '00' is reserved for Q-sized lane.
2678       if (vform == kFormatVnB) {
2679         VIXL_UNIMPLEMENTED();
2680       }
2681       pmull(vform, zd, zn_b, zm_b);
2682       break;
2683     case "pmullt_z_zz"_h:
2684       // '00' is reserved for Q-sized lane.
2685       if (vform == kFormatVnB) {
2686         VIXL_UNIMPLEMENTED();
2687       }
2688       pmull(vform, zd, zn_t, zm_t);
2689       break;
2690     case "smullb_z_zz"_h:
2691       smull(vform, zd, zn_b, zm_b);
2692       break;
2693     case "smullt_z_zz"_h:
2694       smull(vform, zd, zn_t, zm_t);
2695       break;
2696     case "sqdmullb_z_zz"_h:
2697       sqdmull(vform, zd, zn_b, zm_b);
2698       break;
2699     case "sqdmullt_z_zz"_h:
2700       sqdmull(vform, zd, zn_t, zm_t);
2701       break;
2702     case "umullb_z_zz"_h:
2703       umull(vform, zd, zn_b, zm_b);
2704       break;
2705     case "umullt_z_zz"_h:
2706       umull(vform, zd, zn_t, zm_t);
2707       break;
2708     default:
2709       VIXL_UNIMPLEMENTED();
2710   }
2711 }
2712 
SimulateSVEAddSubHigh(const Instruction * instr)2713 void Simulator::SimulateSVEAddSubHigh(const Instruction* instr) {
2714   SimVRegister& zd = ReadVRegister(instr->GetRd());
2715   SimVRegister& zm = ReadVRegister(instr->GetRm());
2716   SimVRegister& zn = ReadVRegister(instr->GetRn());
2717   SimVRegister result;
2718   bool top = false;
2719 
2720   VectorFormat vform_src = instr->GetSVEVectorFormat();
2721   if (vform_src == kFormatVnB) {
2722     VIXL_UNIMPLEMENTED();
2723   }
2724   VectorFormat vform = VectorFormatHalfWidth(vform_src);
2725 
2726   switch (form_hash_) {
2727     case "addhnt_z_zz"_h:
2728       top = true;
2729       VIXL_FALLTHROUGH();
2730     case "addhnb_z_zz"_h:
2731       addhn(vform, result, zn, zm);
2732       break;
2733     case "raddhnt_z_zz"_h:
2734       top = true;
2735       VIXL_FALLTHROUGH();
2736     case "raddhnb_z_zz"_h:
2737       raddhn(vform, result, zn, zm);
2738       break;
2739     case "rsubhnt_z_zz"_h:
2740       top = true;
2741       VIXL_FALLTHROUGH();
2742     case "rsubhnb_z_zz"_h:
2743       rsubhn(vform, result, zn, zm);
2744       break;
2745     case "subhnt_z_zz"_h:
2746       top = true;
2747       VIXL_FALLTHROUGH();
2748     case "subhnb_z_zz"_h:
2749       subhn(vform, result, zn, zm);
2750       break;
2751     default:
2752       VIXL_UNIMPLEMENTED();
2753   }
2754 
2755   if (top) {
2756     // Keep even elements, replace odd elements with the results.
2757     xtn(vform, zd, zd);
2758     zip1(vform, zd, zd, result);
2759   } else {
2760     // Zero odd elements, replace even elements with the results.
2761     SimVRegister zero;
2762     zero.Clear();
2763     zip1(vform, zd, result, zero);
2764   }
2765 }
2766 
SimulateSVEShiftLeftImm(const Instruction * instr)2767 void Simulator::SimulateSVEShiftLeftImm(const Instruction* instr) {
2768   SimVRegister& zd = ReadVRegister(instr->GetRd());
2769   SimVRegister& zn = ReadVRegister(instr->GetRn());
2770   SimVRegister zn_b, zn_t;
2771 
2772   std::pair<int, int> shift_and_lane_size =
2773       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2774   int lane_size = shift_and_lane_size.second;
2775   VIXL_ASSERT((lane_size >= 0) &&
2776               (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2777   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size + 1);
2778   int right_shift_dist = shift_and_lane_size.first;
2779   int left_shift_dist = (8 << lane_size) - right_shift_dist;
2780 
2781   // Construct temporary registers containing the even (bottom) and odd (top)
2782   // elements.
2783   VectorFormat vform_half = VectorFormatHalfWidth(vform);
2784   pack_even_elements(vform_half, zn_b, zn);
2785   pack_odd_elements(vform_half, zn_t, zn);
2786 
2787   switch (form_hash_) {
2788     case "sshllb_z_zi"_h:
2789       sshll(vform, zd, zn_b, left_shift_dist);
2790       break;
2791     case "sshllt_z_zi"_h:
2792       sshll(vform, zd, zn_t, left_shift_dist);
2793       break;
2794     case "ushllb_z_zi"_h:
2795       ushll(vform, zd, zn_b, left_shift_dist);
2796       break;
2797     case "ushllt_z_zi"_h:
2798       ushll(vform, zd, zn_t, left_shift_dist);
2799       break;
2800     default:
2801       VIXL_UNIMPLEMENTED();
2802   }
2803 }
2804 
SimulateSVESaturatingMulAddHigh(const Instruction * instr)2805 void Simulator::SimulateSVESaturatingMulAddHigh(const Instruction* instr) {
2806   VectorFormat vform = instr->GetSVEVectorFormat();
2807   SimVRegister& zda = ReadVRegister(instr->GetRd());
2808   SimVRegister& zn = ReadVRegister(instr->GetRn());
2809   unsigned zm_code = instr->GetRm();
2810   int index = -1;
2811   bool is_mla = false;
2812 
2813   switch (form_hash_) {
2814     case "sqrdmlah_z_zzz"_h:
2815       is_mla = true;
2816       VIXL_FALLTHROUGH();
2817     case "sqrdmlsh_z_zzz"_h:
2818       // Nothing to do.
2819       break;
2820     case "sqrdmlah_z_zzzi_h"_h:
2821       is_mla = true;
2822       VIXL_FALLTHROUGH();
2823     case "sqrdmlsh_z_zzzi_h"_h:
2824       vform = kFormatVnH;
2825       index = (instr->ExtractBit(22) << 2) | instr->ExtractBits(20, 19);
2826       zm_code = instr->ExtractBits(18, 16);
2827       break;
2828     case "sqrdmlah_z_zzzi_s"_h:
2829       is_mla = true;
2830       VIXL_FALLTHROUGH();
2831     case "sqrdmlsh_z_zzzi_s"_h:
2832       vform = kFormatVnS;
2833       index = instr->ExtractBits(20, 19);
2834       zm_code = instr->ExtractBits(18, 16);
2835       break;
2836     case "sqrdmlah_z_zzzi_d"_h:
2837       is_mla = true;
2838       VIXL_FALLTHROUGH();
2839     case "sqrdmlsh_z_zzzi_d"_h:
2840       vform = kFormatVnD;
2841       index = instr->ExtractBit(20);
2842       zm_code = instr->ExtractBits(19, 16);
2843       break;
2844     default:
2845       VIXL_UNIMPLEMENTED();
2846   }
2847 
2848   SimVRegister& zm = ReadVRegister(zm_code);
2849   SimVRegister zm_idx;
2850   if (index >= 0) {
2851     dup_elements_to_segments(vform, zm_idx, zm, index);
2852   }
2853 
2854   if (is_mla) {
2855     sqrdmlah(vform, zda, zn, (index >= 0) ? zm_idx : zm);
2856   } else {
2857     sqrdmlsh(vform, zda, zn, (index >= 0) ? zm_idx : zm);
2858   }
2859 }
2860 
Simulate_ZdaD_ZnS_ZmS_imm(const Instruction * instr)2861 void Simulator::Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr) {
2862   SimVRegister& zda = ReadVRegister(instr->GetRd());
2863   SimVRegister& zn = ReadVRegister(instr->GetRn());
2864   SimVRegister& zm = ReadVRegister(instr->ExtractBits(19, 16));
2865 
2866   SimVRegister temp, zm_idx, zn_b, zn_t;
2867   Instr index = (instr->ExtractBit(20) << 1) | instr->ExtractBit(11);
2868   dup_elements_to_segments(kFormatVnS, temp, zm, index);
2869   pack_even_elements(kFormatVnS, zm_idx, temp);
2870   pack_even_elements(kFormatVnS, zn_b, zn);
2871   pack_odd_elements(kFormatVnS, zn_t, zn);
2872 
2873   switch (form_hash_) {
2874     case "sqdmlalb_z_zzzi_d"_h:
2875       sqdmlal(kFormatVnD, zda, zn_b, zm_idx);
2876       break;
2877     case "sqdmlalt_z_zzzi_d"_h:
2878       sqdmlal(kFormatVnD, zda, zn_t, zm_idx);
2879       break;
2880     case "sqdmlslb_z_zzzi_d"_h:
2881       sqdmlsl(kFormatVnD, zda, zn_b, zm_idx);
2882       break;
2883     case "sqdmlslt_z_zzzi_d"_h:
2884       sqdmlsl(kFormatVnD, zda, zn_t, zm_idx);
2885       break;
2886     default:
2887       VIXL_UNIMPLEMENTED();
2888   }
2889 }
2890 
Simulate_ZdaS_ZnH_ZmH(const Instruction * instr)2891 void Simulator::Simulate_ZdaS_ZnH_ZmH(const Instruction* instr) {
2892   SimVRegister& zda = ReadVRegister(instr->GetRd());
2893   SimVRegister& zm = ReadVRegister(instr->GetRm());
2894   SimVRegister& zn = ReadVRegister(instr->GetRn());
2895 
2896   SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2897   pack_even_elements(kFormatVnH, zn_b, zn);
2898   pack_even_elements(kFormatVnH, zm_b, zm);
2899   pack_odd_elements(kFormatVnH, zn_t, zn);
2900   pack_odd_elements(kFormatVnH, zm_t, zm);
2901 
2902   switch (form_hash_) {
2903     case "fmlalb_z_zzz"_h:
2904       fmlal(kFormatVnS, zda, zn_b, zm_b);
2905       break;
2906     case "fmlalt_z_zzz"_h:
2907       fmlal(kFormatVnS, zda, zn_t, zm_t);
2908       break;
2909     case "fmlslb_z_zzz"_h:
2910       fmlsl(kFormatVnS, zda, zn_b, zm_b);
2911       break;
2912     case "fmlslt_z_zzz"_h:
2913       fmlsl(kFormatVnS, zda, zn_t, zm_t);
2914       break;
2915     default:
2916       VIXL_UNIMPLEMENTED();
2917   }
2918 }
2919 
Simulate_ZdaS_ZnH_ZmH_imm(const Instruction * instr)2920 void Simulator::Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr) {
2921   SimVRegister& zda = ReadVRegister(instr->GetRd());
2922   SimVRegister& zn = ReadVRegister(instr->GetRn());
2923   SimVRegister& zm = ReadVRegister(instr->ExtractBits(18, 16));
2924 
2925   SimVRegister temp, zm_idx, zn_b, zn_t;
2926   Instr index = (instr->ExtractBits(20, 19) << 1) | instr->ExtractBit(11);
2927   dup_elements_to_segments(kFormatVnH, temp, zm, index);
2928   pack_even_elements(kFormatVnH, zm_idx, temp);
2929   pack_even_elements(kFormatVnH, zn_b, zn);
2930   pack_odd_elements(kFormatVnH, zn_t, zn);
2931 
2932   switch (form_hash_) {
2933     case "fmlalb_z_zzzi_s"_h:
2934       fmlal(kFormatVnS, zda, zn_b, zm_idx);
2935       break;
2936     case "fmlalt_z_zzzi_s"_h:
2937       fmlal(kFormatVnS, zda, zn_t, zm_idx);
2938       break;
2939     case "fmlslb_z_zzzi_s"_h:
2940       fmlsl(kFormatVnS, zda, zn_b, zm_idx);
2941       break;
2942     case "fmlslt_z_zzzi_s"_h:
2943       fmlsl(kFormatVnS, zda, zn_t, zm_idx);
2944       break;
2945     case "sqdmlalb_z_zzzi_s"_h:
2946       sqdmlal(kFormatVnS, zda, zn_b, zm_idx);
2947       break;
2948     case "sqdmlalt_z_zzzi_s"_h:
2949       sqdmlal(kFormatVnS, zda, zn_t, zm_idx);
2950       break;
2951     case "sqdmlslb_z_zzzi_s"_h:
2952       sqdmlsl(kFormatVnS, zda, zn_b, zm_idx);
2953       break;
2954     case "sqdmlslt_z_zzzi_s"_h:
2955       sqdmlsl(kFormatVnS, zda, zn_t, zm_idx);
2956       break;
2957     default:
2958       VIXL_UNIMPLEMENTED();
2959   }
2960 }
2961 
Simulate_ZdaT_PgM_ZnTb(const Instruction * instr)2962 void Simulator::Simulate_ZdaT_PgM_ZnTb(const Instruction* instr) {
2963   VectorFormat vform = instr->GetSVEVectorFormat();
2964   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2965   SimVRegister& zda = ReadVRegister(instr->GetRd());
2966   SimVRegister& zn = ReadVRegister(instr->GetRn());
2967   SimVRegister result;
2968 
2969   switch (form_hash_) {
2970     case "sadalp_z_p_z"_h:
2971       sadalp(vform, result, zn);
2972       break;
2973     case "uadalp_z_p_z"_h:
2974       uadalp(vform, result, zn);
2975       break;
2976     default:
2977       VIXL_UNIMPLEMENTED();
2978   }
2979   mov_merging(vform, zda, pg, result);
2980 }
2981 
SimulateSVEAddSubCarry(const Instruction * instr)2982 void Simulator::SimulateSVEAddSubCarry(const Instruction* instr) {
2983   VectorFormat vform = (instr->ExtractBit(22) == 0) ? kFormatVnS : kFormatVnD;
2984   SimVRegister& zda = ReadVRegister(instr->GetRd());
2985   SimVRegister& zm = ReadVRegister(instr->GetRm());
2986   SimVRegister& zn = ReadVRegister(instr->GetRn());
2987 
2988   SimVRegister not_zn;
2989   not_(vform, not_zn, zn);
2990 
2991   switch (form_hash_) {
2992     case "adclb_z_zzz"_h:
2993       adcl(vform, zda, zn, zm, /* top = */ false);
2994       break;
2995     case "adclt_z_zzz"_h:
2996       adcl(vform, zda, zn, zm, /* top = */ true);
2997       break;
2998     case "sbclb_z_zzz"_h:
2999       adcl(vform, zda, not_zn, zm, /* top = */ false);
3000       break;
3001     case "sbclt_z_zzz"_h:
3002       adcl(vform, zda, not_zn, zm, /* top = */ true);
3003       break;
3004     default:
3005       VIXL_UNIMPLEMENTED();
3006   }
3007 }
3008 
Simulate_ZdaT_ZnT_ZmT(const Instruction * instr)3009 void Simulator::Simulate_ZdaT_ZnT_ZmT(const Instruction* instr) {
3010   VectorFormat vform = instr->GetSVEVectorFormat();
3011   SimVRegister& zda = ReadVRegister(instr->GetRd());
3012   SimVRegister& zm = ReadVRegister(instr->GetRm());
3013   SimVRegister& zn = ReadVRegister(instr->GetRn());
3014 
3015   switch (form_hash_) {
3016     case "saba_z_zzz"_h:
3017       saba(vform, zda, zn, zm);
3018       break;
3019     case "uaba_z_zzz"_h:
3020       uaba(vform, zda, zn, zm);
3021       break;
3022     default:
3023       VIXL_UNIMPLEMENTED();
3024   }
3025 }
3026 
SimulateSVEComplexIntMulAdd(const Instruction * instr)3027 void Simulator::SimulateSVEComplexIntMulAdd(const Instruction* instr) {
3028   SimVRegister& zda = ReadVRegister(instr->GetRd());
3029   SimVRegister& zn = ReadVRegister(instr->GetRn());
3030   int rot = instr->ExtractBits(11, 10) * 90;
3031   // vform and zm are only valid for the vector form of instruction.
3032   VectorFormat vform = instr->GetSVEVectorFormat();
3033   SimVRegister& zm = ReadVRegister(instr->GetRm());
3034 
3035   // Inputs for indexed form of instruction.
3036   SimVRegister& zm_h = ReadVRegister(instr->ExtractBits(18, 16));
3037   SimVRegister& zm_s = ReadVRegister(instr->ExtractBits(19, 16));
3038   int idx_h = instr->ExtractBits(20, 19);
3039   int idx_s = instr->ExtractBit(20);
3040 
3041   switch (form_hash_) {
3042     case "cmla_z_zzz"_h:
3043       cmla(vform, zda, zda, zn, zm, rot);
3044       break;
3045     case "cmla_z_zzzi_h"_h:
3046       cmla(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot);
3047       break;
3048     case "cmla_z_zzzi_s"_h:
3049       cmla(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot);
3050       break;
3051     case "sqrdcmlah_z_zzz"_h:
3052       sqrdcmlah(vform, zda, zda, zn, zm, rot);
3053       break;
3054     case "sqrdcmlah_z_zzzi_h"_h:
3055       sqrdcmlah(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot);
3056       break;
3057     case "sqrdcmlah_z_zzzi_s"_h:
3058       sqrdcmlah(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot);
3059       break;
3060     default:
3061       VIXL_UNIMPLEMENTED();
3062   }
3063 }
3064 
Simulate_ZdaT_ZnT_const(const Instruction * instr)3065 void Simulator::Simulate_ZdaT_ZnT_const(const Instruction* instr) {
3066   SimVRegister& zd = ReadVRegister(instr->GetRd());
3067   SimVRegister& zn = ReadVRegister(instr->GetRn());
3068 
3069   std::pair<int, int> shift_and_lane_size =
3070       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3071   int lane_size = shift_and_lane_size.second;
3072   VIXL_ASSERT((lane_size >= 0) &&
3073               (static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
3074   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3075   int shift_dist = shift_and_lane_size.first;
3076 
3077   switch (form_hash_) {
3078     case "srsra_z_zi"_h:
3079       srsra(vform, zd, zn, shift_dist);
3080       break;
3081     case "ssra_z_zi"_h:
3082       ssra(vform, zd, zn, shift_dist);
3083       break;
3084     case "ursra_z_zi"_h:
3085       ursra(vform, zd, zn, shift_dist);
3086       break;
3087     case "usra_z_zi"_h:
3088       usra(vform, zd, zn, shift_dist);
3089       break;
3090     default:
3091       VIXL_UNIMPLEMENTED();
3092   }
3093 }
3094 
Simulate_ZdaT_ZnTb_ZmTb(const Instruction * instr)3095 void Simulator::Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr) {
3096   VectorFormat vform = instr->GetSVEVectorFormat();
3097   SimVRegister& zda = ReadVRegister(instr->GetRd());
3098   SimVRegister& zm = ReadVRegister(instr->GetRm());
3099   SimVRegister& zn = ReadVRegister(instr->GetRn());
3100 
3101   SimVRegister zero, zn_b, zm_b, zn_t, zm_t;
3102   zero.Clear();
3103 
3104   VectorFormat vform_half = VectorFormatHalfWidth(vform);
3105   uzp1(vform_half, zn_b, zn, zero);
3106   uzp1(vform_half, zm_b, zm, zero);
3107   uzp2(vform_half, zn_t, zn, zero);
3108   uzp2(vform_half, zm_t, zm, zero);
3109 
3110   switch (form_hash_) {
3111     case "smlalb_z_zzz"_h:
3112       smlal(vform, zda, zn_b, zm_b);
3113       break;
3114     case "smlalt_z_zzz"_h:
3115       smlal(vform, zda, zn_t, zm_t);
3116       break;
3117     case "smlslb_z_zzz"_h:
3118       smlsl(vform, zda, zn_b, zm_b);
3119       break;
3120     case "smlslt_z_zzz"_h:
3121       smlsl(vform, zda, zn_t, zm_t);
3122       break;
3123     case "sqdmlalb_z_zzz"_h:
3124       sqdmlal(vform, zda, zn_b, zm_b);
3125       break;
3126     case "sqdmlalbt_z_zzz"_h:
3127       sqdmlal(vform, zda, zn_b, zm_t);
3128       break;
3129     case "sqdmlalt_z_zzz"_h:
3130       sqdmlal(vform, zda, zn_t, zm_t);
3131       break;
3132     case "sqdmlslb_z_zzz"_h:
3133       sqdmlsl(vform, zda, zn_b, zm_b);
3134       break;
3135     case "sqdmlslbt_z_zzz"_h:
3136       sqdmlsl(vform, zda, zn_b, zm_t);
3137       break;
3138     case "sqdmlslt_z_zzz"_h:
3139       sqdmlsl(vform, zda, zn_t, zm_t);
3140       break;
3141     case "umlalb_z_zzz"_h:
3142       umlal(vform, zda, zn_b, zm_b);
3143       break;
3144     case "umlalt_z_zzz"_h:
3145       umlal(vform, zda, zn_t, zm_t);
3146       break;
3147     case "umlslb_z_zzz"_h:
3148       umlsl(vform, zda, zn_b, zm_b);
3149       break;
3150     case "umlslt_z_zzz"_h:
3151       umlsl(vform, zda, zn_t, zm_t);
3152       break;
3153     default:
3154       VIXL_UNIMPLEMENTED();
3155   }
3156 }
3157 
SimulateSVEComplexDotProduct(const Instruction * instr)3158 void Simulator::SimulateSVEComplexDotProduct(const Instruction* instr) {
3159   VectorFormat vform = instr->GetSVEVectorFormat();
3160   SimVRegister& zda = ReadVRegister(instr->GetRd());
3161   SimVRegister& zn = ReadVRegister(instr->GetRn());
3162   int rot = instr->ExtractBits(11, 10) * 90;
3163   unsigned zm_code = instr->GetRm();
3164   int index = -1;
3165 
3166   switch (form_hash_) {
3167     case "cdot_z_zzz"_h:
3168       // Nothing to do.
3169       break;
3170     case "cdot_z_zzzi_s"_h:
3171       index = zm_code >> 3;
3172       zm_code &= 0x7;
3173       break;
3174     case "cdot_z_zzzi_d"_h:
3175       index = zm_code >> 4;
3176       zm_code &= 0xf;
3177       break;
3178     default:
3179       VIXL_UNIMPLEMENTED();
3180   }
3181 
3182   SimVRegister temp;
3183   SimVRegister& zm = ReadVRegister(zm_code);
3184   if (index >= 0) dup_elements_to_segments(vform, temp, zm, index);
3185   cdot(vform, zda, zda, zn, (index >= 0) ? temp : zm, rot);
3186 }
3187 
SimulateSVEBitwiseTernary(const Instruction * instr)3188 void Simulator::SimulateSVEBitwiseTernary(const Instruction* instr) {
3189   VectorFormat vform = kFormatVnD;
3190   SimVRegister& zdn = ReadVRegister(instr->GetRd());
3191   SimVRegister& zm = ReadVRegister(instr->GetRm());
3192   SimVRegister& zk = ReadVRegister(instr->GetRn());
3193   SimVRegister temp;
3194 
3195   switch (form_hash_) {
3196     case "bcax_z_zzz"_h:
3197       bic(vform, temp, zm, zk);
3198       eor(vform, zdn, temp, zdn);
3199       break;
3200     case "bsl1n_z_zzz"_h:
3201       not_(vform, temp, zdn);
3202       bsl(vform, zdn, zk, temp, zm);
3203       break;
3204     case "bsl2n_z_zzz"_h:
3205       not_(vform, temp, zm);
3206       bsl(vform, zdn, zk, zdn, temp);
3207       break;
3208     case "bsl_z_zzz"_h:
3209       bsl(vform, zdn, zk, zdn, zm);
3210       break;
3211     case "eor3_z_zzz"_h:
3212       eor(vform, temp, zdn, zm);
3213       eor(vform, zdn, temp, zk);
3214       break;
3215     case "nbsl_z_zzz"_h:
3216       bsl(vform, zdn, zk, zdn, zm);
3217       not_(vform, zdn, zdn);
3218       break;
3219     default:
3220       VIXL_UNIMPLEMENTED();
3221   }
3222 }
3223 
SimulateSVEHalvingAddSub(const Instruction * instr)3224 void Simulator::SimulateSVEHalvingAddSub(const Instruction* instr) {
3225   VectorFormat vform = instr->GetSVEVectorFormat();
3226   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3227   SimVRegister& zdn = ReadVRegister(instr->GetRd());
3228   SimVRegister& zm = ReadVRegister(instr->GetRn());
3229   SimVRegister result;
3230 
3231   switch (form_hash_) {
3232     case "shadd_z_p_zz"_h:
3233       add(vform, result, zdn, zm).Halve(vform);
3234       break;
3235     case "shsub_z_p_zz"_h:
3236       sub(vform, result, zdn, zm).Halve(vform);
3237       break;
3238     case "shsubr_z_p_zz"_h:
3239       sub(vform, result, zm, zdn).Halve(vform);
3240       break;
3241     case "srhadd_z_p_zz"_h:
3242       add(vform, result, zdn, zm).Halve(vform).Round(vform);
3243       break;
3244     case "uhadd_z_p_zz"_h:
3245       add(vform, result, zdn, zm).Uhalve(vform);
3246       break;
3247     case "uhsub_z_p_zz"_h:
3248       sub(vform, result, zdn, zm).Uhalve(vform);
3249       break;
3250     case "uhsubr_z_p_zz"_h:
3251       sub(vform, result, zm, zdn).Uhalve(vform);
3252       break;
3253     case "urhadd_z_p_zz"_h:
3254       add(vform, result, zdn, zm).Uhalve(vform).Round(vform);
3255       break;
3256     default:
3257       VIXL_UNIMPLEMENTED();
3258       break;
3259   }
3260   mov_merging(vform, zdn, pg, result);
3261 }
3262 
SimulateSVESaturatingArithmetic(const Instruction * instr)3263 void Simulator::SimulateSVESaturatingArithmetic(const Instruction* instr) {
3264   VectorFormat vform = instr->GetSVEVectorFormat();
3265   SimVRegister& zdn = ReadVRegister(instr->GetRd());
3266   SimVRegister& zm = ReadVRegister(instr->GetRn());
3267   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3268   SimVRegister result;
3269 
3270   switch (form_hash_) {
3271     case "sqadd_z_p_zz"_h:
3272       add(vform, result, zdn, zm).SignedSaturate(vform);
3273       break;
3274     case "sqsub_z_p_zz"_h:
3275       sub(vform, result, zdn, zm).SignedSaturate(vform);
3276       break;
3277     case "sqsubr_z_p_zz"_h:
3278       sub(vform, result, zm, zdn).SignedSaturate(vform);
3279       break;
3280     case "suqadd_z_p_zz"_h:
3281       suqadd(vform, result, zdn, zm);
3282       break;
3283     case "uqadd_z_p_zz"_h:
3284       add(vform, result, zdn, zm).UnsignedSaturate(vform);
3285       break;
3286     case "uqsub_z_p_zz"_h:
3287       sub(vform, result, zdn, zm).UnsignedSaturate(vform);
3288       break;
3289     case "uqsubr_z_p_zz"_h:
3290       sub(vform, result, zm, zdn).UnsignedSaturate(vform);
3291       break;
3292     case "usqadd_z_p_zz"_h:
3293       usqadd(vform, result, zdn, zm);
3294       break;
3295     default:
3296       VIXL_UNIMPLEMENTED();
3297       break;
3298   }
3299   mov_merging(vform, zdn, pg, result);
3300 }
3301 
SimulateSVEIntArithPair(const Instruction * instr)3302 void Simulator::SimulateSVEIntArithPair(const Instruction* instr) {
3303   VectorFormat vform = instr->GetSVEVectorFormat();
3304   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3305   SimVRegister& zdn = ReadVRegister(instr->GetRd());
3306   SimVRegister& zm = ReadVRegister(instr->GetRn());
3307   SimVRegister result;
3308 
3309   switch (form_hash_) {
3310     case "addp_z_p_zz"_h:
3311       addp(vform, result, zdn, zm);
3312       break;
3313     case "smaxp_z_p_zz"_h:
3314       smaxp(vform, result, zdn, zm);
3315       break;
3316     case "sminp_z_p_zz"_h:
3317       sminp(vform, result, zdn, zm);
3318       break;
3319     case "umaxp_z_p_zz"_h:
3320       umaxp(vform, result, zdn, zm);
3321       break;
3322     case "uminp_z_p_zz"_h:
3323       uminp(vform, result, zdn, zm);
3324       break;
3325     default:
3326       VIXL_UNIMPLEMENTED();
3327       break;
3328   }
3329   mov_merging(vform, zdn, pg, result);
3330 }
3331 
Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction * instr)3332 void Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr) {
3333   VectorFormat vform = instr->GetSVEVectorFormat();
3334   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3335   SimVRegister& zdn = ReadVRegister(instr->GetRd());
3336   SimVRegister& zm = ReadVRegister(instr->GetRn());
3337   SimVRegister result;
3338 
3339   switch (form_hash_) {
3340     case "faddp_z_p_zz"_h:
3341       faddp(vform, result, zdn, zm);
3342       break;
3343     case "fmaxnmp_z_p_zz"_h:
3344       fmaxnmp(vform, result, zdn, zm);
3345       break;
3346     case "fmaxp_z_p_zz"_h:
3347       fmaxp(vform, result, zdn, zm);
3348       break;
3349     case "fminnmp_z_p_zz"_h:
3350       fminnmp(vform, result, zdn, zm);
3351       break;
3352     case "fminp_z_p_zz"_h:
3353       fminp(vform, result, zdn, zm);
3354       break;
3355     default:
3356       VIXL_UNIMPLEMENTED();
3357   }
3358   mov_merging(vform, zdn, pg, result);
3359 }
3360 
Simulate_ZdnT_PgM_ZdnT_const(const Instruction * instr)3361 void Simulator::Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr) {
3362   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3363   SimVRegister& zdn = ReadVRegister(instr->GetRd());
3364 
3365   std::pair<int, int> shift_and_lane_size =
3366       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
3367   unsigned lane_size = shift_and_lane_size.second;
3368   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3369   int right_shift_dist = shift_and_lane_size.first;
3370   int left_shift_dist = (8 << lane_size) - right_shift_dist;
3371   SimVRegister result;
3372 
3373   switch (form_hash_) {
3374     case "sqshl_z_p_zi"_h:
3375       sqshl(vform, result, zdn, left_shift_dist);
3376       break;
3377     case "sqshlu_z_p_zi"_h:
3378       sqshlu(vform, result, zdn, left_shift_dist);
3379       break;
3380     case "srshr_z_p_zi"_h:
3381       sshr(vform, result, zdn, right_shift_dist).Round(vform);
3382       break;
3383     case "uqshl_z_p_zi"_h:
3384       uqshl(vform, result, zdn, left_shift_dist);
3385       break;
3386     case "urshr_z_p_zi"_h:
3387       ushr(vform, result, zdn, right_shift_dist).Round(vform);
3388       break;
3389     default:
3390       VIXL_UNIMPLEMENTED();
3391   }
3392   mov_merging(vform, zdn, pg, result);
3393 }
3394 
SimulateSVEExclusiveOrRotate(const Instruction * instr)3395 void Simulator::SimulateSVEExclusiveOrRotate(const Instruction* instr) {
3396   VIXL_ASSERT(form_hash_ == "xar_z_zzi"_h);
3397 
3398   SimVRegister& zdn = ReadVRegister(instr->GetRd());
3399   SimVRegister& zm = ReadVRegister(instr->GetRn());
3400 
3401   std::pair<int, int> shift_and_lane_size =
3402       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3403   unsigned lane_size = shift_and_lane_size.second;
3404   VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
3405   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3406   int shift_dist = shift_and_lane_size.first;
3407   eor(vform, zdn, zdn, zm);
3408   ror(vform, zdn, zdn, shift_dist);
3409 }
3410 
Simulate_ZdnT_ZdnT_ZmT_const(const Instruction * instr)3411 void Simulator::Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr) {
3412   VectorFormat vform = instr->GetSVEVectorFormat();
3413   SimVRegister& zdn = ReadVRegister(instr->GetRd());
3414   SimVRegister& zm = ReadVRegister(instr->GetRn());
3415   int rot = (instr->ExtractBit(10) == 0) ? 90 : 270;
3416 
3417   switch (form_hash_) {
3418     case "cadd_z_zz"_h:
3419       cadd(vform, zdn, zdn, zm, rot);
3420       break;
3421     case "sqcadd_z_zz"_h:
3422       cadd(vform, zdn, zdn, zm, rot, /* saturate = */ true);
3423       break;
3424     default:
3425       VIXL_UNIMPLEMENTED();
3426   }
3427 }
3428 
Simulate_ZtD_PgZ_ZnD_Xm(const Instruction * instr)3429 void Simulator::Simulate_ZtD_PgZ_ZnD_Xm(const Instruction* instr) {
3430   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3431   SimVRegister& zn = ReadVRegister(instr->GetRn());
3432   uint64_t xm = ReadXRegister(instr->GetRm());
3433 
3434   LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3435   int msize = -1;
3436   bool is_signed = false;
3437 
3438   switch (form_hash_) {
3439     case "ldnt1b_z_p_ar_d_64_unscaled"_h:
3440       msize = 0;
3441       break;
3442     case "ldnt1d_z_p_ar_d_64_unscaled"_h:
3443       msize = 3;
3444       break;
3445     case "ldnt1h_z_p_ar_d_64_unscaled"_h:
3446       msize = 1;
3447       break;
3448     case "ldnt1sb_z_p_ar_d_64_unscaled"_h:
3449       msize = 0;
3450       is_signed = true;
3451       break;
3452     case "ldnt1sh_z_p_ar_d_64_unscaled"_h:
3453       msize = 1;
3454       is_signed = true;
3455       break;
3456     case "ldnt1sw_z_p_ar_d_64_unscaled"_h:
3457       msize = 2;
3458       is_signed = true;
3459       break;
3460     case "ldnt1w_z_p_ar_d_64_unscaled"_h:
3461       msize = 2;
3462       break;
3463     default:
3464       VIXL_UNIMPLEMENTED();
3465   }
3466   addr.SetMsizeInBytesLog2(msize);
3467   SVEStructuredLoadHelper(kFormatVnD, pg, instr->GetRt(), addr, is_signed);
3468 }
3469 
Simulate_ZtD_Pg_ZnD_Xm(const Instruction * instr)3470 void Simulator::Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr) {
3471   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3472   SimVRegister& zn = ReadVRegister(instr->GetRn());
3473   uint64_t xm = ReadXRegister(instr->GetRm());
3474 
3475   LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3476   VIXL_ASSERT((form_hash_ == "stnt1b_z_p_ar_d_64_unscaled"_h) ||
3477               (form_hash_ == "stnt1d_z_p_ar_d_64_unscaled"_h) ||
3478               (form_hash_ == "stnt1h_z_p_ar_d_64_unscaled"_h) ||
3479               (form_hash_ == "stnt1w_z_p_ar_d_64_unscaled"_h));
3480 
3481   addr.SetMsizeInBytesLog2(
3482       instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3483   SVEStructuredStoreHelper(kFormatVnD, pg, instr->GetRt(), addr);
3484 }
3485 
Simulate_ZtS_PgZ_ZnS_Xm(const Instruction * instr)3486 void Simulator::Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr) {
3487   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3488   SimVRegister& zn = ReadVRegister(instr->GetRn());
3489   uint64_t xm = ReadXRegister(instr->GetRm());
3490 
3491   LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3492   int msize = -1;
3493   bool is_signed = false;
3494 
3495   switch (form_hash_) {
3496     case "ldnt1b_z_p_ar_s_x32_unscaled"_h:
3497       msize = 0;
3498       break;
3499     case "ldnt1h_z_p_ar_s_x32_unscaled"_h:
3500       msize = 1;
3501       break;
3502     case "ldnt1sb_z_p_ar_s_x32_unscaled"_h:
3503       msize = 0;
3504       is_signed = true;
3505       break;
3506     case "ldnt1sh_z_p_ar_s_x32_unscaled"_h:
3507       msize = 1;
3508       is_signed = true;
3509       break;
3510     case "ldnt1w_z_p_ar_s_x32_unscaled"_h:
3511       msize = 2;
3512       break;
3513     default:
3514       VIXL_UNIMPLEMENTED();
3515   }
3516   addr.SetMsizeInBytesLog2(msize);
3517   SVEStructuredLoadHelper(kFormatVnS, pg, instr->GetRt(), addr, is_signed);
3518 }
3519 
Simulate_ZtS_Pg_ZnS_Xm(const Instruction * instr)3520 void Simulator::Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr) {
3521   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3522   SimVRegister& zn = ReadVRegister(instr->GetRn());
3523   uint64_t xm = ReadXRegister(instr->GetRm());
3524 
3525   LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3526   VIXL_ASSERT((form_hash_ == "stnt1b_z_p_ar_s_x32_unscaled"_h) ||
3527               (form_hash_ == "stnt1h_z_p_ar_s_x32_unscaled"_h) ||
3528               (form_hash_ == "stnt1w_z_p_ar_s_x32_unscaled"_h));
3529 
3530   addr.SetMsizeInBytesLog2(
3531       instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3532   SVEStructuredStoreHelper(kFormatVnS, pg, instr->GetRt(), addr);
3533 }
3534 
VisitReserved(const Instruction * instr)3535 void Simulator::VisitReserved(const Instruction* instr) {
3536   // UDF is the only instruction in this group, and the Decoder is precise here.
3537   VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
3538 
3539   printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
3540          reinterpret_cast<const void*>(instr),
3541          instr->GetInstructionBits());
3542   VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
3543 }
3544 
3545 
VisitUnimplemented(const Instruction * instr)3546 void Simulator::VisitUnimplemented(const Instruction* instr) {
3547   printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
3548          reinterpret_cast<const void*>(instr),
3549          instr->GetInstructionBits());
3550   VIXL_UNIMPLEMENTED();
3551 }
3552 
3553 
VisitUnallocated(const Instruction * instr)3554 void Simulator::VisitUnallocated(const Instruction* instr) {
3555   printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
3556          reinterpret_cast<const void*>(instr),
3557          instr->GetInstructionBits());
3558   VIXL_UNIMPLEMENTED();
3559 }
3560 
3561 
VisitPCRelAddressing(const Instruction * instr)3562 void Simulator::VisitPCRelAddressing(const Instruction* instr) {
3563   VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
3564               (instr->Mask(PCRelAddressingMask) == ADRP));
3565 
3566   WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
3567 }
3568 
3569 
VisitUnconditionalBranch(const Instruction * instr)3570 void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
3571   switch (instr->Mask(UnconditionalBranchMask)) {
3572     case BL:
3573       WriteLr(instr->GetNextInstruction());
3574       VIXL_FALLTHROUGH();
3575     case B:
3576       WritePc(instr->GetImmPCOffsetTarget());
3577       break;
3578     default:
3579       VIXL_UNREACHABLE();
3580   }
3581 }
3582 
3583 
VisitConditionalBranch(const Instruction * instr)3584 void Simulator::VisitConditionalBranch(const Instruction* instr) {
3585   VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
3586   if (ConditionPassed(instr->GetConditionBranch())) {
3587     WritePc(instr->GetImmPCOffsetTarget());
3588   }
3589 }
3590 
GetBTypeFromInstruction(const Instruction * instr) const3591 BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
3592   switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3593     case BLR:
3594     case BLRAA:
3595     case BLRAB:
3596     case BLRAAZ:
3597     case BLRABZ:
3598       return BranchAndLink;
3599     case BR:
3600     case BRAA:
3601     case BRAB:
3602     case BRAAZ:
3603     case BRABZ:
3604       if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
3605           !PcIsInGuardedPage()) {
3606         return BranchFromUnguardedOrToIP;
3607       }
3608       return BranchFromGuardedNotToIP;
3609   }
3610   return DefaultBType;
3611 }
3612 
VisitUnconditionalBranchToRegister(const Instruction * instr)3613 void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
3614   bool authenticate = false;
3615   bool link = false;
3616   uint64_t addr = ReadXRegister(instr->GetRn());
3617   uint64_t context = 0;
3618 
3619   switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3620     case BLR:
3621       link = true;
3622       VIXL_FALLTHROUGH();
3623     case BR:
3624     case RET:
3625       break;
3626 
3627     case BLRAAZ:
3628     case BLRABZ:
3629       link = true;
3630       VIXL_FALLTHROUGH();
3631     case BRAAZ:
3632     case BRABZ:
3633       authenticate = true;
3634       break;
3635 
3636     case BLRAA:
3637     case BLRAB:
3638       link = true;
3639       VIXL_FALLTHROUGH();
3640     case BRAA:
3641     case BRAB:
3642       authenticate = true;
3643       context = ReadXRegister(instr->GetRd());
3644       break;
3645 
3646     case RETAA:
3647     case RETAB:
3648       authenticate = true;
3649       addr = ReadXRegister(kLinkRegCode);
3650       context = ReadXRegister(31, Reg31IsStackPointer);
3651       break;
3652     default:
3653       VIXL_UNREACHABLE();
3654   }
3655 
3656   if (link) {
3657     WriteLr(instr->GetNextInstruction());
3658   }
3659 
3660   if (authenticate) {
3661     PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
3662     addr = AuthPAC(addr, context, key, kInstructionPointer);
3663 
3664     int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
3665     if (((addr >> error_lsb) & 0x3) != 0x0) {
3666       VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
3667     }
3668   }
3669 
3670   WritePc(Instruction::Cast(addr));
3671   WriteNextBType(GetBTypeFromInstruction(instr));
3672 }
3673 
3674 
VisitTestBranch(const Instruction * instr)3675 void Simulator::VisitTestBranch(const Instruction* instr) {
3676   unsigned bit_pos =
3677       (instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
3678   bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
3679   bool take_branch = false;
3680   switch (instr->Mask(TestBranchMask)) {
3681     case TBZ:
3682       take_branch = bit_zero;
3683       break;
3684     case TBNZ:
3685       take_branch = !bit_zero;
3686       break;
3687     default:
3688       VIXL_UNIMPLEMENTED();
3689   }
3690   if (take_branch) {
3691     WritePc(instr->GetImmPCOffsetTarget());
3692   }
3693 }
3694 
3695 
VisitCompareBranch(const Instruction * instr)3696 void Simulator::VisitCompareBranch(const Instruction* instr) {
3697   unsigned rt = instr->GetRt();
3698   bool take_branch = false;
3699   switch (instr->Mask(CompareBranchMask)) {
3700     case CBZ_w:
3701       take_branch = (ReadWRegister(rt) == 0);
3702       break;
3703     case CBZ_x:
3704       take_branch = (ReadXRegister(rt) == 0);
3705       break;
3706     case CBNZ_w:
3707       take_branch = (ReadWRegister(rt) != 0);
3708       break;
3709     case CBNZ_x:
3710       take_branch = (ReadXRegister(rt) != 0);
3711       break;
3712     default:
3713       VIXL_UNIMPLEMENTED();
3714   }
3715   if (take_branch) {
3716     WritePc(instr->GetImmPCOffsetTarget());
3717   }
3718 }
3719 
3720 
AddSubHelper(const Instruction * instr,int64_t op2)3721 void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
3722   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3723   bool set_flags = instr->GetFlagsUpdate();
3724   int64_t new_val = 0;
3725   Instr operation = instr->Mask(AddSubOpMask);
3726 
3727   switch (operation) {
3728     case ADD:
3729     case ADDS: {
3730       new_val = AddWithCarry(reg_size,
3731                              set_flags,
3732                              ReadRegister(reg_size,
3733                                           instr->GetRn(),
3734                                           instr->GetRnMode()),
3735                              op2);
3736       break;
3737     }
3738     case SUB:
3739     case SUBS: {
3740       new_val = AddWithCarry(reg_size,
3741                              set_flags,
3742                              ReadRegister(reg_size,
3743                                           instr->GetRn(),
3744                                           instr->GetRnMode()),
3745                              ~op2,
3746                              1);
3747       break;
3748     }
3749     default:
3750       VIXL_UNREACHABLE();
3751   }
3752 
3753   WriteRegister(reg_size,
3754                 instr->GetRd(),
3755                 new_val,
3756                 LogRegWrites,
3757                 instr->GetRdMode());
3758 }
3759 
3760 
VisitAddSubShifted(const Instruction * instr)3761 void Simulator::VisitAddSubShifted(const Instruction* instr) {
3762   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3763   int64_t op2 = ShiftOperand(reg_size,
3764                              ReadRegister(reg_size, instr->GetRm()),
3765                              static_cast<Shift>(instr->GetShiftDP()),
3766                              instr->GetImmDPShift());
3767   AddSubHelper(instr, op2);
3768 }
3769 
3770 
VisitAddSubImmediate(const Instruction * instr)3771 void Simulator::VisitAddSubImmediate(const Instruction* instr) {
3772   int64_t op2 = instr->GetImmAddSub()
3773                 << ((instr->GetImmAddSubShift() == 1) ? 12 : 0);
3774   AddSubHelper(instr, op2);
3775 }
3776 
3777 
VisitAddSubExtended(const Instruction * instr)3778 void Simulator::VisitAddSubExtended(const Instruction* instr) {
3779   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3780   int64_t op2 = ExtendValue(reg_size,
3781                             ReadRegister(reg_size, instr->GetRm()),
3782                             static_cast<Extend>(instr->GetExtendMode()),
3783                             instr->GetImmExtendShift());
3784   AddSubHelper(instr, op2);
3785 }
3786 
3787 
VisitAddSubWithCarry(const Instruction * instr)3788 void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
3789   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3790   int64_t op2 = ReadRegister(reg_size, instr->GetRm());
3791   int64_t new_val;
3792 
3793   if ((instr->Mask(AddSubOpMask) == SUB) ||
3794       (instr->Mask(AddSubOpMask) == SUBS)) {
3795     op2 = ~op2;
3796   }
3797 
3798   new_val = AddWithCarry(reg_size,
3799                          instr->GetFlagsUpdate(),
3800                          ReadRegister(reg_size, instr->GetRn()),
3801                          op2,
3802                          ReadC());
3803 
3804   WriteRegister(reg_size, instr->GetRd(), new_val);
3805 }
3806 
3807 
VisitRotateRightIntoFlags(const Instruction * instr)3808 void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
3809   switch (instr->Mask(RotateRightIntoFlagsMask)) {
3810     case RMIF: {
3811       uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
3812       unsigned shift = instr->GetImmRMIFRotation();
3813       unsigned mask = instr->GetNzcv();
3814       uint64_t rotated = RotateRight(value, shift, kXRegSize);
3815 
3816       ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
3817       break;
3818     }
3819   }
3820 }
3821 
3822 
VisitEvaluateIntoFlags(const Instruction * instr)3823 void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
3824   uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
3825   unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
3826 
3827   unsigned sign_bit = (value >> msb) & 1;
3828   unsigned overflow_bit = (value >> (msb + 1)) & 1;
3829   ReadNzcv().SetN(sign_bit);
3830   ReadNzcv().SetZ((value << (31 - msb)) == 0);
3831   ReadNzcv().SetV(sign_bit ^ overflow_bit);
3832 }
3833 
3834 
VisitLogicalShifted(const Instruction * instr)3835 void Simulator::VisitLogicalShifted(const Instruction* instr) {
3836   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3837   Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
3838   unsigned shift_amount = instr->GetImmDPShift();
3839   int64_t op2 = ShiftOperand(reg_size,
3840                              ReadRegister(reg_size, instr->GetRm()),
3841                              shift_type,
3842                              shift_amount);
3843   if (instr->Mask(NOT) == NOT) {
3844     op2 = ~op2;
3845   }
3846   LogicalHelper(instr, op2);
3847 }
3848 
3849 
VisitLogicalImmediate(const Instruction * instr)3850 void Simulator::VisitLogicalImmediate(const Instruction* instr) {
3851   if (instr->GetImmLogical() == 0) {
3852     VIXL_UNIMPLEMENTED();
3853   } else {
3854     LogicalHelper(instr, instr->GetImmLogical());
3855   }
3856 }
3857 
3858 
LogicalHelper(const Instruction * instr,int64_t op2)3859 void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
3860   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3861   int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3862   int64_t result = 0;
3863   bool update_flags = false;
3864 
3865   // Switch on the logical operation, stripping out the NOT bit, as it has a
3866   // different meaning for logical immediate instructions.
3867   switch (instr->Mask(LogicalOpMask & ~NOT)) {
3868     case ANDS:
3869       update_flags = true;
3870       VIXL_FALLTHROUGH();
3871     case AND:
3872       result = op1 & op2;
3873       break;
3874     case ORR:
3875       result = op1 | op2;
3876       break;
3877     case EOR:
3878       result = op1 ^ op2;
3879       break;
3880     default:
3881       VIXL_UNIMPLEMENTED();
3882   }
3883 
3884   if (update_flags) {
3885     ReadNzcv().SetN(CalcNFlag(result, reg_size));
3886     ReadNzcv().SetZ(CalcZFlag(result));
3887     ReadNzcv().SetC(0);
3888     ReadNzcv().SetV(0);
3889     LogSystemRegister(NZCV);
3890   }
3891 
3892   WriteRegister(reg_size,
3893                 instr->GetRd(),
3894                 result,
3895                 LogRegWrites,
3896                 instr->GetRdMode());
3897 }
3898 
3899 
VisitConditionalCompareRegister(const Instruction * instr)3900 void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
3901   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3902   ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
3903 }
3904 
3905 
VisitConditionalCompareImmediate(const Instruction * instr)3906 void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
3907   ConditionalCompareHelper(instr, instr->GetImmCondCmp());
3908 }
3909 
3910 
ConditionalCompareHelper(const Instruction * instr,int64_t op2)3911 void Simulator::ConditionalCompareHelper(const Instruction* instr,
3912                                          int64_t op2) {
3913   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3914   int64_t op1 = ReadRegister(reg_size, instr->GetRn());
3915 
3916   if (ConditionPassed(instr->GetCondition())) {
3917     // If the condition passes, set the status flags to the result of comparing
3918     // the operands.
3919     if (instr->Mask(ConditionalCompareMask) == CCMP) {
3920       AddWithCarry(reg_size, true, op1, ~op2, 1);
3921     } else {
3922       VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
3923       AddWithCarry(reg_size, true, op1, op2, 0);
3924     }
3925   } else {
3926     // If the condition fails, set the status flags to the nzcv immediate.
3927     ReadNzcv().SetFlags(instr->GetNzcv());
3928     LogSystemRegister(NZCV);
3929   }
3930 }
3931 
3932 
VisitLoadStoreUnsignedOffset(const Instruction * instr)3933 void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
3934   int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
3935   LoadStoreHelper(instr, offset, Offset);
3936 }
3937 
3938 
VisitLoadStoreUnscaledOffset(const Instruction * instr)3939 void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
3940   LoadStoreHelper(instr, instr->GetImmLS(), Offset);
3941 }
3942 
3943 
VisitLoadStorePreIndex(const Instruction * instr)3944 void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
3945   LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
3946 }
3947 
3948 
VisitLoadStorePostIndex(const Instruction * instr)3949 void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
3950   LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
3951 }
3952 
3953 
3954 template <typename T1, typename T2>
LoadAcquireRCpcUnscaledOffsetHelper(const Instruction * instr)3955 void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
3956   unsigned rt = instr->GetRt();
3957   unsigned rn = instr->GetRn();
3958 
3959   unsigned element_size = sizeof(T2);
3960   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3961   int offset = instr->GetImmLS();
3962   address += offset;
3963 
3964   // Verify that the address is available to the host.
3965   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3966 
3967   // Check the alignment of `address`.
3968   if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3969     VIXL_ALIGNMENT_EXCEPTION();
3970   }
3971 
3972   WriteRegister<T1>(rt, static_cast<T1>(MemRead<T2>(address)));
3973 
3974   // Approximate load-acquire by issuing a full barrier after the load.
3975   __sync_synchronize();
3976 
3977   LogRead(rt, GetPrintRegisterFormat(element_size), address);
3978 }
3979 
3980 
3981 template <typename T>
StoreReleaseUnscaledOffsetHelper(const Instruction * instr)3982 void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
3983   unsigned rt = instr->GetRt();
3984   unsigned rn = instr->GetRn();
3985 
3986   unsigned element_size = sizeof(T);
3987   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
3988   int offset = instr->GetImmLS();
3989   address += offset;
3990 
3991   // Verify that the address is available to the host.
3992   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
3993 
3994   // Check the alignment of `address`.
3995   if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
3996     VIXL_ALIGNMENT_EXCEPTION();
3997   }
3998 
3999   // Approximate store-release by issuing a full barrier after the load.
4000   __sync_synchronize();
4001 
4002   MemWrite<T>(address, ReadRegister<T>(rt));
4003 
4004   LogWrite(rt, GetPrintRegisterFormat(element_size), address);
4005 }
4006 
4007 
VisitLoadStoreRCpcUnscaledOffset(const Instruction * instr)4008 void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
4009   switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
4010     case LDAPURB:
4011       LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
4012       break;
4013     case LDAPURH:
4014       LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
4015       break;
4016     case LDAPUR_w:
4017       LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
4018       break;
4019     case LDAPUR_x:
4020       LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
4021       break;
4022     case LDAPURSB_w:
4023       LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
4024       break;
4025     case LDAPURSB_x:
4026       LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
4027       break;
4028     case LDAPURSH_w:
4029       LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
4030       break;
4031     case LDAPURSH_x:
4032       LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
4033       break;
4034     case LDAPURSW:
4035       LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
4036       break;
4037     case STLURB:
4038       StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
4039       break;
4040     case STLURH:
4041       StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
4042       break;
4043     case STLUR_w:
4044       StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
4045       break;
4046     case STLUR_x:
4047       StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
4048       break;
4049   }
4050 }
4051 
4052 
VisitLoadStorePAC(const Instruction * instr)4053 void Simulator::VisitLoadStorePAC(const Instruction* instr) {
4054   unsigned dst = instr->GetRt();
4055   unsigned addr_reg = instr->GetRn();
4056 
4057   uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
4058 
4059   PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
4060   address = AuthPAC(address, 0, key, kDataPointer);
4061 
4062   int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
4063   if (((address >> error_lsb) & 0x3) != 0x0) {
4064     VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
4065   }
4066 
4067 
4068   if ((addr_reg == 31) && ((address % 16) != 0)) {
4069     // When the base register is SP the stack pointer is required to be
4070     // quadword aligned prior to the address calculation and write-backs.
4071     // Misalignment will cause a stack alignment fault.
4072     VIXL_ALIGNMENT_EXCEPTION();
4073   }
4074 
4075   int64_t offset = instr->GetImmLSPAC();
4076   address += offset;
4077 
4078   if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
4079     // Pre-index mode.
4080     VIXL_ASSERT(offset != 0);
4081     WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
4082   }
4083 
4084   uintptr_t addr_ptr = static_cast<uintptr_t>(address);
4085 
4086   // Verify that the calculated address is available to the host.
4087   VIXL_ASSERT(address == addr_ptr);
4088 
4089   WriteXRegister(dst, MemRead<uint64_t>(addr_ptr), NoRegLog);
4090   unsigned access_size = 1 << 3;
4091   LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
4092 }
4093 
4094 
VisitLoadStoreRegisterOffset(const Instruction * instr)4095 void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
4096   Extend ext = static_cast<Extend>(instr->GetExtendMode());
4097   VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
4098   unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
4099 
4100   int64_t offset =
4101       ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
4102   LoadStoreHelper(instr, offset, Offset);
4103 }
4104 
4105 
LoadStoreHelper(const Instruction * instr,int64_t offset,AddrMode addrmode)4106 void Simulator::LoadStoreHelper(const Instruction* instr,
4107                                 int64_t offset,
4108                                 AddrMode addrmode) {
4109   unsigned srcdst = instr->GetRt();
4110   uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4111 
4112   bool rt_is_vreg = false;
4113   int extend_to_size = 0;
4114   LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
4115   switch (op) {
4116     case LDRB_w:
4117       WriteWRegister(srcdst, MemRead<uint8_t>(address), NoRegLog);
4118       extend_to_size = kWRegSizeInBytes;
4119       break;
4120     case LDRH_w:
4121       WriteWRegister(srcdst, MemRead<uint16_t>(address), NoRegLog);
4122       extend_to_size = kWRegSizeInBytes;
4123       break;
4124     case LDR_w:
4125       WriteWRegister(srcdst, MemRead<uint32_t>(address), NoRegLog);
4126       extend_to_size = kWRegSizeInBytes;
4127       break;
4128     case LDR_x:
4129       WriteXRegister(srcdst, MemRead<uint64_t>(address), NoRegLog);
4130       extend_to_size = kXRegSizeInBytes;
4131       break;
4132     case LDRSB_w:
4133       WriteWRegister(srcdst, MemRead<int8_t>(address), NoRegLog);
4134       extend_to_size = kWRegSizeInBytes;
4135       break;
4136     case LDRSH_w:
4137       WriteWRegister(srcdst, MemRead<int16_t>(address), NoRegLog);
4138       extend_to_size = kWRegSizeInBytes;
4139       break;
4140     case LDRSB_x:
4141       WriteXRegister(srcdst, MemRead<int8_t>(address), NoRegLog);
4142       extend_to_size = kXRegSizeInBytes;
4143       break;
4144     case LDRSH_x:
4145       WriteXRegister(srcdst, MemRead<int16_t>(address), NoRegLog);
4146       extend_to_size = kXRegSizeInBytes;
4147       break;
4148     case LDRSW_x:
4149       WriteXRegister(srcdst, MemRead<int32_t>(address), NoRegLog);
4150       extend_to_size = kXRegSizeInBytes;
4151       break;
4152     case LDR_b:
4153       WriteBRegister(srcdst, MemRead<uint8_t>(address), NoRegLog);
4154       rt_is_vreg = true;
4155       break;
4156     case LDR_h:
4157       WriteHRegister(srcdst, MemRead<uint16_t>(address), NoRegLog);
4158       rt_is_vreg = true;
4159       break;
4160     case LDR_s:
4161       WriteSRegister(srcdst, MemRead<float>(address), NoRegLog);
4162       rt_is_vreg = true;
4163       break;
4164     case LDR_d:
4165       WriteDRegister(srcdst, MemRead<double>(address), NoRegLog);
4166       rt_is_vreg = true;
4167       break;
4168     case LDR_q:
4169       WriteQRegister(srcdst, MemRead<qreg_t>(address), NoRegLog);
4170       rt_is_vreg = true;
4171       break;
4172 
4173     case STRB_w:
4174       MemWrite<uint8_t>(address, ReadWRegister(srcdst));
4175       break;
4176     case STRH_w:
4177       MemWrite<uint16_t>(address, ReadWRegister(srcdst));
4178       break;
4179     case STR_w:
4180       MemWrite<uint32_t>(address, ReadWRegister(srcdst));
4181       break;
4182     case STR_x:
4183       MemWrite<uint64_t>(address, ReadXRegister(srcdst));
4184       break;
4185     case STR_b:
4186       MemWrite<uint8_t>(address, ReadBRegister(srcdst));
4187       rt_is_vreg = true;
4188       break;
4189     case STR_h:
4190       MemWrite<uint16_t>(address, ReadHRegisterBits(srcdst));
4191       rt_is_vreg = true;
4192       break;
4193     case STR_s:
4194       MemWrite<float>(address, ReadSRegister(srcdst));
4195       rt_is_vreg = true;
4196       break;
4197     case STR_d:
4198       MemWrite<double>(address, ReadDRegister(srcdst));
4199       rt_is_vreg = true;
4200       break;
4201     case STR_q:
4202       MemWrite<qreg_t>(address, ReadQRegister(srcdst));
4203       rt_is_vreg = true;
4204       break;
4205 
4206     // Ignore prfm hint instructions.
4207     case PRFM:
4208       break;
4209 
4210     default:
4211       VIXL_UNIMPLEMENTED();
4212   }
4213 
4214   // Print a detailed trace (including the memory address).
4215   bool extend = (extend_to_size != 0);
4216   unsigned access_size = 1 << instr->GetSizeLS();
4217   unsigned result_size = extend ? extend_to_size : access_size;
4218   PrintRegisterFormat print_format =
4219       rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4220                  : GetPrintRegisterFormatForSize(result_size);
4221 
4222   if (instr->IsLoad()) {
4223     if (rt_is_vreg) {
4224       LogVRead(srcdst, print_format, address);
4225     } else {
4226       LogExtendingRead(srcdst, print_format, access_size, address);
4227     }
4228   } else if (instr->IsStore()) {
4229     if (rt_is_vreg) {
4230       LogVWrite(srcdst, print_format, address);
4231     } else {
4232       LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
4233     }
4234   } else {
4235     VIXL_ASSERT(op == PRFM);
4236   }
4237 
4238   local_monitor_.MaybeClear();
4239 }
4240 
4241 
VisitLoadStorePairOffset(const Instruction * instr)4242 void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
4243   LoadStorePairHelper(instr, Offset);
4244 }
4245 
4246 
VisitLoadStorePairPreIndex(const Instruction * instr)4247 void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
4248   LoadStorePairHelper(instr, PreIndex);
4249 }
4250 
4251 
VisitLoadStorePairPostIndex(const Instruction * instr)4252 void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
4253   LoadStorePairHelper(instr, PostIndex);
4254 }
4255 
4256 
VisitLoadStorePairNonTemporal(const Instruction * instr)4257 void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
4258   LoadStorePairHelper(instr, Offset);
4259 }
4260 
4261 
LoadStorePairHelper(const Instruction * instr,AddrMode addrmode)4262 void Simulator::LoadStorePairHelper(const Instruction* instr,
4263                                     AddrMode addrmode) {
4264   unsigned rt = instr->GetRt();
4265   unsigned rt2 = instr->GetRt2();
4266   int element_size = 1 << instr->GetSizeLSPair();
4267   int64_t offset = instr->GetImmLSPair() * element_size;
4268   uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4269   uintptr_t address2 = address + element_size;
4270 
4271   LoadStorePairOp op =
4272       static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
4273 
4274   // 'rt' and 'rt2' can only be aliased for stores.
4275   VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
4276 
4277   bool rt_is_vreg = false;
4278   bool sign_extend = false;
4279   switch (op) {
4280     // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
4281     // will print a more detailed log.
4282     case LDP_w: {
4283       WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
4284       WriteWRegister(rt2, MemRead<uint32_t>(address2), NoRegLog);
4285       break;
4286     }
4287     case LDP_s: {
4288       WriteSRegister(rt, MemRead<float>(address), NoRegLog);
4289       WriteSRegister(rt2, MemRead<float>(address2), NoRegLog);
4290       rt_is_vreg = true;
4291       break;
4292     }
4293     case LDP_x: {
4294       WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
4295       WriteXRegister(rt2, MemRead<uint64_t>(address2), NoRegLog);
4296       break;
4297     }
4298     case LDP_d: {
4299       WriteDRegister(rt, MemRead<double>(address), NoRegLog);
4300       WriteDRegister(rt2, MemRead<double>(address2), NoRegLog);
4301       rt_is_vreg = true;
4302       break;
4303     }
4304     case LDP_q: {
4305       WriteQRegister(rt, MemRead<qreg_t>(address), NoRegLog);
4306       WriteQRegister(rt2, MemRead<qreg_t>(address2), NoRegLog);
4307       rt_is_vreg = true;
4308       break;
4309     }
4310     case LDPSW_x: {
4311       WriteXRegister(rt, MemRead<int32_t>(address), NoRegLog);
4312       WriteXRegister(rt2, MemRead<int32_t>(address2), NoRegLog);
4313       sign_extend = true;
4314       break;
4315     }
4316     case STP_w: {
4317       MemWrite<uint32_t>(address, ReadWRegister(rt));
4318       MemWrite<uint32_t>(address2, ReadWRegister(rt2));
4319       break;
4320     }
4321     case STP_s: {
4322       MemWrite<float>(address, ReadSRegister(rt));
4323       MemWrite<float>(address2, ReadSRegister(rt2));
4324       rt_is_vreg = true;
4325       break;
4326     }
4327     case STP_x: {
4328       MemWrite<uint64_t>(address, ReadXRegister(rt));
4329       MemWrite<uint64_t>(address2, ReadXRegister(rt2));
4330       break;
4331     }
4332     case STP_d: {
4333       MemWrite<double>(address, ReadDRegister(rt));
4334       MemWrite<double>(address2, ReadDRegister(rt2));
4335       rt_is_vreg = true;
4336       break;
4337     }
4338     case STP_q: {
4339       MemWrite<qreg_t>(address, ReadQRegister(rt));
4340       MemWrite<qreg_t>(address2, ReadQRegister(rt2));
4341       rt_is_vreg = true;
4342       break;
4343     }
4344     default:
4345       VIXL_UNREACHABLE();
4346   }
4347 
4348   // Print a detailed trace (including the memory address).
4349   unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
4350   PrintRegisterFormat print_format =
4351       rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4352                  : GetPrintRegisterFormatForSize(result_size);
4353 
4354   if (instr->IsLoad()) {
4355     if (rt_is_vreg) {
4356       LogVRead(rt, print_format, address);
4357       LogVRead(rt2, print_format, address2);
4358     } else if (sign_extend) {
4359       LogExtendingRead(rt, print_format, element_size, address);
4360       LogExtendingRead(rt2, print_format, element_size, address2);
4361     } else {
4362       LogRead(rt, print_format, address);
4363       LogRead(rt2, print_format, address2);
4364     }
4365   } else {
4366     if (rt_is_vreg) {
4367       LogVWrite(rt, print_format, address);
4368       LogVWrite(rt2, print_format, address2);
4369     } else {
4370       LogWrite(rt, print_format, address);
4371       LogWrite(rt2, print_format, address2);
4372     }
4373   }
4374 
4375   local_monitor_.MaybeClear();
4376 }
4377 
4378 
4379 template <typename T>
CompareAndSwapHelper(const Instruction * instr)4380 void Simulator::CompareAndSwapHelper(const Instruction* instr) {
4381   unsigned rs = instr->GetRs();
4382   unsigned rt = instr->GetRt();
4383   unsigned rn = instr->GetRn();
4384 
4385   unsigned element_size = sizeof(T);
4386   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4387 
4388   CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4389 
4390   bool is_acquire = instr->ExtractBit(22) == 1;
4391   bool is_release = instr->ExtractBit(15) == 1;
4392 
4393   T comparevalue = ReadRegister<T>(rs);
4394   T newvalue = ReadRegister<T>(rt);
4395 
4396   // The architecture permits that the data read clears any exclusive monitors
4397   // associated with that location, even if the compare subsequently fails.
4398   local_monitor_.Clear();
4399 
4400   T data = MemRead<T>(address);
4401   if (is_acquire) {
4402     // Approximate load-acquire by issuing a full barrier after the load.
4403     __sync_synchronize();
4404   }
4405 
4406   if (data == comparevalue) {
4407     if (is_release) {
4408       // Approximate store-release by issuing a full barrier before the store.
4409       __sync_synchronize();
4410     }
4411     MemWrite<T>(address, newvalue);
4412     LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
4413   }
4414   WriteRegister<T>(rs, data, NoRegLog);
4415   LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
4416 }
4417 
4418 
4419 template <typename T>
CompareAndSwapPairHelper(const Instruction * instr)4420 void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
4421   VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
4422   unsigned rs = instr->GetRs();
4423   unsigned rt = instr->GetRt();
4424   unsigned rn = instr->GetRn();
4425 
4426   VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
4427 
4428   unsigned element_size = sizeof(T);
4429   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4430 
4431   CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
4432 
4433   uint64_t address2 = address + element_size;
4434 
4435   bool is_acquire = instr->ExtractBit(22) == 1;
4436   bool is_release = instr->ExtractBit(15) == 1;
4437 
4438   T comparevalue_high = ReadRegister<T>(rs + 1);
4439   T comparevalue_low = ReadRegister<T>(rs);
4440   T newvalue_high = ReadRegister<T>(rt + 1);
4441   T newvalue_low = ReadRegister<T>(rt);
4442 
4443   // The architecture permits that the data read clears any exclusive monitors
4444   // associated with that location, even if the compare subsequently fails.
4445   local_monitor_.Clear();
4446 
4447   T data_low = MemRead<T>(address);
4448   T data_high = MemRead<T>(address2);
4449 
4450   if (is_acquire) {
4451     // Approximate load-acquire by issuing a full barrier after the load.
4452     __sync_synchronize();
4453   }
4454 
4455   bool same =
4456       (data_high == comparevalue_high) && (data_low == comparevalue_low);
4457   if (same) {
4458     if (is_release) {
4459       // Approximate store-release by issuing a full barrier before the store.
4460       __sync_synchronize();
4461     }
4462 
4463     MemWrite<T>(address, newvalue_low);
4464     MemWrite<T>(address2, newvalue_high);
4465   }
4466 
4467   WriteRegister<T>(rs + 1, data_high, NoRegLog);
4468   WriteRegister<T>(rs, data_low, NoRegLog);
4469 
4470   PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4471   LogRead(rs, format, address);
4472   LogRead(rs + 1, format, address2);
4473 
4474   if (same) {
4475     LogWrite(rt, format, address);
4476     LogWrite(rt + 1, format, address2);
4477   }
4478 }
4479 
CanReadMemory(uintptr_t address,size_t size)4480 bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
4481   // To simulate fault-tolerant loads, we need to know what host addresses we
4482   // can access without generating a real fault. One way to do that is to
4483   // attempt to `write()` the memory to a placeholder pipe[1]. This is more
4484   // portable and less intrusive than using (global) signal handlers.
4485   //
4486   // [1]: https://stackoverflow.com/questions/7134590
4487 
4488   size_t written = 0;
4489   bool can_read = true;
4490   // `write` will normally return after one invocation, but it is allowed to
4491   // handle only part of the operation, so wrap it in a loop.
4492   while (can_read && (written < size)) {
4493     ssize_t result = write(placeholder_pipe_fd_[1],
4494                            reinterpret_cast<void*>(address + written),
4495                            size - written);
4496     if (result > 0) {
4497       written += result;
4498     } else {
4499       switch (result) {
4500         case -EPERM:
4501         case -EFAULT:
4502           // The address range is not accessible.
4503           // `write` is supposed to return -EFAULT in this case, but in practice
4504           // it seems to return -EPERM, so we accept that too.
4505           can_read = false;
4506           break;
4507         case -EINTR:
4508           // The call was interrupted by a signal. Just try again.
4509           break;
4510         default:
4511           // Any other error is fatal.
4512           VIXL_ABORT();
4513       }
4514     }
4515   }
4516   // Drain the read side of the pipe. If we don't do this, we'll leak memory as
4517   // the placeholder data is buffered. As before, we expect to drain the whole
4518   // write in one invocation, but cannot guarantee that, so we wrap it in a
4519   // loop. This function is primarily intended to implement SVE fault-tolerant
4520   // loads, so the maximum Z register size is a good default buffer size.
4521   char buffer[kZRegMaxSizeInBytes];
4522   while (written > 0) {
4523     ssize_t result = read(placeholder_pipe_fd_[0],
4524                           reinterpret_cast<void*>(buffer),
4525                           sizeof(buffer));
4526     // `read` blocks, and returns 0 only at EOF. We should not hit EOF until
4527     // we've read everything that was written, so treat 0 as an error.
4528     if (result > 0) {
4529       VIXL_ASSERT(static_cast<size_t>(result) <= written);
4530       written -= result;
4531     } else {
4532       // For -EINTR, just try again. We can't handle any other error.
4533       VIXL_CHECK(result == -EINTR);
4534     }
4535   }
4536 
4537   return can_read;
4538 }
4539 
PrintExclusiveAccessWarning()4540 void Simulator::PrintExclusiveAccessWarning() {
4541   if (print_exclusive_access_warning_) {
4542     fprintf(stderr,
4543             "%sWARNING:%s VIXL simulator support for "
4544             "load-/store-/clear-exclusive "
4545             "instructions is limited. Refer to the README for details.%s\n",
4546             clr_warning,
4547             clr_warning_message,
4548             clr_normal);
4549     print_exclusive_access_warning_ = false;
4550   }
4551 }
4552 
VisitLoadStoreExclusive(const Instruction * instr)4553 void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
4554   LoadStoreExclusive op =
4555       static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
4556 
4557   switch (op) {
4558     case CAS_w:
4559     case CASA_w:
4560     case CASL_w:
4561     case CASAL_w:
4562       CompareAndSwapHelper<uint32_t>(instr);
4563       break;
4564     case CAS_x:
4565     case CASA_x:
4566     case CASL_x:
4567     case CASAL_x:
4568       CompareAndSwapHelper<uint64_t>(instr);
4569       break;
4570     case CASB:
4571     case CASAB:
4572     case CASLB:
4573     case CASALB:
4574       CompareAndSwapHelper<uint8_t>(instr);
4575       break;
4576     case CASH:
4577     case CASAH:
4578     case CASLH:
4579     case CASALH:
4580       CompareAndSwapHelper<uint16_t>(instr);
4581       break;
4582     case CASP_w:
4583     case CASPA_w:
4584     case CASPL_w:
4585     case CASPAL_w:
4586       CompareAndSwapPairHelper<uint32_t>(instr);
4587       break;
4588     case CASP_x:
4589     case CASPA_x:
4590     case CASPL_x:
4591     case CASPAL_x:
4592       CompareAndSwapPairHelper<uint64_t>(instr);
4593       break;
4594     default:
4595       PrintExclusiveAccessWarning();
4596 
4597       unsigned rs = instr->GetRs();
4598       unsigned rt = instr->GetRt();
4599       unsigned rt2 = instr->GetRt2();
4600       unsigned rn = instr->GetRn();
4601 
4602       bool is_exclusive = !instr->GetLdStXNotExclusive();
4603       bool is_acquire_release =
4604           !is_exclusive || instr->GetLdStXAcquireRelease();
4605       bool is_load = instr->GetLdStXLoad();
4606       bool is_pair = instr->GetLdStXPair();
4607 
4608       unsigned element_size = 1 << instr->GetLdStXSizeLog2();
4609       unsigned access_size = is_pair ? element_size * 2 : element_size;
4610       uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4611 
4612       CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
4613 
4614       if (is_load) {
4615         if (is_exclusive) {
4616           local_monitor_.MarkExclusive(address, access_size);
4617         } else {
4618           // Any non-exclusive load can clear the local monitor as a side
4619           // effect. We don't need to do this, but it is useful to stress the
4620           // simulated code.
4621           local_monitor_.Clear();
4622         }
4623 
4624         // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
4625         // We will print a more detailed log.
4626         unsigned reg_size = 0;
4627         switch (op) {
4628           case LDXRB_w:
4629           case LDAXRB_w:
4630           case LDARB_w:
4631           case LDLARB:
4632             WriteWRegister(rt, MemRead<uint8_t>(address), NoRegLog);
4633             reg_size = kWRegSizeInBytes;
4634             break;
4635           case LDXRH_w:
4636           case LDAXRH_w:
4637           case LDARH_w:
4638           case LDLARH:
4639             WriteWRegister(rt, MemRead<uint16_t>(address), NoRegLog);
4640             reg_size = kWRegSizeInBytes;
4641             break;
4642           case LDXR_w:
4643           case LDAXR_w:
4644           case LDAR_w:
4645           case LDLAR_w:
4646             WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
4647             reg_size = kWRegSizeInBytes;
4648             break;
4649           case LDXR_x:
4650           case LDAXR_x:
4651           case LDAR_x:
4652           case LDLAR_x:
4653             WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
4654             reg_size = kXRegSizeInBytes;
4655             break;
4656           case LDXP_w:
4657           case LDAXP_w:
4658             WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
4659             WriteWRegister(rt2,
4660                            MemRead<uint32_t>(address + element_size),
4661                            NoRegLog);
4662             reg_size = kWRegSizeInBytes;
4663             break;
4664           case LDXP_x:
4665           case LDAXP_x:
4666             WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
4667             WriteXRegister(rt2,
4668                            MemRead<uint64_t>(address + element_size),
4669                            NoRegLog);
4670             reg_size = kXRegSizeInBytes;
4671             break;
4672           default:
4673             VIXL_UNREACHABLE();
4674         }
4675 
4676         if (is_acquire_release) {
4677           // Approximate load-acquire by issuing a full barrier after the load.
4678           __sync_synchronize();
4679         }
4680 
4681         PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
4682         LogExtendingRead(rt, format, element_size, address);
4683         if (is_pair) {
4684           LogExtendingRead(rt2, format, element_size, address + element_size);
4685         }
4686       } else {
4687         if (is_acquire_release) {
4688           // Approximate store-release by issuing a full barrier before the
4689           // store.
4690           __sync_synchronize();
4691         }
4692 
4693         bool do_store = true;
4694         if (is_exclusive) {
4695           do_store = local_monitor_.IsExclusive(address, access_size) &&
4696                      global_monitor_.IsExclusive(address, access_size);
4697           WriteWRegister(rs, do_store ? 0 : 1);
4698 
4699           //  - All exclusive stores explicitly clear the local monitor.
4700           local_monitor_.Clear();
4701         } else {
4702           //  - Any other store can clear the local monitor as a side effect.
4703           local_monitor_.MaybeClear();
4704         }
4705 
4706         if (do_store) {
4707           switch (op) {
4708             case STXRB_w:
4709             case STLXRB_w:
4710             case STLRB_w:
4711             case STLLRB:
4712               MemWrite<uint8_t>(address, ReadWRegister(rt));
4713               break;
4714             case STXRH_w:
4715             case STLXRH_w:
4716             case STLRH_w:
4717             case STLLRH:
4718               MemWrite<uint16_t>(address, ReadWRegister(rt));
4719               break;
4720             case STXR_w:
4721             case STLXR_w:
4722             case STLR_w:
4723             case STLLR_w:
4724               MemWrite<uint32_t>(address, ReadWRegister(rt));
4725               break;
4726             case STXR_x:
4727             case STLXR_x:
4728             case STLR_x:
4729             case STLLR_x:
4730               MemWrite<uint64_t>(address, ReadXRegister(rt));
4731               break;
4732             case STXP_w:
4733             case STLXP_w:
4734               MemWrite<uint32_t>(address, ReadWRegister(rt));
4735               MemWrite<uint32_t>(address + element_size, ReadWRegister(rt2));
4736               break;
4737             case STXP_x:
4738             case STLXP_x:
4739               MemWrite<uint64_t>(address, ReadXRegister(rt));
4740               MemWrite<uint64_t>(address + element_size, ReadXRegister(rt2));
4741               break;
4742             default:
4743               VIXL_UNREACHABLE();
4744           }
4745 
4746           PrintRegisterFormat format =
4747               GetPrintRegisterFormatForSize(element_size);
4748           LogWrite(rt, format, address);
4749           if (is_pair) {
4750             LogWrite(rt2, format, address + element_size);
4751           }
4752         }
4753       }
4754   }
4755 }
4756 
4757 template <typename T>
AtomicMemorySimpleHelper(const Instruction * instr)4758 void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
4759   unsigned rs = instr->GetRs();
4760   unsigned rt = instr->GetRt();
4761   unsigned rn = instr->GetRn();
4762 
4763   bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4764   bool is_release = instr->ExtractBit(22) == 1;
4765 
4766   unsigned element_size = sizeof(T);
4767   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4768 
4769   CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4770 
4771   T value = ReadRegister<T>(rs);
4772 
4773   T data = MemRead<T>(address);
4774 
4775   if (is_acquire) {
4776     // Approximate load-acquire by issuing a full barrier after the load.
4777     __sync_synchronize();
4778   }
4779 
4780   T result = 0;
4781   switch (instr->Mask(AtomicMemorySimpleOpMask)) {
4782     case LDADDOp:
4783       result = data + value;
4784       break;
4785     case LDCLROp:
4786       VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4787       result = data & ~value;
4788       break;
4789     case LDEOROp:
4790       VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4791       result = data ^ value;
4792       break;
4793     case LDSETOp:
4794       VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
4795       result = data | value;
4796       break;
4797 
4798     // Signed/Unsigned difference is done via the templated type T.
4799     case LDSMAXOp:
4800     case LDUMAXOp:
4801       result = (data > value) ? data : value;
4802       break;
4803     case LDSMINOp:
4804     case LDUMINOp:
4805       result = (data > value) ? value : data;
4806       break;
4807   }
4808 
4809   if (is_release) {
4810     // Approximate store-release by issuing a full barrier before the store.
4811     __sync_synchronize();
4812   }
4813 
4814   WriteRegister<T>(rt, data, NoRegLog);
4815 
4816   unsigned register_size = element_size;
4817   if (element_size < kXRegSizeInBytes) {
4818     register_size = kWRegSizeInBytes;
4819   }
4820   PrintRegisterFormat format = GetPrintRegisterFormatForSize(register_size);
4821   LogExtendingRead(rt, format, element_size, address);
4822 
4823   MemWrite<T>(address, result);
4824   format = GetPrintRegisterFormatForSize(element_size);
4825   LogWrite(rs, format, address);
4826 }
4827 
4828 template <typename T>
AtomicMemorySwapHelper(const Instruction * instr)4829 void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
4830   unsigned rs = instr->GetRs();
4831   unsigned rt = instr->GetRt();
4832   unsigned rn = instr->GetRn();
4833 
4834   bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
4835   bool is_release = instr->ExtractBit(22) == 1;
4836 
4837   unsigned element_size = sizeof(T);
4838   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4839 
4840   CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4841 
4842   T data = MemRead<T>(address);
4843   if (is_acquire) {
4844     // Approximate load-acquire by issuing a full barrier after the load.
4845     __sync_synchronize();
4846   }
4847 
4848   if (is_release) {
4849     // Approximate store-release by issuing a full barrier before the store.
4850     __sync_synchronize();
4851   }
4852   MemWrite<T>(address, ReadRegister<T>(rs));
4853 
4854   WriteRegister<T>(rt, data);
4855 
4856   PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4857   LogRead(rt, format, address);
4858   LogWrite(rs, format, address);
4859 }
4860 
4861 template <typename T>
LoadAcquireRCpcHelper(const Instruction * instr)4862 void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
4863   unsigned rt = instr->GetRt();
4864   unsigned rn = instr->GetRn();
4865 
4866   unsigned element_size = sizeof(T);
4867   uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4868 
4869   CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4870 
4871   WriteRegister<T>(rt, MemRead<T>(address));
4872 
4873   // Approximate load-acquire by issuing a full barrier after the load.
4874   __sync_synchronize();
4875 
4876   LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
4877 }
4878 
4879 #define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
4880   V(LDADD)                                \
4881   V(LDCLR)                                \
4882   V(LDEOR)                                \
4883   V(LDSET)                                \
4884   V(LDUMAX)                               \
4885   V(LDUMIN)
4886 
4887 #define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
4888   V(LDSMAX)                              \
4889   V(LDSMIN)
4890 
VisitAtomicMemory(const Instruction * instr)4891 void Simulator::VisitAtomicMemory(const Instruction* instr) {
4892   switch (instr->Mask(AtomicMemoryMask)) {
4893 // clang-format off
4894 #define SIM_FUNC_B(A) \
4895     case A##B:        \
4896     case A##AB:       \
4897     case A##LB:       \
4898     case A##ALB:
4899 #define SIM_FUNC_H(A) \
4900     case A##H:        \
4901     case A##AH:       \
4902     case A##LH:       \
4903     case A##ALH:
4904 #define SIM_FUNC_w(A) \
4905     case A##_w:       \
4906     case A##A_w:      \
4907     case A##L_w:      \
4908     case A##AL_w:
4909 #define SIM_FUNC_x(A) \
4910     case A##_x:       \
4911     case A##A_x:      \
4912     case A##L_x:      \
4913     case A##AL_x:
4914 
4915     ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
4916       AtomicMemorySimpleHelper<uint8_t>(instr);
4917       break;
4918     ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
4919       AtomicMemorySimpleHelper<int8_t>(instr);
4920       break;
4921     ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
4922       AtomicMemorySimpleHelper<uint16_t>(instr);
4923       break;
4924     ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
4925       AtomicMemorySimpleHelper<int16_t>(instr);
4926       break;
4927     ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
4928       AtomicMemorySimpleHelper<uint32_t>(instr);
4929       break;
4930     ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
4931       AtomicMemorySimpleHelper<int32_t>(instr);
4932       break;
4933     ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
4934       AtomicMemorySimpleHelper<uint64_t>(instr);
4935       break;
4936     ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
4937       AtomicMemorySimpleHelper<int64_t>(instr);
4938       break;
4939     // clang-format on
4940 
4941     case SWPB:
4942     case SWPAB:
4943     case SWPLB:
4944     case SWPALB:
4945       AtomicMemorySwapHelper<uint8_t>(instr);
4946       break;
4947     case SWPH:
4948     case SWPAH:
4949     case SWPLH:
4950     case SWPALH:
4951       AtomicMemorySwapHelper<uint16_t>(instr);
4952       break;
4953     case SWP_w:
4954     case SWPA_w:
4955     case SWPL_w:
4956     case SWPAL_w:
4957       AtomicMemorySwapHelper<uint32_t>(instr);
4958       break;
4959     case SWP_x:
4960     case SWPA_x:
4961     case SWPL_x:
4962     case SWPAL_x:
4963       AtomicMemorySwapHelper<uint64_t>(instr);
4964       break;
4965     case LDAPRB:
4966       LoadAcquireRCpcHelper<uint8_t>(instr);
4967       break;
4968     case LDAPRH:
4969       LoadAcquireRCpcHelper<uint16_t>(instr);
4970       break;
4971     case LDAPR_w:
4972       LoadAcquireRCpcHelper<uint32_t>(instr);
4973       break;
4974     case LDAPR_x:
4975       LoadAcquireRCpcHelper<uint64_t>(instr);
4976       break;
4977   }
4978 }
4979 
4980 
VisitLoadLiteral(const Instruction * instr)4981 void Simulator::VisitLoadLiteral(const Instruction* instr) {
4982   unsigned rt = instr->GetRt();
4983   uint64_t address = instr->GetLiteralAddress<uint64_t>();
4984 
4985   // Verify that the calculated address is available to the host.
4986   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4987 
4988   switch (instr->Mask(LoadLiteralMask)) {
4989     // Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
4990     // print a more detailed log.
4991     case LDR_w_lit:
4992       WriteWRegister(rt, MemRead<uint32_t>(address), NoRegLog);
4993       LogRead(rt, kPrintWReg, address);
4994       break;
4995     case LDR_x_lit:
4996       WriteXRegister(rt, MemRead<uint64_t>(address), NoRegLog);
4997       LogRead(rt, kPrintXReg, address);
4998       break;
4999     case LDR_s_lit:
5000       WriteSRegister(rt, MemRead<float>(address), NoRegLog);
5001       LogVRead(rt, kPrintSRegFP, address);
5002       break;
5003     case LDR_d_lit:
5004       WriteDRegister(rt, MemRead<double>(address), NoRegLog);
5005       LogVRead(rt, kPrintDRegFP, address);
5006       break;
5007     case LDR_q_lit:
5008       WriteQRegister(rt, MemRead<qreg_t>(address), NoRegLog);
5009       LogVRead(rt, kPrintReg1Q, address);
5010       break;
5011     case LDRSW_x_lit:
5012       WriteXRegister(rt, MemRead<int32_t>(address), NoRegLog);
5013       LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
5014       break;
5015 
5016     // Ignore prfm hint instructions.
5017     case PRFM_lit:
5018       break;
5019 
5020     default:
5021       VIXL_UNREACHABLE();
5022   }
5023 
5024   local_monitor_.MaybeClear();
5025 }
5026 
5027 
AddressModeHelper(unsigned addr_reg,int64_t offset,AddrMode addrmode)5028 uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
5029                                        int64_t offset,
5030                                        AddrMode addrmode) {
5031   uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
5032 
5033   if ((addr_reg == 31) && ((address % 16) != 0)) {
5034     // When the base register is SP the stack pointer is required to be
5035     // quadword aligned prior to the address calculation and write-backs.
5036     // Misalignment will cause a stack alignment fault.
5037     VIXL_ALIGNMENT_EXCEPTION();
5038   }
5039 
5040   if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
5041     VIXL_ASSERT(offset != 0);
5042     // Only preindex should log the register update here. For Postindex, the
5043     // update will be printed automatically by LogWrittenRegisters _after_ the
5044     // memory access itself is logged.
5045     RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
5046     WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
5047   }
5048 
5049   if ((addrmode == Offset) || (addrmode == PreIndex)) {
5050     address += offset;
5051   }
5052 
5053   // Verify that the calculated address is available to the host.
5054   VIXL_ASSERT(address == static_cast<uintptr_t>(address));
5055 
5056   return static_cast<uintptr_t>(address);
5057 }
5058 
5059 
VisitMoveWideImmediate(const Instruction * instr)5060 void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
5061   MoveWideImmediateOp mov_op =
5062       static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
5063   int64_t new_xn_val = 0;
5064 
5065   bool is_64_bits = instr->GetSixtyFourBits() == 1;
5066   // Shift is limited for W operations.
5067   VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
5068 
5069   // Get the shifted immediate.
5070   int64_t shift = instr->GetShiftMoveWide() * 16;
5071   int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
5072                           << shift;
5073 
5074   // Compute the new value.
5075   switch (mov_op) {
5076     case MOVN_w:
5077     case MOVN_x: {
5078       new_xn_val = ~shifted_imm16;
5079       if (!is_64_bits) new_xn_val &= kWRegMask;
5080       break;
5081     }
5082     case MOVK_w:
5083     case MOVK_x: {
5084       unsigned reg_code = instr->GetRd();
5085       int64_t prev_xn_val =
5086           is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
5087       new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
5088       break;
5089     }
5090     case MOVZ_w:
5091     case MOVZ_x: {
5092       new_xn_val = shifted_imm16;
5093       break;
5094     }
5095     default:
5096       VIXL_UNREACHABLE();
5097   }
5098 
5099   // Update the destination register.
5100   WriteXRegister(instr->GetRd(), new_xn_val);
5101 }
5102 
5103 
VisitConditionalSelect(const Instruction * instr)5104 void Simulator::VisitConditionalSelect(const Instruction* instr) {
5105   uint64_t new_val = ReadXRegister(instr->GetRn());
5106 
5107   if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
5108     new_val = ReadXRegister(instr->GetRm());
5109     switch (instr->Mask(ConditionalSelectMask)) {
5110       case CSEL_w:
5111       case CSEL_x:
5112         break;
5113       case CSINC_w:
5114       case CSINC_x:
5115         new_val++;
5116         break;
5117       case CSINV_w:
5118       case CSINV_x:
5119         new_val = ~new_val;
5120         break;
5121       case CSNEG_w:
5122       case CSNEG_x:
5123         new_val = -new_val;
5124         break;
5125       default:
5126         VIXL_UNIMPLEMENTED();
5127     }
5128   }
5129   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5130   WriteRegister(reg_size, instr->GetRd(), new_val);
5131 }
5132 
5133 
5134 #define PAUTH_MODES_REGISTER_CONTEXT(V) \
5135   V(IA, kPACKeyIA, kInstructionPointer) \
5136   V(IB, kPACKeyIB, kInstructionPointer) \
5137   V(DA, kPACKeyDA, kDataPointer)        \
5138   V(DB, kPACKeyDB, kDataPointer)
5139 
5140 #define PAUTH_MODES_ZERO_CONTEXT(V)      \
5141   V(IZA, kPACKeyIA, kInstructionPointer) \
5142   V(IZB, kPACKeyIB, kInstructionPointer) \
5143   V(DZA, kPACKeyDA, kDataPointer)        \
5144   V(DZB, kPACKeyDB, kDataPointer)
5145 
VisitDataProcessing1Source(const Instruction * instr)5146 void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
5147   unsigned dst = instr->GetRd();
5148   unsigned src = instr->GetRn();
5149 
5150   switch (instr->Mask(DataProcessing1SourceMask)) {
5151 #define DEFINE_PAUTH_FUNCS(SUFFIX, KEY, D)          \
5152   case PAC##SUFFIX: {                               \
5153     uint64_t mod = ReadXRegister(src);              \
5154     uint64_t ptr = ReadXRegister(dst);              \
5155     WriteXRegister(dst, AddPAC(ptr, mod, KEY, D));  \
5156     break;                                          \
5157   }                                                 \
5158   case AUT##SUFFIX: {                               \
5159     uint64_t mod = ReadXRegister(src);              \
5160     uint64_t ptr = ReadXRegister(dst);              \
5161     WriteXRegister(dst, AuthPAC(ptr, mod, KEY, D)); \
5162     break;                                          \
5163   }
5164 
5165     PAUTH_MODES_REGISTER_CONTEXT(DEFINE_PAUTH_FUNCS)
5166 #undef DEFINE_PAUTH_FUNCS
5167 
5168 #define DEFINE_PAUTH_FUNCS(SUFFIX, KEY, D)          \
5169   case PAC##SUFFIX: {                               \
5170     if (src != kZeroRegCode) {                      \
5171       VIXL_UNIMPLEMENTED();                         \
5172     }                                               \
5173     uint64_t ptr = ReadXRegister(dst);              \
5174     WriteXRegister(dst, AddPAC(ptr, 0x0, KEY, D));  \
5175     break;                                          \
5176   }                                                 \
5177   case AUT##SUFFIX: {                               \
5178     if (src != kZeroRegCode) {                      \
5179       VIXL_UNIMPLEMENTED();                         \
5180     }                                               \
5181     uint64_t ptr = ReadXRegister(dst);              \
5182     WriteXRegister(dst, AuthPAC(ptr, 0x0, KEY, D)); \
5183     break;                                          \
5184   }
5185 
5186     PAUTH_MODES_ZERO_CONTEXT(DEFINE_PAUTH_FUNCS)
5187 #undef DEFINE_PAUTH_FUNCS
5188 
5189     case XPACI:
5190       if (src != kZeroRegCode) {
5191         VIXL_UNIMPLEMENTED();
5192       }
5193       WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
5194       break;
5195     case XPACD:
5196       if (src != kZeroRegCode) {
5197         VIXL_UNIMPLEMENTED();
5198       }
5199       WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
5200       break;
5201     case RBIT_w:
5202       WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
5203       break;
5204     case RBIT_x:
5205       WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
5206       break;
5207     case REV16_w:
5208       WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
5209       break;
5210     case REV16_x:
5211       WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
5212       break;
5213     case REV_w:
5214       WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
5215       break;
5216     case REV32_x:
5217       WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
5218       break;
5219     case REV_x:
5220       WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
5221       break;
5222     case CLZ_w:
5223       WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
5224       break;
5225     case CLZ_x:
5226       WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
5227       break;
5228     case CLS_w:
5229       WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
5230       break;
5231     case CLS_x:
5232       WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
5233       break;
5234     default:
5235       VIXL_UNIMPLEMENTED();
5236   }
5237 }
5238 
5239 
Poly32Mod2(unsigned n,uint64_t data,uint32_t poly)5240 uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
5241   VIXL_ASSERT((n > 32) && (n <= 64));
5242   for (unsigned i = (n - 1); i >= 32; i--) {
5243     if (((data >> i) & 1) != 0) {
5244       uint64_t polysh32 = (uint64_t)poly << (i - 32);
5245       uint64_t mask = (UINT64_C(1) << i) - 1;
5246       data = ((data & mask) ^ polysh32);
5247     }
5248   }
5249   return data & 0xffffffff;
5250 }
5251 
5252 
5253 template <typename T>
Crc32Checksum(uint32_t acc,T val,uint32_t poly)5254 uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
5255   unsigned size = sizeof(val) * 8;  // Number of bits in type T.
5256   VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
5257   uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
5258   uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
5259   return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
5260 }
5261 
5262 
Crc32Checksum(uint32_t acc,uint64_t val,uint32_t poly)5263 uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
5264   // Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
5265   // the CRC of each 32-bit word sequentially.
5266   acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
5267   return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
5268 }
5269 
5270 
VisitDataProcessing2Source(const Instruction * instr)5271 void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
5272   Shift shift_op = NO_SHIFT;
5273   int64_t result = 0;
5274   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5275 
5276   switch (instr->Mask(DataProcessing2SourceMask)) {
5277     case SDIV_w: {
5278       int32_t rn = ReadWRegister(instr->GetRn());
5279       int32_t rm = ReadWRegister(instr->GetRm());
5280       if ((rn == kWMinInt) && (rm == -1)) {
5281         result = kWMinInt;
5282       } else if (rm == 0) {
5283         // Division by zero can be trapped, but not on A-class processors.
5284         result = 0;
5285       } else {
5286         result = rn / rm;
5287       }
5288       break;
5289     }
5290     case SDIV_x: {
5291       int64_t rn = ReadXRegister(instr->GetRn());
5292       int64_t rm = ReadXRegister(instr->GetRm());
5293       if ((rn == kXMinInt) && (rm == -1)) {
5294         result = kXMinInt;
5295       } else if (rm == 0) {
5296         // Division by zero can be trapped, but not on A-class processors.
5297         result = 0;
5298       } else {
5299         result = rn / rm;
5300       }
5301       break;
5302     }
5303     case UDIV_w: {
5304       uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
5305       uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
5306       if (rm == 0) {
5307         // Division by zero can be trapped, but not on A-class processors.
5308         result = 0;
5309       } else {
5310         result = rn / rm;
5311       }
5312       break;
5313     }
5314     case UDIV_x: {
5315       uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5316       uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
5317       if (rm == 0) {
5318         // Division by zero can be trapped, but not on A-class processors.
5319         result = 0;
5320       } else {
5321         result = rn / rm;
5322       }
5323       break;
5324     }
5325     case LSLV_w:
5326     case LSLV_x:
5327       shift_op = LSL;
5328       break;
5329     case LSRV_w:
5330     case LSRV_x:
5331       shift_op = LSR;
5332       break;
5333     case ASRV_w:
5334     case ASRV_x:
5335       shift_op = ASR;
5336       break;
5337     case RORV_w:
5338     case RORV_x:
5339       shift_op = ROR;
5340       break;
5341     case PACGA: {
5342       uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5343       uint64_t src = static_cast<uint64_t>(
5344           ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
5345       uint64_t code = ComputePAC(dst, src, kPACKeyGA);
5346       result = code & 0xffffffff00000000;
5347       break;
5348     }
5349     case CRC32B: {
5350       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5351       uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5352       result = Crc32Checksum(acc, val, CRC32_POLY);
5353       break;
5354     }
5355     case CRC32H: {
5356       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5357       uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5358       result = Crc32Checksum(acc, val, CRC32_POLY);
5359       break;
5360     }
5361     case CRC32W: {
5362       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5363       uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5364       result = Crc32Checksum(acc, val, CRC32_POLY);
5365       break;
5366     }
5367     case CRC32X: {
5368       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5369       uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5370       result = Crc32Checksum(acc, val, CRC32_POLY);
5371       reg_size = kWRegSize;
5372       break;
5373     }
5374     case CRC32CB: {
5375       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5376       uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5377       result = Crc32Checksum(acc, val, CRC32C_POLY);
5378       break;
5379     }
5380     case CRC32CH: {
5381       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5382       uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5383       result = Crc32Checksum(acc, val, CRC32C_POLY);
5384       break;
5385     }
5386     case CRC32CW: {
5387       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5388       uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5389       result = Crc32Checksum(acc, val, CRC32C_POLY);
5390       break;
5391     }
5392     case CRC32CX: {
5393       uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5394       uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5395       result = Crc32Checksum(acc, val, CRC32C_POLY);
5396       reg_size = kWRegSize;
5397       break;
5398     }
5399     default:
5400       VIXL_UNIMPLEMENTED();
5401   }
5402 
5403   if (shift_op != NO_SHIFT) {
5404     // Shift distance encoded in the least-significant five/six bits of the
5405     // register.
5406     int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
5407     unsigned shift = ReadWRegister(instr->GetRm()) & mask;
5408     result = ShiftOperand(reg_size,
5409                           ReadRegister(reg_size, instr->GetRn()),
5410                           shift_op,
5411                           shift);
5412   }
5413   WriteRegister(reg_size, instr->GetRd(), result);
5414 }
5415 
5416 
VisitDataProcessing3Source(const Instruction * instr)5417 void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
5418   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5419 
5420   uint64_t result = 0;
5421   // Extract and sign- or zero-extend 32-bit arguments for widening operations.
5422   uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
5423   uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
5424   int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
5425   int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
5426   uint64_t rn_u64 = ReadXRegister(instr->GetRn());
5427   uint64_t rm_u64 = ReadXRegister(instr->GetRm());
5428   switch (instr->Mask(DataProcessing3SourceMask)) {
5429     case MADD_w:
5430     case MADD_x:
5431       result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
5432       break;
5433     case MSUB_w:
5434     case MSUB_x:
5435       result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
5436       break;
5437     case SMADDL_x:
5438       result = ReadXRegister(instr->GetRa()) +
5439                static_cast<uint64_t>(rn_s32 * rm_s32);
5440       break;
5441     case SMSUBL_x:
5442       result = ReadXRegister(instr->GetRa()) -
5443                static_cast<uint64_t>(rn_s32 * rm_s32);
5444       break;
5445     case UMADDL_x:
5446       result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
5447       break;
5448     case UMSUBL_x:
5449       result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
5450       break;
5451     case UMULH_x:
5452       result =
5453           internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
5454                                      ReadRegister<uint64_t>(instr->GetRm()));
5455       break;
5456     case SMULH_x:
5457       result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
5458                                           ReadXRegister(instr->GetRm()));
5459       break;
5460     default:
5461       VIXL_UNIMPLEMENTED();
5462   }
5463   WriteRegister(reg_size, instr->GetRd(), result);
5464 }
5465 
5466 
VisitBitfield(const Instruction * instr)5467 void Simulator::VisitBitfield(const Instruction* instr) {
5468   unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5469   int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
5470   int R = instr->GetImmR();
5471   int S = instr->GetImmS();
5472 
5473   if (instr->GetSixtyFourBits() != instr->GetBitN()) {
5474     VisitUnallocated(instr);
5475   }
5476 
5477   if ((instr->GetSixtyFourBits() == 0) && ((S > 31) || (R > 31))) {
5478     VisitUnallocated(instr);
5479   }
5480 
5481   int diff = S - R;
5482   uint64_t mask;
5483   if (diff >= 0) {
5484     mask = ~UINT64_C(0) >> (64 - (diff + 1));
5485     mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
5486   } else {
5487     mask = ~UINT64_C(0) >> (64 - (S + 1));
5488     mask = RotateRight(mask, R, reg_size);
5489     diff += reg_size;
5490   }
5491 
5492   // inzero indicates if the extracted bitfield is inserted into the
5493   // destination register value or in zero.
5494   // If extend is true, extend the sign of the extracted bitfield.
5495   bool inzero = false;
5496   bool extend = false;
5497   switch (instr->Mask(BitfieldMask)) {
5498     case BFM_x:
5499     case BFM_w:
5500       break;
5501     case SBFM_x:
5502     case SBFM_w:
5503       inzero = true;
5504       extend = true;
5505       break;
5506     case UBFM_x:
5507     case UBFM_w:
5508       inzero = true;
5509       break;
5510     default:
5511       VIXL_UNIMPLEMENTED();
5512   }
5513 
5514   uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
5515   uint64_t src = ReadRegister(reg_size, instr->GetRn());
5516   // Rotate source bitfield into place.
5517   uint64_t result = RotateRight(src, R, reg_size);
5518   // Determine the sign extension.
5519   uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
5520   uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
5521 
5522   // Merge sign extension, dest/zero and bitfield.
5523   result = signbits | (result & mask) | (dst & ~mask);
5524 
5525   WriteRegister(reg_size, instr->GetRd(), result);
5526 }
5527 
5528 
VisitExtract(const Instruction * instr)5529 void Simulator::VisitExtract(const Instruction* instr) {
5530   unsigned lsb = instr->GetImmS();
5531   unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
5532   uint64_t low_res =
5533       static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
5534   uint64_t high_res = (lsb == 0)
5535                           ? 0
5536                           : ReadRegister<uint64_t>(reg_size, instr->GetRn())
5537                                 << (reg_size - lsb);
5538   WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
5539 }
5540 
5541 
VisitFPImmediate(const Instruction * instr)5542 void Simulator::VisitFPImmediate(const Instruction* instr) {
5543   AssertSupportedFPCR();
5544   unsigned dest = instr->GetRd();
5545   switch (instr->Mask(FPImmediateMask)) {
5546     case FMOV_h_imm:
5547       WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
5548       break;
5549     case FMOV_s_imm:
5550       WriteSRegister(dest, instr->GetImmFP32());
5551       break;
5552     case FMOV_d_imm:
5553       WriteDRegister(dest, instr->GetImmFP64());
5554       break;
5555     default:
5556       VIXL_UNREACHABLE();
5557   }
5558 }
5559 
5560 
VisitFPIntegerConvert(const Instruction * instr)5561 void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
5562   AssertSupportedFPCR();
5563 
5564   unsigned dst = instr->GetRd();
5565   unsigned src = instr->GetRn();
5566 
5567   FPRounding round = ReadRMode();
5568 
5569   switch (instr->Mask(FPIntegerConvertMask)) {
5570     case FCVTAS_wh:
5571       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
5572       break;
5573     case FCVTAS_xh:
5574       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
5575       break;
5576     case FCVTAS_ws:
5577       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
5578       break;
5579     case FCVTAS_xs:
5580       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
5581       break;
5582     case FCVTAS_wd:
5583       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
5584       break;
5585     case FCVTAS_xd:
5586       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
5587       break;
5588     case FCVTAU_wh:
5589       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
5590       break;
5591     case FCVTAU_xh:
5592       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
5593       break;
5594     case FCVTAU_ws:
5595       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
5596       break;
5597     case FCVTAU_xs:
5598       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
5599       break;
5600     case FCVTAU_wd:
5601       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
5602       break;
5603     case FCVTAU_xd:
5604       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
5605       break;
5606     case FCVTMS_wh:
5607       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
5608       break;
5609     case FCVTMS_xh:
5610       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
5611       break;
5612     case FCVTMS_ws:
5613       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
5614       break;
5615     case FCVTMS_xs:
5616       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
5617       break;
5618     case FCVTMS_wd:
5619       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
5620       break;
5621     case FCVTMS_xd:
5622       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
5623       break;
5624     case FCVTMU_wh:
5625       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
5626       break;
5627     case FCVTMU_xh:
5628       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
5629       break;
5630     case FCVTMU_ws:
5631       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
5632       break;
5633     case FCVTMU_xs:
5634       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
5635       break;
5636     case FCVTMU_wd:
5637       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
5638       break;
5639     case FCVTMU_xd:
5640       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
5641       break;
5642     case FCVTPS_wh:
5643       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
5644       break;
5645     case FCVTPS_xh:
5646       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
5647       break;
5648     case FCVTPS_ws:
5649       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
5650       break;
5651     case FCVTPS_xs:
5652       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
5653       break;
5654     case FCVTPS_wd:
5655       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
5656       break;
5657     case FCVTPS_xd:
5658       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
5659       break;
5660     case FCVTPU_wh:
5661       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
5662       break;
5663     case FCVTPU_xh:
5664       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
5665       break;
5666     case FCVTPU_ws:
5667       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
5668       break;
5669     case FCVTPU_xs:
5670       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
5671       break;
5672     case FCVTPU_wd:
5673       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
5674       break;
5675     case FCVTPU_xd:
5676       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
5677       break;
5678     case FCVTNS_wh:
5679       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
5680       break;
5681     case FCVTNS_xh:
5682       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
5683       break;
5684     case FCVTNS_ws:
5685       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
5686       break;
5687     case FCVTNS_xs:
5688       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
5689       break;
5690     case FCVTNS_wd:
5691       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
5692       break;
5693     case FCVTNS_xd:
5694       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
5695       break;
5696     case FCVTNU_wh:
5697       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
5698       break;
5699     case FCVTNU_xh:
5700       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
5701       break;
5702     case FCVTNU_ws:
5703       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
5704       break;
5705     case FCVTNU_xs:
5706       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
5707       break;
5708     case FCVTNU_wd:
5709       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
5710       break;
5711     case FCVTNU_xd:
5712       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
5713       break;
5714     case FCVTZS_wh:
5715       WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
5716       break;
5717     case FCVTZS_xh:
5718       WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
5719       break;
5720     case FCVTZS_ws:
5721       WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
5722       break;
5723     case FCVTZS_xs:
5724       WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
5725       break;
5726     case FCVTZS_wd:
5727       WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
5728       break;
5729     case FCVTZS_xd:
5730       WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
5731       break;
5732     case FCVTZU_wh:
5733       WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
5734       break;
5735     case FCVTZU_xh:
5736       WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
5737       break;
5738     case FCVTZU_ws:
5739       WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
5740       break;
5741     case FCVTZU_xs:
5742       WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
5743       break;
5744     case FCVTZU_wd:
5745       WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
5746       break;
5747     case FCVTZU_xd:
5748       WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
5749       break;
5750     case FJCVTZS:
5751       WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
5752       break;
5753     case FMOV_hw:
5754       WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
5755       break;
5756     case FMOV_wh:
5757       WriteWRegister(dst, ReadHRegisterBits(src));
5758       break;
5759     case FMOV_xh:
5760       WriteXRegister(dst, ReadHRegisterBits(src));
5761       break;
5762     case FMOV_hx:
5763       WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
5764       break;
5765     case FMOV_ws:
5766       WriteWRegister(dst, ReadSRegisterBits(src));
5767       break;
5768     case FMOV_xd:
5769       WriteXRegister(dst, ReadDRegisterBits(src));
5770       break;
5771     case FMOV_sw:
5772       WriteSRegisterBits(dst, ReadWRegister(src));
5773       break;
5774     case FMOV_dx:
5775       WriteDRegisterBits(dst, ReadXRegister(src));
5776       break;
5777     case FMOV_d1_x:
5778       LogicVRegister(ReadVRegister(dst))
5779           .SetUint(kFormatD, 1, ReadXRegister(src));
5780       break;
5781     case FMOV_x_d1:
5782       WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
5783       break;
5784 
5785     // A 32-bit input can be handled in the same way as a 64-bit input, since
5786     // the sign- or zero-extension will not affect the conversion.
5787     case SCVTF_dx:
5788       WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
5789       break;
5790     case SCVTF_dw:
5791       WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
5792       break;
5793     case UCVTF_dx:
5794       WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
5795       break;
5796     case UCVTF_dw: {
5797       WriteDRegister(dst,
5798                      UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
5799       break;
5800     }
5801     case SCVTF_sx:
5802       WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
5803       break;
5804     case SCVTF_sw:
5805       WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
5806       break;
5807     case UCVTF_sx:
5808       WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
5809       break;
5810     case UCVTF_sw: {
5811       WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
5812       break;
5813     }
5814     case SCVTF_hx:
5815       WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
5816       break;
5817     case SCVTF_hw:
5818       WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
5819       break;
5820     case UCVTF_hx:
5821       WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
5822       break;
5823     case UCVTF_hw: {
5824       WriteHRegister(dst,
5825                      UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
5826       break;
5827     }
5828 
5829     default:
5830       VIXL_UNREACHABLE();
5831   }
5832 }
5833 
5834 
VisitFPFixedPointConvert(const Instruction * instr)5835 void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
5836   AssertSupportedFPCR();
5837 
5838   unsigned dst = instr->GetRd();
5839   unsigned src = instr->GetRn();
5840   int fbits = 64 - instr->GetFPScale();
5841 
5842   FPRounding round = ReadRMode();
5843 
5844   switch (instr->Mask(FPFixedPointConvertMask)) {
5845     // A 32-bit input can be handled in the same way as a 64-bit input, since
5846     // the sign- or zero-extension will not affect the conversion.
5847     case SCVTF_dx_fixed:
5848       WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
5849       break;
5850     case SCVTF_dw_fixed:
5851       WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
5852       break;
5853     case UCVTF_dx_fixed:
5854       WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
5855       break;
5856     case UCVTF_dw_fixed: {
5857       WriteDRegister(dst,
5858                      UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
5859       break;
5860     }
5861     case SCVTF_sx_fixed:
5862       WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
5863       break;
5864     case SCVTF_sw_fixed:
5865       WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
5866       break;
5867     case UCVTF_sx_fixed:
5868       WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
5869       break;
5870     case UCVTF_sw_fixed: {
5871       WriteSRegister(dst,
5872                      UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
5873       break;
5874     }
5875     case SCVTF_hx_fixed:
5876       WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
5877       break;
5878     case SCVTF_hw_fixed:
5879       WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
5880       break;
5881     case UCVTF_hx_fixed:
5882       WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
5883       break;
5884     case UCVTF_hw_fixed: {
5885       WriteHRegister(dst,
5886                      UFixedToFloat16(ReadRegister<uint32_t>(src),
5887                                      fbits,
5888                                      round));
5889       break;
5890     }
5891     case FCVTZS_xd_fixed:
5892       WriteXRegister(dst,
5893                      FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5894                                FPZero));
5895       break;
5896     case FCVTZS_wd_fixed:
5897       WriteWRegister(dst,
5898                      FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5899                                FPZero));
5900       break;
5901     case FCVTZU_xd_fixed:
5902       WriteXRegister(dst,
5903                      FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
5904                                 FPZero));
5905       break;
5906     case FCVTZU_wd_fixed:
5907       WriteWRegister(dst,
5908                      FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
5909                                 FPZero));
5910       break;
5911     case FCVTZS_xs_fixed:
5912       WriteXRegister(dst,
5913                      FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5914                                FPZero));
5915       break;
5916     case FCVTZS_ws_fixed:
5917       WriteWRegister(dst,
5918                      FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5919                                FPZero));
5920       break;
5921     case FCVTZU_xs_fixed:
5922       WriteXRegister(dst,
5923                      FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
5924                                 FPZero));
5925       break;
5926     case FCVTZU_ws_fixed:
5927       WriteWRegister(dst,
5928                      FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
5929                                 FPZero));
5930       break;
5931     case FCVTZS_xh_fixed: {
5932       double output =
5933           static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5934       WriteXRegister(dst, FPToInt64(output, FPZero));
5935       break;
5936     }
5937     case FCVTZS_wh_fixed: {
5938       double output =
5939           static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5940       WriteWRegister(dst, FPToInt32(output, FPZero));
5941       break;
5942     }
5943     case FCVTZU_xh_fixed: {
5944       double output =
5945           static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5946       WriteXRegister(dst, FPToUInt64(output, FPZero));
5947       break;
5948     }
5949     case FCVTZU_wh_fixed: {
5950       double output =
5951           static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
5952       WriteWRegister(dst, FPToUInt32(output, FPZero));
5953       break;
5954     }
5955     default:
5956       VIXL_UNREACHABLE();
5957   }
5958 }
5959 
5960 
VisitFPCompare(const Instruction * instr)5961 void Simulator::VisitFPCompare(const Instruction* instr) {
5962   AssertSupportedFPCR();
5963 
5964   FPTrapFlags trap = DisableTrap;
5965   switch (instr->Mask(FPCompareMask)) {
5966     case FCMPE_h:
5967       trap = EnableTrap;
5968       VIXL_FALLTHROUGH();
5969     case FCMP_h:
5970       FPCompare(ReadHRegister(instr->GetRn()),
5971                 ReadHRegister(instr->GetRm()),
5972                 trap);
5973       break;
5974     case FCMPE_s:
5975       trap = EnableTrap;
5976       VIXL_FALLTHROUGH();
5977     case FCMP_s:
5978       FPCompare(ReadSRegister(instr->GetRn()),
5979                 ReadSRegister(instr->GetRm()),
5980                 trap);
5981       break;
5982     case FCMPE_d:
5983       trap = EnableTrap;
5984       VIXL_FALLTHROUGH();
5985     case FCMP_d:
5986       FPCompare(ReadDRegister(instr->GetRn()),
5987                 ReadDRegister(instr->GetRm()),
5988                 trap);
5989       break;
5990     case FCMPE_h_zero:
5991       trap = EnableTrap;
5992       VIXL_FALLTHROUGH();
5993     case FCMP_h_zero:
5994       FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
5995       break;
5996     case FCMPE_s_zero:
5997       trap = EnableTrap;
5998       VIXL_FALLTHROUGH();
5999     case FCMP_s_zero:
6000       FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
6001       break;
6002     case FCMPE_d_zero:
6003       trap = EnableTrap;
6004       VIXL_FALLTHROUGH();
6005     case FCMP_d_zero:
6006       FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
6007       break;
6008     default:
6009       VIXL_UNIMPLEMENTED();
6010   }
6011 }
6012 
6013 
VisitFPConditionalCompare(const Instruction * instr)6014 void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
6015   AssertSupportedFPCR();
6016 
6017   FPTrapFlags trap = DisableTrap;
6018   switch (instr->Mask(FPConditionalCompareMask)) {
6019     case FCCMPE_h:
6020       trap = EnableTrap;
6021       VIXL_FALLTHROUGH();
6022     case FCCMP_h:
6023       if (ConditionPassed(instr->GetCondition())) {
6024         FPCompare(ReadHRegister(instr->GetRn()),
6025                   ReadHRegister(instr->GetRm()),
6026                   trap);
6027       } else {
6028         ReadNzcv().SetFlags(instr->GetNzcv());
6029         LogSystemRegister(NZCV);
6030       }
6031       break;
6032     case FCCMPE_s:
6033       trap = EnableTrap;
6034       VIXL_FALLTHROUGH();
6035     case FCCMP_s:
6036       if (ConditionPassed(instr->GetCondition())) {
6037         FPCompare(ReadSRegister(instr->GetRn()),
6038                   ReadSRegister(instr->GetRm()),
6039                   trap);
6040       } else {
6041         ReadNzcv().SetFlags(instr->GetNzcv());
6042         LogSystemRegister(NZCV);
6043       }
6044       break;
6045     case FCCMPE_d:
6046       trap = EnableTrap;
6047       VIXL_FALLTHROUGH();
6048     case FCCMP_d:
6049       if (ConditionPassed(instr->GetCondition())) {
6050         FPCompare(ReadDRegister(instr->GetRn()),
6051                   ReadDRegister(instr->GetRm()),
6052                   trap);
6053       } else {
6054         ReadNzcv().SetFlags(instr->GetNzcv());
6055         LogSystemRegister(NZCV);
6056       }
6057       break;
6058     default:
6059       VIXL_UNIMPLEMENTED();
6060   }
6061 }
6062 
6063 
VisitFPConditionalSelect(const Instruction * instr)6064 void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
6065   AssertSupportedFPCR();
6066 
6067   Instr selected;
6068   if (ConditionPassed(instr->GetCondition())) {
6069     selected = instr->GetRn();
6070   } else {
6071     selected = instr->GetRm();
6072   }
6073 
6074   switch (instr->Mask(FPConditionalSelectMask)) {
6075     case FCSEL_h:
6076       WriteHRegister(instr->GetRd(), ReadHRegister(selected));
6077       break;
6078     case FCSEL_s:
6079       WriteSRegister(instr->GetRd(), ReadSRegister(selected));
6080       break;
6081     case FCSEL_d:
6082       WriteDRegister(instr->GetRd(), ReadDRegister(selected));
6083       break;
6084     default:
6085       VIXL_UNIMPLEMENTED();
6086   }
6087 }
6088 
6089 
VisitFPDataProcessing1Source(const Instruction * instr)6090 void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
6091   AssertSupportedFPCR();
6092 
6093   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6094   VectorFormat vform;
6095   switch (instr->Mask(FPTypeMask)) {
6096     default:
6097       VIXL_UNREACHABLE_OR_FALLTHROUGH();
6098     case FP64:
6099       vform = kFormatD;
6100       break;
6101     case FP32:
6102       vform = kFormatS;
6103       break;
6104     case FP16:
6105       vform = kFormatH;
6106       break;
6107   }
6108 
6109   SimVRegister& rd = ReadVRegister(instr->GetRd());
6110   SimVRegister& rn = ReadVRegister(instr->GetRn());
6111   bool inexact_exception = false;
6112   FrintMode frint_mode = kFrintToInteger;
6113 
6114   unsigned fd = instr->GetRd();
6115   unsigned fn = instr->GetRn();
6116 
6117   switch (instr->Mask(FPDataProcessing1SourceMask)) {
6118     case FMOV_h:
6119       WriteHRegister(fd, ReadHRegister(fn));
6120       return;
6121     case FMOV_s:
6122       WriteSRegister(fd, ReadSRegister(fn));
6123       return;
6124     case FMOV_d:
6125       WriteDRegister(fd, ReadDRegister(fn));
6126       return;
6127     case FABS_h:
6128     case FABS_s:
6129     case FABS_d:
6130       fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
6131       // Explicitly log the register update whilst we have type information.
6132       LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6133       return;
6134     case FNEG_h:
6135     case FNEG_s:
6136     case FNEG_d:
6137       fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
6138       // Explicitly log the register update whilst we have type information.
6139       LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6140       return;
6141     case FCVT_ds:
6142       WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
6143       return;
6144     case FCVT_sd:
6145       WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
6146       return;
6147     case FCVT_hs:
6148       WriteHRegister(fd,
6149                      Float16ToRawbits(
6150                          FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
6151       return;
6152     case FCVT_sh:
6153       WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
6154       return;
6155     case FCVT_dh:
6156       WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
6157       return;
6158     case FCVT_hd:
6159       WriteHRegister(fd,
6160                      Float16ToRawbits(
6161                          FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
6162       return;
6163     case FSQRT_h:
6164     case FSQRT_s:
6165     case FSQRT_d:
6166       fsqrt(vform, rd, rn);
6167       // Explicitly log the register update whilst we have type information.
6168       LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6169       return;
6170     case FRINT32X_s:
6171     case FRINT32X_d:
6172       inexact_exception = true;
6173       frint_mode = kFrintToInt32;
6174       break;  // Use FPCR rounding mode.
6175     case FRINT64X_s:
6176     case FRINT64X_d:
6177       inexact_exception = true;
6178       frint_mode = kFrintToInt64;
6179       break;  // Use FPCR rounding mode.
6180     case FRINT32Z_s:
6181     case FRINT32Z_d:
6182       inexact_exception = true;
6183       frint_mode = kFrintToInt32;
6184       fpcr_rounding = FPZero;
6185       break;
6186     case FRINT64Z_s:
6187     case FRINT64Z_d:
6188       inexact_exception = true;
6189       frint_mode = kFrintToInt64;
6190       fpcr_rounding = FPZero;
6191       break;
6192     case FRINTI_h:
6193     case FRINTI_s:
6194     case FRINTI_d:
6195       break;  // Use FPCR rounding mode.
6196     case FRINTX_h:
6197     case FRINTX_s:
6198     case FRINTX_d:
6199       inexact_exception = true;
6200       break;
6201     case FRINTA_h:
6202     case FRINTA_s:
6203     case FRINTA_d:
6204       fpcr_rounding = FPTieAway;
6205       break;
6206     case FRINTM_h:
6207     case FRINTM_s:
6208     case FRINTM_d:
6209       fpcr_rounding = FPNegativeInfinity;
6210       break;
6211     case FRINTN_h:
6212     case FRINTN_s:
6213     case FRINTN_d:
6214       fpcr_rounding = FPTieEven;
6215       break;
6216     case FRINTP_h:
6217     case FRINTP_s:
6218     case FRINTP_d:
6219       fpcr_rounding = FPPositiveInfinity;
6220       break;
6221     case FRINTZ_h:
6222     case FRINTZ_s:
6223     case FRINTZ_d:
6224       fpcr_rounding = FPZero;
6225       break;
6226     default:
6227       VIXL_UNIMPLEMENTED();
6228   }
6229 
6230   // Only FRINT* instructions fall through the switch above.
6231   frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
6232   // Explicitly log the register update whilst we have type information.
6233   LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6234 }
6235 
6236 
VisitFPDataProcessing2Source(const Instruction * instr)6237 void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
6238   AssertSupportedFPCR();
6239 
6240   VectorFormat vform;
6241   switch (instr->Mask(FPTypeMask)) {
6242     default:
6243       VIXL_UNREACHABLE_OR_FALLTHROUGH();
6244     case FP64:
6245       vform = kFormatD;
6246       break;
6247     case FP32:
6248       vform = kFormatS;
6249       break;
6250     case FP16:
6251       vform = kFormatH;
6252       break;
6253   }
6254   SimVRegister& rd = ReadVRegister(instr->GetRd());
6255   SimVRegister& rn = ReadVRegister(instr->GetRn());
6256   SimVRegister& rm = ReadVRegister(instr->GetRm());
6257 
6258   switch (instr->Mask(FPDataProcessing2SourceMask)) {
6259     case FADD_h:
6260     case FADD_s:
6261     case FADD_d:
6262       fadd(vform, rd, rn, rm);
6263       break;
6264     case FSUB_h:
6265     case FSUB_s:
6266     case FSUB_d:
6267       fsub(vform, rd, rn, rm);
6268       break;
6269     case FMUL_h:
6270     case FMUL_s:
6271     case FMUL_d:
6272       fmul(vform, rd, rn, rm);
6273       break;
6274     case FNMUL_h:
6275     case FNMUL_s:
6276     case FNMUL_d:
6277       fnmul(vform, rd, rn, rm);
6278       break;
6279     case FDIV_h:
6280     case FDIV_s:
6281     case FDIV_d:
6282       fdiv(vform, rd, rn, rm);
6283       break;
6284     case FMAX_h:
6285     case FMAX_s:
6286     case FMAX_d:
6287       fmax(vform, rd, rn, rm);
6288       break;
6289     case FMIN_h:
6290     case FMIN_s:
6291     case FMIN_d:
6292       fmin(vform, rd, rn, rm);
6293       break;
6294     case FMAXNM_h:
6295     case FMAXNM_s:
6296     case FMAXNM_d:
6297       fmaxnm(vform, rd, rn, rm);
6298       break;
6299     case FMINNM_h:
6300     case FMINNM_s:
6301     case FMINNM_d:
6302       fminnm(vform, rd, rn, rm);
6303       break;
6304     default:
6305       VIXL_UNREACHABLE();
6306   }
6307   // Explicitly log the register update whilst we have type information.
6308   LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
6309 }
6310 
6311 
VisitFPDataProcessing3Source(const Instruction * instr)6312 void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
6313   AssertSupportedFPCR();
6314 
6315   unsigned fd = instr->GetRd();
6316   unsigned fn = instr->GetRn();
6317   unsigned fm = instr->GetRm();
6318   unsigned fa = instr->GetRa();
6319 
6320   switch (instr->Mask(FPDataProcessing3SourceMask)) {
6321     // fd = fa +/- (fn * fm)
6322     case FMADD_h:
6323       WriteHRegister(fd,
6324                      FPMulAdd(ReadHRegister(fa),
6325                               ReadHRegister(fn),
6326                               ReadHRegister(fm)));
6327       break;
6328     case FMSUB_h:
6329       WriteHRegister(fd,
6330                      FPMulAdd(ReadHRegister(fa),
6331                               -ReadHRegister(fn),
6332                               ReadHRegister(fm)));
6333       break;
6334     case FMADD_s:
6335       WriteSRegister(fd,
6336                      FPMulAdd(ReadSRegister(fa),
6337                               ReadSRegister(fn),
6338                               ReadSRegister(fm)));
6339       break;
6340     case FMSUB_s:
6341       WriteSRegister(fd,
6342                      FPMulAdd(ReadSRegister(fa),
6343                               -ReadSRegister(fn),
6344                               ReadSRegister(fm)));
6345       break;
6346     case FMADD_d:
6347       WriteDRegister(fd,
6348                      FPMulAdd(ReadDRegister(fa),
6349                               ReadDRegister(fn),
6350                               ReadDRegister(fm)));
6351       break;
6352     case FMSUB_d:
6353       WriteDRegister(fd,
6354                      FPMulAdd(ReadDRegister(fa),
6355                               -ReadDRegister(fn),
6356                               ReadDRegister(fm)));
6357       break;
6358     // Negated variants of the above.
6359     case FNMADD_h:
6360       WriteHRegister(fd,
6361                      FPMulAdd(-ReadHRegister(fa),
6362                               -ReadHRegister(fn),
6363                               ReadHRegister(fm)));
6364       break;
6365     case FNMSUB_h:
6366       WriteHRegister(fd,
6367                      FPMulAdd(-ReadHRegister(fa),
6368                               ReadHRegister(fn),
6369                               ReadHRegister(fm)));
6370       break;
6371     case FNMADD_s:
6372       WriteSRegister(fd,
6373                      FPMulAdd(-ReadSRegister(fa),
6374                               -ReadSRegister(fn),
6375                               ReadSRegister(fm)));
6376       break;
6377     case FNMSUB_s:
6378       WriteSRegister(fd,
6379                      FPMulAdd(-ReadSRegister(fa),
6380                               ReadSRegister(fn),
6381                               ReadSRegister(fm)));
6382       break;
6383     case FNMADD_d:
6384       WriteDRegister(fd,
6385                      FPMulAdd(-ReadDRegister(fa),
6386                               -ReadDRegister(fn),
6387                               ReadDRegister(fm)));
6388       break;
6389     case FNMSUB_d:
6390       WriteDRegister(fd,
6391                      FPMulAdd(-ReadDRegister(fa),
6392                               ReadDRegister(fn),
6393                               ReadDRegister(fm)));
6394       break;
6395     default:
6396       VIXL_UNIMPLEMENTED();
6397   }
6398 }
6399 
6400 
FPProcessNaNs(const Instruction * instr)6401 bool Simulator::FPProcessNaNs(const Instruction* instr) {
6402   unsigned fd = instr->GetRd();
6403   unsigned fn = instr->GetRn();
6404   unsigned fm = instr->GetRm();
6405   bool done = false;
6406 
6407   if (instr->Mask(FP64) == FP64) {
6408     double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
6409     if (IsNaN(result)) {
6410       WriteDRegister(fd, result);
6411       done = true;
6412     }
6413   } else if (instr->Mask(FP32) == FP32) {
6414     float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
6415     if (IsNaN(result)) {
6416       WriteSRegister(fd, result);
6417       done = true;
6418     }
6419   } else {
6420     VIXL_ASSERT(instr->Mask(FP16) == FP16);
6421     VIXL_UNIMPLEMENTED();
6422   }
6423 
6424   return done;
6425 }
6426 
6427 
SysOp_W(int op,int64_t val)6428 void Simulator::SysOp_W(int op, int64_t val) {
6429   switch (op) {
6430     case IVAU:
6431     case CVAC:
6432     case CVAU:
6433     case CVAP:
6434     case CVADP:
6435     case CIVAC: {
6436       // Perform a placeholder memory access to ensure that we have read access
6437       // to the specified address.
6438       volatile uint8_t y = MemRead<uint8_t>(val);
6439       USE(y);
6440       // TODO: Implement "case ZVA:".
6441       break;
6442     }
6443     default:
6444       VIXL_UNIMPLEMENTED();
6445   }
6446 }
6447 
6448 
6449 // clang-format off
6450 #define PAUTH_SYSTEM_MODES(V)                                     \
6451   V(A1716, 17, ReadXRegister(16),                      kPACKeyIA) \
6452   V(B1716, 17, ReadXRegister(16),                      kPACKeyIB) \
6453   V(AZ,    30, 0x00000000,                             kPACKeyIA) \
6454   V(BZ,    30, 0x00000000,                             kPACKeyIB) \
6455   V(ASP,   30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIA) \
6456   V(BSP,   30, ReadXRegister(31, Reg31IsStackPointer), kPACKeyIB)
6457 // clang-format on
6458 
6459 
VisitSystem(const Instruction * instr)6460 void Simulator::VisitSystem(const Instruction* instr) {
6461   // Some system instructions hijack their Op and Cp fields to represent a
6462   // range of immediates instead of indicating a different instruction. This
6463   // makes the decoding tricky.
6464   if (instr->GetInstructionBits() == XPACLRI) {
6465     WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
6466   } else if (instr->Mask(SystemPStateFMask) == SystemPStateFixed) {
6467     switch (instr->Mask(SystemPStateMask)) {
6468       case CFINV:
6469         ReadNzcv().SetC(!ReadC());
6470         break;
6471       case AXFLAG:
6472         ReadNzcv().SetN(0);
6473         ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
6474         ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
6475         ReadNzcv().SetV(0);
6476         break;
6477       case XAFLAG: {
6478         // Can't set the flags in place due to the logical dependencies.
6479         uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
6480         uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
6481         uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
6482         uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
6483         ReadNzcv().SetN(n);
6484         ReadNzcv().SetZ(z);
6485         ReadNzcv().SetC(c);
6486         ReadNzcv().SetV(v);
6487         break;
6488       }
6489     }
6490   } else if (instr->Mask(SystemPAuthFMask) == SystemPAuthFixed) {
6491     // Check BType allows PACI[AB]SP instructions.
6492     if (PcIsInGuardedPage()) {
6493       Instr i = instr->Mask(SystemPAuthMask);
6494       if ((i == PACIASP) || (i == PACIBSP)) {
6495         switch (ReadBType()) {
6496           case BranchFromGuardedNotToIP:
6497           // TODO: This case depends on the value of SCTLR_EL1.BT0, which we
6498           // assume here to be zero. This allows execution of PACI[AB]SP when
6499           // BTYPE is BranchFromGuardedNotToIP (0b11).
6500           case DefaultBType:
6501           case BranchFromUnguardedOrToIP:
6502           case BranchAndLink:
6503             break;
6504         }
6505       }
6506     }
6507 
6508     switch (instr->Mask(SystemPAuthMask)) {
6509 #define DEFINE_PAUTH_FUNCS(SUFFIX, DST, MOD, KEY)                              \
6510   case PACI##SUFFIX:                                                           \
6511     WriteXRegister(DST,                                                        \
6512                    AddPAC(ReadXRegister(DST), MOD, KEY, kInstructionPointer)); \
6513     break;                                                                     \
6514   case AUTI##SUFFIX:                                                           \
6515     WriteXRegister(DST,                                                        \
6516                    AuthPAC(ReadXRegister(DST),                                 \
6517                            MOD,                                                \
6518                            KEY,                                                \
6519                            kInstructionPointer));                              \
6520     break;
6521 
6522       PAUTH_SYSTEM_MODES(DEFINE_PAUTH_FUNCS)
6523 #undef DEFINE_PAUTH_FUNCS
6524     }
6525   } else if (instr->Mask(SystemExclusiveMonitorFMask) ==
6526              SystemExclusiveMonitorFixed) {
6527     VIXL_ASSERT(instr->Mask(SystemExclusiveMonitorMask) == CLREX);
6528     switch (instr->Mask(SystemExclusiveMonitorMask)) {
6529       case CLREX: {
6530         PrintExclusiveAccessWarning();
6531         ClearLocalMonitor();
6532         break;
6533       }
6534     }
6535   } else if (instr->Mask(SystemSysRegFMask) == SystemSysRegFixed) {
6536     switch (instr->Mask(SystemSysRegMask)) {
6537       case MRS: {
6538         switch (instr->GetImmSystemRegister()) {
6539           case NZCV:
6540             WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
6541             break;
6542           case FPCR:
6543             WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
6544             break;
6545           case RNDR:
6546           case RNDRRS: {
6547             uint64_t high = jrand48(rand_state_);
6548             uint64_t low = jrand48(rand_state_);
6549             uint64_t rand_num = (high << 32) | (low & 0xffffffff);
6550             WriteXRegister(instr->GetRt(), rand_num);
6551             // Simulate successful random number generation.
6552             // TODO: Return failure occasionally as a random number cannot be
6553             // returned in a period of time.
6554             ReadNzcv().SetRawValue(NoFlag);
6555             LogSystemRegister(NZCV);
6556             break;
6557           }
6558           default:
6559             VIXL_UNIMPLEMENTED();
6560         }
6561         break;
6562       }
6563       case MSR: {
6564         switch (instr->GetImmSystemRegister()) {
6565           case NZCV:
6566             ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
6567             LogSystemRegister(NZCV);
6568             break;
6569           case FPCR:
6570             ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
6571             LogSystemRegister(FPCR);
6572             break;
6573           default:
6574             VIXL_UNIMPLEMENTED();
6575         }
6576         break;
6577       }
6578     }
6579   } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
6580     VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
6581     switch (instr->GetImmHint()) {
6582       case NOP:
6583       case ESB:
6584       case CSDB:
6585       case BTI_jc:
6586         break;
6587       case BTI:
6588         if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
6589           VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
6590         }
6591         break;
6592       case BTI_c:
6593         if (PcIsInGuardedPage() && (ReadBType() == BranchFromGuardedNotToIP)) {
6594           VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
6595         }
6596         break;
6597       case BTI_j:
6598         if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
6599           VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
6600         }
6601         break;
6602       default:
6603         VIXL_UNIMPLEMENTED();
6604     }
6605   } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
6606     __sync_synchronize();
6607   } else if ((instr->Mask(SystemSysFMask) == SystemSysFixed)) {
6608     switch (instr->Mask(SystemSysMask)) {
6609       case SYS:
6610         SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
6611         break;
6612       default:
6613         VIXL_UNIMPLEMENTED();
6614     }
6615   } else {
6616     VIXL_UNIMPLEMENTED();
6617   }
6618 }
6619 
6620 
VisitException(const Instruction * instr)6621 void Simulator::VisitException(const Instruction* instr) {
6622   switch (instr->Mask(ExceptionMask)) {
6623     case HLT:
6624       switch (instr->GetImmException()) {
6625         case kUnreachableOpcode:
6626           DoUnreachable(instr);
6627           return;
6628         case kTraceOpcode:
6629           DoTrace(instr);
6630           return;
6631         case kLogOpcode:
6632           DoLog(instr);
6633           return;
6634         case kPrintfOpcode:
6635           DoPrintf(instr);
6636           return;
6637         case kRuntimeCallOpcode:
6638           DoRuntimeCall(instr);
6639           return;
6640         case kSetCPUFeaturesOpcode:
6641         case kEnableCPUFeaturesOpcode:
6642         case kDisableCPUFeaturesOpcode:
6643           DoConfigureCPUFeatures(instr);
6644           return;
6645         case kSaveCPUFeaturesOpcode:
6646           DoSaveCPUFeatures(instr);
6647           return;
6648         case kRestoreCPUFeaturesOpcode:
6649           DoRestoreCPUFeatures(instr);
6650           return;
6651         default:
6652           HostBreakpoint();
6653           return;
6654       }
6655     case BRK:
6656       HostBreakpoint();
6657       return;
6658     default:
6659       VIXL_UNIMPLEMENTED();
6660   }
6661 }
6662 
6663 
VisitCrypto2RegSHA(const Instruction * instr)6664 void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
6665   VisitUnimplemented(instr);
6666 }
6667 
6668 
VisitCrypto3RegSHA(const Instruction * instr)6669 void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
6670   VisitUnimplemented(instr);
6671 }
6672 
6673 
VisitCryptoAES(const Instruction * instr)6674 void Simulator::VisitCryptoAES(const Instruction* instr) {
6675   VisitUnimplemented(instr);
6676 }
6677 
6678 
VisitNEON2RegMisc(const Instruction * instr)6679 void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
6680   NEONFormatDecoder nfd(instr);
6681   VectorFormat vf = nfd.GetVectorFormat();
6682 
6683   static const NEONFormatMap map_lp =
6684       {{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
6685   VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
6686 
6687   static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
6688   VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
6689 
6690   static const NEONFormatMap map_fcvtn = {{22, 30},
6691                                           {NF_4H, NF_8H, NF_2S, NF_4S}};
6692   VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
6693 
6694   SimVRegister& rd = ReadVRegister(instr->GetRd());
6695   SimVRegister& rn = ReadVRegister(instr->GetRn());
6696 
6697   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
6698     // These instructions all use a two bit size field, except NOT and RBIT,
6699     // which use the field to encode the operation.
6700     switch (instr->Mask(NEON2RegMiscMask)) {
6701       case NEON_REV64:
6702         rev64(vf, rd, rn);
6703         break;
6704       case NEON_REV32:
6705         rev32(vf, rd, rn);
6706         break;
6707       case NEON_REV16:
6708         rev16(vf, rd, rn);
6709         break;
6710       case NEON_SUQADD:
6711         suqadd(vf, rd, rd, rn);
6712         break;
6713       case NEON_USQADD:
6714         usqadd(vf, rd, rd, rn);
6715         break;
6716       case NEON_CLS:
6717         cls(vf, rd, rn);
6718         break;
6719       case NEON_CLZ:
6720         clz(vf, rd, rn);
6721         break;
6722       case NEON_CNT:
6723         cnt(vf, rd, rn);
6724         break;
6725       case NEON_SQABS:
6726         abs(vf, rd, rn).SignedSaturate(vf);
6727         break;
6728       case NEON_SQNEG:
6729         neg(vf, rd, rn).SignedSaturate(vf);
6730         break;
6731       case NEON_CMGT_zero:
6732         cmp(vf, rd, rn, 0, gt);
6733         break;
6734       case NEON_CMGE_zero:
6735         cmp(vf, rd, rn, 0, ge);
6736         break;
6737       case NEON_CMEQ_zero:
6738         cmp(vf, rd, rn, 0, eq);
6739         break;
6740       case NEON_CMLE_zero:
6741         cmp(vf, rd, rn, 0, le);
6742         break;
6743       case NEON_CMLT_zero:
6744         cmp(vf, rd, rn, 0, lt);
6745         break;
6746       case NEON_ABS:
6747         abs(vf, rd, rn);
6748         break;
6749       case NEON_NEG:
6750         neg(vf, rd, rn);
6751         break;
6752       case NEON_SADDLP:
6753         saddlp(vf_lp, rd, rn);
6754         break;
6755       case NEON_UADDLP:
6756         uaddlp(vf_lp, rd, rn);
6757         break;
6758       case NEON_SADALP:
6759         sadalp(vf_lp, rd, rn);
6760         break;
6761       case NEON_UADALP:
6762         uadalp(vf_lp, rd, rn);
6763         break;
6764       case NEON_RBIT_NOT:
6765         vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
6766         switch (instr->GetFPType()) {
6767           case 0:
6768             not_(vf, rd, rn);
6769             break;
6770           case 1:
6771             rbit(vf, rd, rn);
6772             break;
6773           default:
6774             VIXL_UNIMPLEMENTED();
6775         }
6776         break;
6777     }
6778   } else {
6779     VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
6780     FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6781     bool inexact_exception = false;
6782     FrintMode frint_mode = kFrintToInteger;
6783 
6784     // These instructions all use a one bit size field, except XTN, SQXTUN,
6785     // SHLL, SQXTN and UQXTN, which use a two bit size field.
6786     switch (instr->Mask(NEON2RegMiscFPMask)) {
6787       case NEON_FABS:
6788         fabs_(fpf, rd, rn);
6789         return;
6790       case NEON_FNEG:
6791         fneg(fpf, rd, rn);
6792         return;
6793       case NEON_FSQRT:
6794         fsqrt(fpf, rd, rn);
6795         return;
6796       case NEON_FCVTL:
6797         if (instr->Mask(NEON_Q)) {
6798           fcvtl2(vf_fcvtl, rd, rn);
6799         } else {
6800           fcvtl(vf_fcvtl, rd, rn);
6801         }
6802         return;
6803       case NEON_FCVTN:
6804         if (instr->Mask(NEON_Q)) {
6805           fcvtn2(vf_fcvtn, rd, rn);
6806         } else {
6807           fcvtn(vf_fcvtn, rd, rn);
6808         }
6809         return;
6810       case NEON_FCVTXN:
6811         if (instr->Mask(NEON_Q)) {
6812           fcvtxn2(vf_fcvtn, rd, rn);
6813         } else {
6814           fcvtxn(vf_fcvtn, rd, rn);
6815         }
6816         return;
6817 
6818       // The following instructions break from the switch statement, rather
6819       // than return.
6820       case NEON_FRINT32X:
6821         inexact_exception = true;
6822         frint_mode = kFrintToInt32;
6823         break;  // Use FPCR rounding mode.
6824       case NEON_FRINT32Z:
6825         inexact_exception = true;
6826         frint_mode = kFrintToInt32;
6827         fpcr_rounding = FPZero;
6828         break;
6829       case NEON_FRINT64X:
6830         inexact_exception = true;
6831         frint_mode = kFrintToInt64;
6832         break;  // Use FPCR rounding mode.
6833       case NEON_FRINT64Z:
6834         inexact_exception = true;
6835         frint_mode = kFrintToInt64;
6836         fpcr_rounding = FPZero;
6837         break;
6838       case NEON_FRINTI:
6839         break;  // Use FPCR rounding mode.
6840       case NEON_FRINTX:
6841         inexact_exception = true;
6842         break;
6843       case NEON_FRINTA:
6844         fpcr_rounding = FPTieAway;
6845         break;
6846       case NEON_FRINTM:
6847         fpcr_rounding = FPNegativeInfinity;
6848         break;
6849       case NEON_FRINTN:
6850         fpcr_rounding = FPTieEven;
6851         break;
6852       case NEON_FRINTP:
6853         fpcr_rounding = FPPositiveInfinity;
6854         break;
6855       case NEON_FRINTZ:
6856         fpcr_rounding = FPZero;
6857         break;
6858 
6859       case NEON_FCVTNS:
6860         fcvts(fpf, rd, rn, FPTieEven);
6861         return;
6862       case NEON_FCVTNU:
6863         fcvtu(fpf, rd, rn, FPTieEven);
6864         return;
6865       case NEON_FCVTPS:
6866         fcvts(fpf, rd, rn, FPPositiveInfinity);
6867         return;
6868       case NEON_FCVTPU:
6869         fcvtu(fpf, rd, rn, FPPositiveInfinity);
6870         return;
6871       case NEON_FCVTMS:
6872         fcvts(fpf, rd, rn, FPNegativeInfinity);
6873         return;
6874       case NEON_FCVTMU:
6875         fcvtu(fpf, rd, rn, FPNegativeInfinity);
6876         return;
6877       case NEON_FCVTZS:
6878         fcvts(fpf, rd, rn, FPZero);
6879         return;
6880       case NEON_FCVTZU:
6881         fcvtu(fpf, rd, rn, FPZero);
6882         return;
6883       case NEON_FCVTAS:
6884         fcvts(fpf, rd, rn, FPTieAway);
6885         return;
6886       case NEON_FCVTAU:
6887         fcvtu(fpf, rd, rn, FPTieAway);
6888         return;
6889       case NEON_SCVTF:
6890         scvtf(fpf, rd, rn, 0, fpcr_rounding);
6891         return;
6892       case NEON_UCVTF:
6893         ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6894         return;
6895       case NEON_URSQRTE:
6896         ursqrte(fpf, rd, rn);
6897         return;
6898       case NEON_URECPE:
6899         urecpe(fpf, rd, rn);
6900         return;
6901       case NEON_FRSQRTE:
6902         frsqrte(fpf, rd, rn);
6903         return;
6904       case NEON_FRECPE:
6905         frecpe(fpf, rd, rn, fpcr_rounding);
6906         return;
6907       case NEON_FCMGT_zero:
6908         fcmp_zero(fpf, rd, rn, gt);
6909         return;
6910       case NEON_FCMGE_zero:
6911         fcmp_zero(fpf, rd, rn, ge);
6912         return;
6913       case NEON_FCMEQ_zero:
6914         fcmp_zero(fpf, rd, rn, eq);
6915         return;
6916       case NEON_FCMLE_zero:
6917         fcmp_zero(fpf, rd, rn, le);
6918         return;
6919       case NEON_FCMLT_zero:
6920         fcmp_zero(fpf, rd, rn, lt);
6921         return;
6922       default:
6923         if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
6924             (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
6925           switch (instr->Mask(NEON2RegMiscMask)) {
6926             case NEON_XTN:
6927               xtn(vf, rd, rn);
6928               return;
6929             case NEON_SQXTN:
6930               sqxtn(vf, rd, rn);
6931               return;
6932             case NEON_UQXTN:
6933               uqxtn(vf, rd, rn);
6934               return;
6935             case NEON_SQXTUN:
6936               sqxtun(vf, rd, rn);
6937               return;
6938             case NEON_SHLL:
6939               vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
6940               if (instr->Mask(NEON_Q)) {
6941                 shll2(vf, rd, rn);
6942               } else {
6943                 shll(vf, rd, rn);
6944               }
6945               return;
6946             default:
6947               VIXL_UNIMPLEMENTED();
6948           }
6949         } else {
6950           VIXL_UNIMPLEMENTED();
6951         }
6952     }
6953 
6954     // Only FRINT* instructions fall through the switch above.
6955     frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
6956   }
6957 }
6958 
6959 
VisitNEON2RegMiscFP16(const Instruction * instr)6960 void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
6961   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
6962   NEONFormatDecoder nfd(instr);
6963   VectorFormat fpf = nfd.GetVectorFormat(&map_half);
6964 
6965   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6966 
6967   SimVRegister& rd = ReadVRegister(instr->GetRd());
6968   SimVRegister& rn = ReadVRegister(instr->GetRn());
6969 
6970   switch (instr->Mask(NEON2RegMiscFP16Mask)) {
6971     case NEON_SCVTF_H:
6972       scvtf(fpf, rd, rn, 0, fpcr_rounding);
6973       return;
6974     case NEON_UCVTF_H:
6975       ucvtf(fpf, rd, rn, 0, fpcr_rounding);
6976       return;
6977     case NEON_FCVTNS_H:
6978       fcvts(fpf, rd, rn, FPTieEven);
6979       return;
6980     case NEON_FCVTNU_H:
6981       fcvtu(fpf, rd, rn, FPTieEven);
6982       return;
6983     case NEON_FCVTPS_H:
6984       fcvts(fpf, rd, rn, FPPositiveInfinity);
6985       return;
6986     case NEON_FCVTPU_H:
6987       fcvtu(fpf, rd, rn, FPPositiveInfinity);
6988       return;
6989     case NEON_FCVTMS_H:
6990       fcvts(fpf, rd, rn, FPNegativeInfinity);
6991       return;
6992     case NEON_FCVTMU_H:
6993       fcvtu(fpf, rd, rn, FPNegativeInfinity);
6994       return;
6995     case NEON_FCVTZS_H:
6996       fcvts(fpf, rd, rn, FPZero);
6997       return;
6998     case NEON_FCVTZU_H:
6999       fcvtu(fpf, rd, rn, FPZero);
7000       return;
7001     case NEON_FCVTAS_H:
7002       fcvts(fpf, rd, rn, FPTieAway);
7003       return;
7004     case NEON_FCVTAU_H:
7005       fcvtu(fpf, rd, rn, FPTieAway);
7006       return;
7007     case NEON_FRINTI_H:
7008       frint(fpf, rd, rn, fpcr_rounding, false);
7009       return;
7010     case NEON_FRINTX_H:
7011       frint(fpf, rd, rn, fpcr_rounding, true);
7012       return;
7013     case NEON_FRINTA_H:
7014       frint(fpf, rd, rn, FPTieAway, false);
7015       return;
7016     case NEON_FRINTM_H:
7017       frint(fpf, rd, rn, FPNegativeInfinity, false);
7018       return;
7019     case NEON_FRINTN_H:
7020       frint(fpf, rd, rn, FPTieEven, false);
7021       return;
7022     case NEON_FRINTP_H:
7023       frint(fpf, rd, rn, FPPositiveInfinity, false);
7024       return;
7025     case NEON_FRINTZ_H:
7026       frint(fpf, rd, rn, FPZero, false);
7027       return;
7028     case NEON_FABS_H:
7029       fabs_(fpf, rd, rn);
7030       return;
7031     case NEON_FNEG_H:
7032       fneg(fpf, rd, rn);
7033       return;
7034     case NEON_FSQRT_H:
7035       fsqrt(fpf, rd, rn);
7036       return;
7037     case NEON_FRSQRTE_H:
7038       frsqrte(fpf, rd, rn);
7039       return;
7040     case NEON_FRECPE_H:
7041       frecpe(fpf, rd, rn, fpcr_rounding);
7042       return;
7043     case NEON_FCMGT_H_zero:
7044       fcmp_zero(fpf, rd, rn, gt);
7045       return;
7046     case NEON_FCMGE_H_zero:
7047       fcmp_zero(fpf, rd, rn, ge);
7048       return;
7049     case NEON_FCMEQ_H_zero:
7050       fcmp_zero(fpf, rd, rn, eq);
7051       return;
7052     case NEON_FCMLE_H_zero:
7053       fcmp_zero(fpf, rd, rn, le);
7054       return;
7055     case NEON_FCMLT_H_zero:
7056       fcmp_zero(fpf, rd, rn, lt);
7057       return;
7058     default:
7059       VIXL_UNIMPLEMENTED();
7060       return;
7061   }
7062 }
7063 
7064 
VisitNEON3Same(const Instruction * instr)7065 void Simulator::VisitNEON3Same(const Instruction* instr) {
7066   NEONFormatDecoder nfd(instr);
7067   SimVRegister& rd = ReadVRegister(instr->GetRd());
7068   SimVRegister& rn = ReadVRegister(instr->GetRn());
7069   SimVRegister& rm = ReadVRegister(instr->GetRm());
7070 
7071   if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
7072     VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
7073     switch (instr->Mask(NEON3SameLogicalMask)) {
7074       case NEON_AND:
7075         and_(vf, rd, rn, rm);
7076         break;
7077       case NEON_ORR:
7078         orr(vf, rd, rn, rm);
7079         break;
7080       case NEON_ORN:
7081         orn(vf, rd, rn, rm);
7082         break;
7083       case NEON_EOR:
7084         eor(vf, rd, rn, rm);
7085         break;
7086       case NEON_BIC:
7087         bic(vf, rd, rn, rm);
7088         break;
7089       case NEON_BIF:
7090         bif(vf, rd, rn, rm);
7091         break;
7092       case NEON_BIT:
7093         bit(vf, rd, rn, rm);
7094         break;
7095       case NEON_BSL:
7096         bsl(vf, rd, rd, rn, rm);
7097         break;
7098       default:
7099         VIXL_UNIMPLEMENTED();
7100     }
7101   } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
7102     VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7103     switch (instr->Mask(NEON3SameFPMask)) {
7104       case NEON_FADD:
7105         fadd(vf, rd, rn, rm);
7106         break;
7107       case NEON_FSUB:
7108         fsub(vf, rd, rn, rm);
7109         break;
7110       case NEON_FMUL:
7111         fmul(vf, rd, rn, rm);
7112         break;
7113       case NEON_FDIV:
7114         fdiv(vf, rd, rn, rm);
7115         break;
7116       case NEON_FMAX:
7117         fmax(vf, rd, rn, rm);
7118         break;
7119       case NEON_FMIN:
7120         fmin(vf, rd, rn, rm);
7121         break;
7122       case NEON_FMAXNM:
7123         fmaxnm(vf, rd, rn, rm);
7124         break;
7125       case NEON_FMINNM:
7126         fminnm(vf, rd, rn, rm);
7127         break;
7128       case NEON_FMLA:
7129         fmla(vf, rd, rd, rn, rm);
7130         break;
7131       case NEON_FMLS:
7132         fmls(vf, rd, rd, rn, rm);
7133         break;
7134       case NEON_FMULX:
7135         fmulx(vf, rd, rn, rm);
7136         break;
7137       case NEON_FACGE:
7138         fabscmp(vf, rd, rn, rm, ge);
7139         break;
7140       case NEON_FACGT:
7141         fabscmp(vf, rd, rn, rm, gt);
7142         break;
7143       case NEON_FCMEQ:
7144         fcmp(vf, rd, rn, rm, eq);
7145         break;
7146       case NEON_FCMGE:
7147         fcmp(vf, rd, rn, rm, ge);
7148         break;
7149       case NEON_FCMGT:
7150         fcmp(vf, rd, rn, rm, gt);
7151         break;
7152       case NEON_FRECPS:
7153         frecps(vf, rd, rn, rm);
7154         break;
7155       case NEON_FRSQRTS:
7156         frsqrts(vf, rd, rn, rm);
7157         break;
7158       case NEON_FABD:
7159         fabd(vf, rd, rn, rm);
7160         break;
7161       case NEON_FADDP:
7162         faddp(vf, rd, rn, rm);
7163         break;
7164       case NEON_FMAXP:
7165         fmaxp(vf, rd, rn, rm);
7166         break;
7167       case NEON_FMAXNMP:
7168         fmaxnmp(vf, rd, rn, rm);
7169         break;
7170       case NEON_FMINP:
7171         fminp(vf, rd, rn, rm);
7172         break;
7173       case NEON_FMINNMP:
7174         fminnmp(vf, rd, rn, rm);
7175         break;
7176       default:
7177         // FMLAL{2} and FMLSL{2} have special-case encodings.
7178         switch (instr->Mask(NEON3SameFHMMask)) {
7179           case NEON_FMLAL:
7180             fmlal(vf, rd, rn, rm);
7181             break;
7182           case NEON_FMLAL2:
7183             fmlal2(vf, rd, rn, rm);
7184             break;
7185           case NEON_FMLSL:
7186             fmlsl(vf, rd, rn, rm);
7187             break;
7188           case NEON_FMLSL2:
7189             fmlsl2(vf, rd, rn, rm);
7190             break;
7191           default:
7192             VIXL_UNIMPLEMENTED();
7193         }
7194     }
7195   } else {
7196     VectorFormat vf = nfd.GetVectorFormat();
7197     switch (instr->Mask(NEON3SameMask)) {
7198       case NEON_ADD:
7199         add(vf, rd, rn, rm);
7200         break;
7201       case NEON_ADDP:
7202         addp(vf, rd, rn, rm);
7203         break;
7204       case NEON_CMEQ:
7205         cmp(vf, rd, rn, rm, eq);
7206         break;
7207       case NEON_CMGE:
7208         cmp(vf, rd, rn, rm, ge);
7209         break;
7210       case NEON_CMGT:
7211         cmp(vf, rd, rn, rm, gt);
7212         break;
7213       case NEON_CMHI:
7214         cmp(vf, rd, rn, rm, hi);
7215         break;
7216       case NEON_CMHS:
7217         cmp(vf, rd, rn, rm, hs);
7218         break;
7219       case NEON_CMTST:
7220         cmptst(vf, rd, rn, rm);
7221         break;
7222       case NEON_MLS:
7223         mls(vf, rd, rd, rn, rm);
7224         break;
7225       case NEON_MLA:
7226         mla(vf, rd, rd, rn, rm);
7227         break;
7228       case NEON_MUL:
7229         mul(vf, rd, rn, rm);
7230         break;
7231       case NEON_PMUL:
7232         pmul(vf, rd, rn, rm);
7233         break;
7234       case NEON_SMAX:
7235         smax(vf, rd, rn, rm);
7236         break;
7237       case NEON_SMAXP:
7238         smaxp(vf, rd, rn, rm);
7239         break;
7240       case NEON_SMIN:
7241         smin(vf, rd, rn, rm);
7242         break;
7243       case NEON_SMINP:
7244         sminp(vf, rd, rn, rm);
7245         break;
7246       case NEON_SUB:
7247         sub(vf, rd, rn, rm);
7248         break;
7249       case NEON_UMAX:
7250         umax(vf, rd, rn, rm);
7251         break;
7252       case NEON_UMAXP:
7253         umaxp(vf, rd, rn, rm);
7254         break;
7255       case NEON_UMIN:
7256         umin(vf, rd, rn, rm);
7257         break;
7258       case NEON_UMINP:
7259         uminp(vf, rd, rn, rm);
7260         break;
7261       case NEON_SSHL:
7262         sshl(vf, rd, rn, rm);
7263         break;
7264       case NEON_USHL:
7265         ushl(vf, rd, rn, rm);
7266         break;
7267       case NEON_SABD:
7268         absdiff(vf, rd, rn, rm, true);
7269         break;
7270       case NEON_UABD:
7271         absdiff(vf, rd, rn, rm, false);
7272         break;
7273       case NEON_SABA:
7274         saba(vf, rd, rn, rm);
7275         break;
7276       case NEON_UABA:
7277         uaba(vf, rd, rn, rm);
7278         break;
7279       case NEON_UQADD:
7280         add(vf, rd, rn, rm).UnsignedSaturate(vf);
7281         break;
7282       case NEON_SQADD:
7283         add(vf, rd, rn, rm).SignedSaturate(vf);
7284         break;
7285       case NEON_UQSUB:
7286         sub(vf, rd, rn, rm).UnsignedSaturate(vf);
7287         break;
7288       case NEON_SQSUB:
7289         sub(vf, rd, rn, rm).SignedSaturate(vf);
7290         break;
7291       case NEON_SQDMULH:
7292         sqdmulh(vf, rd, rn, rm);
7293         break;
7294       case NEON_SQRDMULH:
7295         sqrdmulh(vf, rd, rn, rm);
7296         break;
7297       case NEON_UQSHL:
7298         ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
7299         break;
7300       case NEON_SQSHL:
7301         sshl(vf, rd, rn, rm).SignedSaturate(vf);
7302         break;
7303       case NEON_URSHL:
7304         ushl(vf, rd, rn, rm).Round(vf);
7305         break;
7306       case NEON_SRSHL:
7307         sshl(vf, rd, rn, rm).Round(vf);
7308         break;
7309       case NEON_UQRSHL:
7310         ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
7311         break;
7312       case NEON_SQRSHL:
7313         sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
7314         break;
7315       case NEON_UHADD:
7316         add(vf, rd, rn, rm).Uhalve(vf);
7317         break;
7318       case NEON_URHADD:
7319         add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
7320         break;
7321       case NEON_SHADD:
7322         add(vf, rd, rn, rm).Halve(vf);
7323         break;
7324       case NEON_SRHADD:
7325         add(vf, rd, rn, rm).Halve(vf).Round(vf);
7326         break;
7327       case NEON_UHSUB:
7328         sub(vf, rd, rn, rm).Uhalve(vf);
7329         break;
7330       case NEON_SHSUB:
7331         sub(vf, rd, rn, rm).Halve(vf);
7332         break;
7333       default:
7334         VIXL_UNIMPLEMENTED();
7335     }
7336   }
7337 }
7338 
7339 
VisitNEON3SameFP16(const Instruction * instr)7340 void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
7341   NEONFormatDecoder nfd(instr);
7342   SimVRegister& rd = ReadVRegister(instr->GetRd());
7343   SimVRegister& rn = ReadVRegister(instr->GetRn());
7344   SimVRegister& rm = ReadVRegister(instr->GetRm());
7345 
7346   VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
7347   switch (instr->Mask(NEON3SameFP16Mask)) {
7348 #define SIM_FUNC(A, B) \
7349   case NEON_##A##_H:   \
7350     B(vf, rd, rn, rm); \
7351     break;
7352     SIM_FUNC(FMAXNM, fmaxnm);
7353     SIM_FUNC(FADD, fadd);
7354     SIM_FUNC(FMULX, fmulx);
7355     SIM_FUNC(FMAX, fmax);
7356     SIM_FUNC(FRECPS, frecps);
7357     SIM_FUNC(FMINNM, fminnm);
7358     SIM_FUNC(FSUB, fsub);
7359     SIM_FUNC(FMIN, fmin);
7360     SIM_FUNC(FRSQRTS, frsqrts);
7361     SIM_FUNC(FMAXNMP, fmaxnmp);
7362     SIM_FUNC(FADDP, faddp);
7363     SIM_FUNC(FMUL, fmul);
7364     SIM_FUNC(FMAXP, fmaxp);
7365     SIM_FUNC(FDIV, fdiv);
7366     SIM_FUNC(FMINNMP, fminnmp);
7367     SIM_FUNC(FABD, fabd);
7368     SIM_FUNC(FMINP, fminp);
7369 #undef SIM_FUNC
7370     case NEON_FMLA_H:
7371       fmla(vf, rd, rd, rn, rm);
7372       break;
7373     case NEON_FMLS_H:
7374       fmls(vf, rd, rd, rn, rm);
7375       break;
7376     case NEON_FCMEQ_H:
7377       fcmp(vf, rd, rn, rm, eq);
7378       break;
7379     case NEON_FCMGE_H:
7380       fcmp(vf, rd, rn, rm, ge);
7381       break;
7382     case NEON_FACGE_H:
7383       fabscmp(vf, rd, rn, rm, ge);
7384       break;
7385     case NEON_FCMGT_H:
7386       fcmp(vf, rd, rn, rm, gt);
7387       break;
7388     case NEON_FACGT_H:
7389       fabscmp(vf, rd, rn, rm, gt);
7390       break;
7391     default:
7392       VIXL_UNIMPLEMENTED();
7393       break;
7394   }
7395 }
7396 
VisitNEON3SameExtra(const Instruction * instr)7397 void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
7398   NEONFormatDecoder nfd(instr);
7399   SimVRegister& rd = ReadVRegister(instr->GetRd());
7400   SimVRegister& rn = ReadVRegister(instr->GetRn());
7401   SimVRegister& rm = ReadVRegister(instr->GetRm());
7402   int rot = 0;
7403   VectorFormat vf = nfd.GetVectorFormat();
7404 
7405   switch (form_hash_) {
7406     case "fcmla_asimdsame2_c"_h:
7407       rot = instr->GetImmRotFcmlaVec();
7408       fcmla(vf, rd, rn, rm, rd, rot);
7409       break;
7410     case "fcadd_asimdsame2_c"_h:
7411       rot = instr->GetImmRotFcadd();
7412       fcadd(vf, rd, rn, rm, rot);
7413       break;
7414     case "sdot_asimdsame2_d"_h:
7415       sdot(vf, rd, rn, rm);
7416       break;
7417     case "udot_asimdsame2_d"_h:
7418       udot(vf, rd, rn, rm);
7419       break;
7420     case "usdot_asimdsame2_d"_h:
7421       usdot(vf, rd, rn, rm);
7422       break;
7423     case "sqrdmlah_asimdsame2_only"_h:
7424       sqrdmlah(vf, rd, rn, rm);
7425       break;
7426     case "sqrdmlsh_asimdsame2_only"_h:
7427       sqrdmlsh(vf, rd, rn, rm);
7428       break;
7429   }
7430 }
7431 
7432 
VisitNEON3Different(const Instruction * instr)7433 void Simulator::VisitNEON3Different(const Instruction* instr) {
7434   NEONFormatDecoder nfd(instr);
7435   VectorFormat vf = nfd.GetVectorFormat();
7436   VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7437 
7438   SimVRegister& rd = ReadVRegister(instr->GetRd());
7439   SimVRegister& rn = ReadVRegister(instr->GetRn());
7440   SimVRegister& rm = ReadVRegister(instr->GetRm());
7441 
7442   switch (instr->Mask(NEON3DifferentMask)) {
7443     case NEON_PMULL:
7444       pmull(vf_l, rd, rn, rm);
7445       break;
7446     case NEON_PMULL2:
7447       pmull2(vf_l, rd, rn, rm);
7448       break;
7449     case NEON_UADDL:
7450       uaddl(vf_l, rd, rn, rm);
7451       break;
7452     case NEON_UADDL2:
7453       uaddl2(vf_l, rd, rn, rm);
7454       break;
7455     case NEON_SADDL:
7456       saddl(vf_l, rd, rn, rm);
7457       break;
7458     case NEON_SADDL2:
7459       saddl2(vf_l, rd, rn, rm);
7460       break;
7461     case NEON_USUBL:
7462       usubl(vf_l, rd, rn, rm);
7463       break;
7464     case NEON_USUBL2:
7465       usubl2(vf_l, rd, rn, rm);
7466       break;
7467     case NEON_SSUBL:
7468       ssubl(vf_l, rd, rn, rm);
7469       break;
7470     case NEON_SSUBL2:
7471       ssubl2(vf_l, rd, rn, rm);
7472       break;
7473     case NEON_SABAL:
7474       sabal(vf_l, rd, rn, rm);
7475       break;
7476     case NEON_SABAL2:
7477       sabal2(vf_l, rd, rn, rm);
7478       break;
7479     case NEON_UABAL:
7480       uabal(vf_l, rd, rn, rm);
7481       break;
7482     case NEON_UABAL2:
7483       uabal2(vf_l, rd, rn, rm);
7484       break;
7485     case NEON_SABDL:
7486       sabdl(vf_l, rd, rn, rm);
7487       break;
7488     case NEON_SABDL2:
7489       sabdl2(vf_l, rd, rn, rm);
7490       break;
7491     case NEON_UABDL:
7492       uabdl(vf_l, rd, rn, rm);
7493       break;
7494     case NEON_UABDL2:
7495       uabdl2(vf_l, rd, rn, rm);
7496       break;
7497     case NEON_SMLAL:
7498       smlal(vf_l, rd, rn, rm);
7499       break;
7500     case NEON_SMLAL2:
7501       smlal2(vf_l, rd, rn, rm);
7502       break;
7503     case NEON_UMLAL:
7504       umlal(vf_l, rd, rn, rm);
7505       break;
7506     case NEON_UMLAL2:
7507       umlal2(vf_l, rd, rn, rm);
7508       break;
7509     case NEON_SMLSL:
7510       smlsl(vf_l, rd, rn, rm);
7511       break;
7512     case NEON_SMLSL2:
7513       smlsl2(vf_l, rd, rn, rm);
7514       break;
7515     case NEON_UMLSL:
7516       umlsl(vf_l, rd, rn, rm);
7517       break;
7518     case NEON_UMLSL2:
7519       umlsl2(vf_l, rd, rn, rm);
7520       break;
7521     case NEON_SMULL:
7522       smull(vf_l, rd, rn, rm);
7523       break;
7524     case NEON_SMULL2:
7525       smull2(vf_l, rd, rn, rm);
7526       break;
7527     case NEON_UMULL:
7528       umull(vf_l, rd, rn, rm);
7529       break;
7530     case NEON_UMULL2:
7531       umull2(vf_l, rd, rn, rm);
7532       break;
7533     case NEON_SQDMLAL:
7534       sqdmlal(vf_l, rd, rn, rm);
7535       break;
7536     case NEON_SQDMLAL2:
7537       sqdmlal2(vf_l, rd, rn, rm);
7538       break;
7539     case NEON_SQDMLSL:
7540       sqdmlsl(vf_l, rd, rn, rm);
7541       break;
7542     case NEON_SQDMLSL2:
7543       sqdmlsl2(vf_l, rd, rn, rm);
7544       break;
7545     case NEON_SQDMULL:
7546       sqdmull(vf_l, rd, rn, rm);
7547       break;
7548     case NEON_SQDMULL2:
7549       sqdmull2(vf_l, rd, rn, rm);
7550       break;
7551     case NEON_UADDW:
7552       uaddw(vf_l, rd, rn, rm);
7553       break;
7554     case NEON_UADDW2:
7555       uaddw2(vf_l, rd, rn, rm);
7556       break;
7557     case NEON_SADDW:
7558       saddw(vf_l, rd, rn, rm);
7559       break;
7560     case NEON_SADDW2:
7561       saddw2(vf_l, rd, rn, rm);
7562       break;
7563     case NEON_USUBW:
7564       usubw(vf_l, rd, rn, rm);
7565       break;
7566     case NEON_USUBW2:
7567       usubw2(vf_l, rd, rn, rm);
7568       break;
7569     case NEON_SSUBW:
7570       ssubw(vf_l, rd, rn, rm);
7571       break;
7572     case NEON_SSUBW2:
7573       ssubw2(vf_l, rd, rn, rm);
7574       break;
7575     case NEON_ADDHN:
7576       addhn(vf, rd, rn, rm);
7577       break;
7578     case NEON_ADDHN2:
7579       addhn2(vf, rd, rn, rm);
7580       break;
7581     case NEON_RADDHN:
7582       raddhn(vf, rd, rn, rm);
7583       break;
7584     case NEON_RADDHN2:
7585       raddhn2(vf, rd, rn, rm);
7586       break;
7587     case NEON_SUBHN:
7588       subhn(vf, rd, rn, rm);
7589       break;
7590     case NEON_SUBHN2:
7591       subhn2(vf, rd, rn, rm);
7592       break;
7593     case NEON_RSUBHN:
7594       rsubhn(vf, rd, rn, rm);
7595       break;
7596     case NEON_RSUBHN2:
7597       rsubhn2(vf, rd, rn, rm);
7598       break;
7599     default:
7600       VIXL_UNIMPLEMENTED();
7601   }
7602 }
7603 
7604 
VisitNEONAcrossLanes(const Instruction * instr)7605 void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
7606   NEONFormatDecoder nfd(instr);
7607 
7608   static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
7609 
7610   SimVRegister& rd = ReadVRegister(instr->GetRd());
7611   SimVRegister& rn = ReadVRegister(instr->GetRn());
7612 
7613   if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
7614     VectorFormat vf = nfd.GetVectorFormat(&map_half);
7615     switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
7616       case NEON_FMAXV_H:
7617         fmaxv(vf, rd, rn);
7618         break;
7619       case NEON_FMINV_H:
7620         fminv(vf, rd, rn);
7621         break;
7622       case NEON_FMAXNMV_H:
7623         fmaxnmv(vf, rd, rn);
7624         break;
7625       case NEON_FMINNMV_H:
7626         fminnmv(vf, rd, rn);
7627         break;
7628       default:
7629         VIXL_UNIMPLEMENTED();
7630     }
7631   } else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
7632     // The input operand's VectorFormat is passed for these instructions.
7633     VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7634 
7635     switch (instr->Mask(NEONAcrossLanesFPMask)) {
7636       case NEON_FMAXV:
7637         fmaxv(vf, rd, rn);
7638         break;
7639       case NEON_FMINV:
7640         fminv(vf, rd, rn);
7641         break;
7642       case NEON_FMAXNMV:
7643         fmaxnmv(vf, rd, rn);
7644         break;
7645       case NEON_FMINNMV:
7646         fminnmv(vf, rd, rn);
7647         break;
7648       default:
7649         VIXL_UNIMPLEMENTED();
7650     }
7651   } else {
7652     VectorFormat vf = nfd.GetVectorFormat();
7653 
7654     switch (instr->Mask(NEONAcrossLanesMask)) {
7655       case NEON_ADDV:
7656         addv(vf, rd, rn);
7657         break;
7658       case NEON_SMAXV:
7659         smaxv(vf, rd, rn);
7660         break;
7661       case NEON_SMINV:
7662         sminv(vf, rd, rn);
7663         break;
7664       case NEON_UMAXV:
7665         umaxv(vf, rd, rn);
7666         break;
7667       case NEON_UMINV:
7668         uminv(vf, rd, rn);
7669         break;
7670       case NEON_SADDLV:
7671         saddlv(vf, rd, rn);
7672         break;
7673       case NEON_UADDLV:
7674         uaddlv(vf, rd, rn);
7675         break;
7676       default:
7677         VIXL_UNIMPLEMENTED();
7678     }
7679   }
7680 }
7681 
SimulateNEONMulByElementLong(const Instruction * instr)7682 void Simulator::SimulateNEONMulByElementLong(const Instruction* instr) {
7683   NEONFormatDecoder nfd(instr);
7684   VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7685 
7686   SimVRegister& rd = ReadVRegister(instr->GetRd());
7687   SimVRegister& rn = ReadVRegister(instr->GetRn());
7688 
7689   int rm_reg = instr->GetRm();
7690   int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
7691   if (instr->GetNEONSize() == 1) {
7692     rm_reg = instr->GetRmLow16();
7693     index = (index << 1) | instr->GetNEONM();
7694   }
7695   SimVRegister& rm = ReadVRegister(rm_reg);
7696 
7697   SimVRegister temp;
7698   VectorFormat indexform =
7699       VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vf));
7700   dup_element(indexform, temp, rm, index);
7701 
7702   bool is_2 = instr->Mask(NEON_Q) ? true : false;
7703 
7704   switch (form_hash_) {
7705     case "smull_asimdelem_l"_h:
7706       smull(vf, rd, rn, temp, is_2);
7707       break;
7708     case "umull_asimdelem_l"_h:
7709       umull(vf, rd, rn, temp, is_2);
7710       break;
7711     case "smlal_asimdelem_l"_h:
7712       smlal(vf, rd, rn, temp, is_2);
7713       break;
7714     case "umlal_asimdelem_l"_h:
7715       umlal(vf, rd, rn, temp, is_2);
7716       break;
7717     case "smlsl_asimdelem_l"_h:
7718       smlsl(vf, rd, rn, temp, is_2);
7719       break;
7720     case "umlsl_asimdelem_l"_h:
7721       umlsl(vf, rd, rn, temp, is_2);
7722       break;
7723     case "sqdmull_asimdelem_l"_h:
7724       sqdmull(vf, rd, rn, temp, is_2);
7725       break;
7726     case "sqdmlal_asimdelem_l"_h:
7727       sqdmlal(vf, rd, rn, temp, is_2);
7728       break;
7729     case "sqdmlsl_asimdelem_l"_h:
7730       sqdmlsl(vf, rd, rn, temp, is_2);
7731       break;
7732     default:
7733       VIXL_UNREACHABLE();
7734   }
7735 }
7736 
SimulateNEONFPMulByElementLong(const Instruction * instr)7737 void Simulator::SimulateNEONFPMulByElementLong(const Instruction* instr) {
7738   VectorFormat vform = instr->GetNEONQ() ? kFormat4S : kFormat2S;
7739   SimVRegister& rd = ReadVRegister(instr->GetRd());
7740   SimVRegister& rn = ReadVRegister(instr->GetRn());
7741   SimVRegister& rm = ReadVRegister(instr->GetRmLow16());
7742 
7743   int index =
7744       (instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
7745 
7746   switch (form_hash_) {
7747     case "fmlal_asimdelem_lh"_h:
7748       fmlal(vform, rd, rn, rm, index);
7749       break;
7750     case "fmlal2_asimdelem_lh"_h:
7751       fmlal2(vform, rd, rn, rm, index);
7752       break;
7753     case "fmlsl_asimdelem_lh"_h:
7754       fmlsl(vform, rd, rn, rm, index);
7755       break;
7756     case "fmlsl2_asimdelem_lh"_h:
7757       fmlsl2(vform, rd, rn, rm, index);
7758       break;
7759     default:
7760       VIXL_UNREACHABLE();
7761   }
7762 }
7763 
SimulateNEONFPMulByElement(const Instruction * instr)7764 void Simulator::SimulateNEONFPMulByElement(const Instruction* instr) {
7765   NEONFormatDecoder nfd(instr);
7766   static const NEONFormatMap map =
7767       {{23, 22, 30},
7768        {NF_4H, NF_8H, NF_UNDEF, NF_UNDEF, NF_2S, NF_4S, NF_UNDEF, NF_2D}};
7769   VectorFormat vform = nfd.GetVectorFormat(&map);
7770 
7771   SimVRegister& rd = ReadVRegister(instr->GetRd());
7772   SimVRegister& rn = ReadVRegister(instr->GetRn());
7773 
7774   int rm_reg = instr->GetRm();
7775   int index =
7776       (instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
7777 
7778   if ((vform == kFormat4H) || (vform == kFormat8H)) {
7779     rm_reg &= 0xf;
7780   } else if ((vform == kFormat2S) || (vform == kFormat4S)) {
7781     index >>= 1;
7782   } else {
7783     VIXL_ASSERT(vform == kFormat2D);
7784     VIXL_ASSERT(instr->GetNEONL() == 0);
7785     index >>= 2;
7786   }
7787 
7788   SimVRegister& rm = ReadVRegister(rm_reg);
7789 
7790   switch (form_hash_) {
7791     case "fmul_asimdelem_rh_h"_h:
7792     case "fmul_asimdelem_r_sd"_h:
7793       fmul(vform, rd, rn, rm, index);
7794       break;
7795     case "fmla_asimdelem_rh_h"_h:
7796     case "fmla_asimdelem_r_sd"_h:
7797       fmla(vform, rd, rn, rm, index);
7798       break;
7799     case "fmls_asimdelem_rh_h"_h:
7800     case "fmls_asimdelem_r_sd"_h:
7801       fmls(vform, rd, rn, rm, index);
7802       break;
7803     case "fmulx_asimdelem_rh_h"_h:
7804     case "fmulx_asimdelem_r_sd"_h:
7805       fmulx(vform, rd, rn, rm, index);
7806       break;
7807     default:
7808       VIXL_UNREACHABLE();
7809   }
7810 }
7811 
SimulateNEONComplexMulByElement(const Instruction * instr)7812 void Simulator::SimulateNEONComplexMulByElement(const Instruction* instr) {
7813   VectorFormat vform = instr->GetNEONQ() ? kFormat8H : kFormat4H;
7814   SimVRegister& rd = ReadVRegister(instr->GetRd());
7815   SimVRegister& rn = ReadVRegister(instr->GetRn());
7816   SimVRegister& rm = ReadVRegister(instr->GetRm());
7817   int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
7818 
7819   switch (form_hash_) {
7820     case "fcmla_asimdelem_c_s"_h:
7821       vform = kFormat4S;
7822       index >>= 1;
7823       VIXL_FALLTHROUGH();
7824     case "fcmla_asimdelem_c_h"_h:
7825       fcmla(vform, rd, rn, rm, index, instr->GetImmRotFcmlaSca());
7826       break;
7827     default:
7828       VIXL_UNREACHABLE();
7829   }
7830 }
7831 
SimulateNEONDotProdByElement(const Instruction * instr)7832 void Simulator::SimulateNEONDotProdByElement(const Instruction* instr) {
7833   VectorFormat vform = instr->GetNEONQ() ? kFormat4S : kFormat2S;
7834 
7835   SimVRegister& rd = ReadVRegister(instr->GetRd());
7836   SimVRegister& rn = ReadVRegister(instr->GetRn());
7837   SimVRegister& rm = ReadVRegister(instr->GetRm());
7838   int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
7839 
7840   SimVRegister temp;
7841   // NEON indexed `dot` allows the index value exceed the register size.
7842   // Promote the format to Q-sized vector format before the duplication.
7843   dup_elements_to_segments(VectorFormatFillQ(vform), temp, rm, index);
7844 
7845   switch (form_hash_) {
7846     case "sdot_asimdelem_d"_h:
7847       sdot(vform, rd, rn, temp);
7848       break;
7849     case "udot_asimdelem_d"_h:
7850       udot(vform, rd, rn, temp);
7851       break;
7852     case "sudot_asimdelem_d"_h:
7853       usdot(vform, rd, temp, rn);
7854       break;
7855     case "usdot_asimdelem_d"_h:
7856       usdot(vform, rd, rn, temp);
7857       break;
7858   }
7859 }
7860 
VisitNEONByIndexedElement(const Instruction * instr)7861 void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
7862   NEONFormatDecoder nfd(instr);
7863   VectorFormat vform = nfd.GetVectorFormat();
7864 
7865   SimVRegister& rd = ReadVRegister(instr->GetRd());
7866   SimVRegister& rn = ReadVRegister(instr->GetRn());
7867 
7868   int rm_reg = instr->GetRm();
7869   int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
7870 
7871   if ((vform == kFormat4H) || (vform == kFormat8H)) {
7872     rm_reg &= 0xf;
7873     index = (index << 1) | instr->GetNEONM();
7874   }
7875 
7876   SimVRegister& rm = ReadVRegister(rm_reg);
7877 
7878   switch (form_hash_) {
7879     case "mul_asimdelem_r"_h:
7880       mul(vform, rd, rn, rm, index);
7881       break;
7882     case "mla_asimdelem_r"_h:
7883       mla(vform, rd, rn, rm, index);
7884       break;
7885     case "mls_asimdelem_r"_h:
7886       mls(vform, rd, rn, rm, index);
7887       break;
7888     case "sqdmulh_asimdelem_r"_h:
7889       sqdmulh(vform, rd, rn, rm, index);
7890       break;
7891     case "sqrdmulh_asimdelem_r"_h:
7892       sqrdmulh(vform, rd, rn, rm, index);
7893       break;
7894     case "sqrdmlah_asimdelem_r"_h:
7895       sqrdmlah(vform, rd, rn, rm, index);
7896       break;
7897     case "sqrdmlsh_asimdelem_r"_h:
7898       sqrdmlsh(vform, rd, rn, rm, index);
7899       break;
7900   }
7901 }
7902 
7903 
VisitNEONCopy(const Instruction * instr)7904 void Simulator::VisitNEONCopy(const Instruction* instr) {
7905   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
7906   VectorFormat vf = nfd.GetVectorFormat();
7907 
7908   SimVRegister& rd = ReadVRegister(instr->GetRd());
7909   SimVRegister& rn = ReadVRegister(instr->GetRn());
7910   int imm5 = instr->GetImmNEON5();
7911   int tz = CountTrailingZeros(imm5, 32);
7912   int reg_index = ExtractSignedBitfield32(31, tz + 1, imm5);
7913 
7914   if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
7915     int imm4 = instr->GetImmNEON4();
7916     int rn_index = ExtractSignedBitfield32(31, tz, imm4);
7917     ins_element(vf, rd, reg_index, rn, rn_index);
7918   } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
7919     ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
7920   } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
7921     uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
7922     value &= MaxUintFromFormat(vf);
7923     WriteXRegister(instr->GetRd(), value);
7924   } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
7925     int64_t value = LogicVRegister(rn).Int(vf, reg_index);
7926     if (instr->GetNEONQ()) {
7927       WriteXRegister(instr->GetRd(), value);
7928     } else {
7929       WriteWRegister(instr->GetRd(), (int32_t)value);
7930     }
7931   } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
7932     dup_element(vf, rd, rn, reg_index);
7933   } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
7934     dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
7935   } else {
7936     VIXL_UNIMPLEMENTED();
7937   }
7938 }
7939 
7940 
VisitNEONExtract(const Instruction * instr)7941 void Simulator::VisitNEONExtract(const Instruction* instr) {
7942   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
7943   VectorFormat vf = nfd.GetVectorFormat();
7944   SimVRegister& rd = ReadVRegister(instr->GetRd());
7945   SimVRegister& rn = ReadVRegister(instr->GetRn());
7946   SimVRegister& rm = ReadVRegister(instr->GetRm());
7947   if (instr->Mask(NEONExtractMask) == NEON_EXT) {
7948     int index = instr->GetImmNEONExt();
7949     ext(vf, rd, rn, rm, index);
7950   } else {
7951     VIXL_UNIMPLEMENTED();
7952   }
7953 }
7954 
7955 
NEONLoadStoreMultiStructHelper(const Instruction * instr,AddrMode addr_mode)7956 void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
7957                                                AddrMode addr_mode) {
7958   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
7959   VectorFormat vf = nfd.GetVectorFormat();
7960 
7961   uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
7962   int reg_size = RegisterSizeInBytesFromFormat(vf);
7963 
7964   int reg[4];
7965   uint64_t addr[4];
7966   for (int i = 0; i < 4; i++) {
7967     reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
7968     addr[i] = addr_base + (i * reg_size);
7969   }
7970   int struct_parts = 1;
7971   int reg_count = 1;
7972   bool log_read = true;
7973 
7974   // Bit 23 determines whether this is an offset or post-index addressing mode.
7975   // In offset mode, bits 20 to 16 should be zero; these bits encode the
7976   // register or immediate in post-index mode.
7977   if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
7978     VIXL_UNREACHABLE();
7979   }
7980 
7981   // We use the PostIndex mask here, as it works in this case for both Offset
7982   // and PostIndex addressing.
7983   switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
7984     case NEON_LD1_4v:
7985     case NEON_LD1_4v_post:
7986       ld1(vf, ReadVRegister(reg[3]), addr[3]);
7987       reg_count++;
7988       VIXL_FALLTHROUGH();
7989     case NEON_LD1_3v:
7990     case NEON_LD1_3v_post:
7991       ld1(vf, ReadVRegister(reg[2]), addr[2]);
7992       reg_count++;
7993       VIXL_FALLTHROUGH();
7994     case NEON_LD1_2v:
7995     case NEON_LD1_2v_post:
7996       ld1(vf, ReadVRegister(reg[1]), addr[1]);
7997       reg_count++;
7998       VIXL_FALLTHROUGH();
7999     case NEON_LD1_1v:
8000     case NEON_LD1_1v_post:
8001       ld1(vf, ReadVRegister(reg[0]), addr[0]);
8002       break;
8003     case NEON_ST1_4v:
8004     case NEON_ST1_4v_post:
8005       st1(vf, ReadVRegister(reg[3]), addr[3]);
8006       reg_count++;
8007       VIXL_FALLTHROUGH();
8008     case NEON_ST1_3v:
8009     case NEON_ST1_3v_post:
8010       st1(vf, ReadVRegister(reg[2]), addr[2]);
8011       reg_count++;
8012       VIXL_FALLTHROUGH();
8013     case NEON_ST1_2v:
8014     case NEON_ST1_2v_post:
8015       st1(vf, ReadVRegister(reg[1]), addr[1]);
8016       reg_count++;
8017       VIXL_FALLTHROUGH();
8018     case NEON_ST1_1v:
8019     case NEON_ST1_1v_post:
8020       st1(vf, ReadVRegister(reg[0]), addr[0]);
8021       log_read = false;
8022       break;
8023     case NEON_LD2_post:
8024     case NEON_LD2:
8025       ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
8026       struct_parts = 2;
8027       reg_count = 2;
8028       break;
8029     case NEON_ST2:
8030     case NEON_ST2_post:
8031       st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0]);
8032       struct_parts = 2;
8033       reg_count = 2;
8034       log_read = false;
8035       break;
8036     case NEON_LD3_post:
8037     case NEON_LD3:
8038       ld3(vf,
8039           ReadVRegister(reg[0]),
8040           ReadVRegister(reg[1]),
8041           ReadVRegister(reg[2]),
8042           addr[0]);
8043       struct_parts = 3;
8044       reg_count = 3;
8045       break;
8046     case NEON_ST3:
8047     case NEON_ST3_post:
8048       st3(vf,
8049           ReadVRegister(reg[0]),
8050           ReadVRegister(reg[1]),
8051           ReadVRegister(reg[2]),
8052           addr[0]);
8053       struct_parts = 3;
8054       reg_count = 3;
8055       log_read = false;
8056       break;
8057     case NEON_ST4:
8058     case NEON_ST4_post:
8059       st4(vf,
8060           ReadVRegister(reg[0]),
8061           ReadVRegister(reg[1]),
8062           ReadVRegister(reg[2]),
8063           ReadVRegister(reg[3]),
8064           addr[0]);
8065       struct_parts = 4;
8066       reg_count = 4;
8067       log_read = false;
8068       break;
8069     case NEON_LD4_post:
8070     case NEON_LD4:
8071       ld4(vf,
8072           ReadVRegister(reg[0]),
8073           ReadVRegister(reg[1]),
8074           ReadVRegister(reg[2]),
8075           ReadVRegister(reg[3]),
8076           addr[0]);
8077       struct_parts = 4;
8078       reg_count = 4;
8079       break;
8080     default:
8081       VIXL_UNIMPLEMENTED();
8082   }
8083 
8084   bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
8085   if (do_trace) {
8086     PrintRegisterFormat print_format =
8087         GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8088     const char* op;
8089     if (log_read) {
8090       op = "<-";
8091     } else {
8092       op = "->";
8093       // Stores don't represent a change to the source register's value, so only
8094       // print the relevant part of the value.
8095       print_format = GetPrintRegPartial(print_format);
8096     }
8097 
8098     VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
8099     for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
8100       uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
8101       PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
8102     }
8103   }
8104 
8105   if (addr_mode == PostIndex) {
8106     int rm = instr->GetRm();
8107     // The immediate post index addressing mode is indicated by rm = 31.
8108     // The immediate is implied by the number of vector registers used.
8109     addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
8110                             : ReadXRegister(rm);
8111     WriteXRegister(instr->GetRn(), addr_base);
8112   } else {
8113     VIXL_ASSERT(addr_mode == Offset);
8114   }
8115 }
8116 
8117 
VisitNEONLoadStoreMultiStruct(const Instruction * instr)8118 void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
8119   NEONLoadStoreMultiStructHelper(instr, Offset);
8120 }
8121 
8122 
VisitNEONLoadStoreMultiStructPostIndex(const Instruction * instr)8123 void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
8124     const Instruction* instr) {
8125   NEONLoadStoreMultiStructHelper(instr, PostIndex);
8126 }
8127 
8128 
NEONLoadStoreSingleStructHelper(const Instruction * instr,AddrMode addr_mode)8129 void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
8130                                                 AddrMode addr_mode) {
8131   uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
8132   int rt = instr->GetRt();
8133 
8134   // Bit 23 determines whether this is an offset or post-index addressing mode.
8135   // In offset mode, bits 20 to 16 should be zero; these bits encode the
8136   // register or immediate in post-index mode.
8137   if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
8138     VIXL_UNREACHABLE();
8139   }
8140 
8141   // We use the PostIndex mask here, as it works in this case for both Offset
8142   // and PostIndex addressing.
8143   bool do_load = false;
8144 
8145   bool replicating = false;
8146 
8147   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
8148   VectorFormat vf_t = nfd.GetVectorFormat();
8149 
8150   VectorFormat vf = kFormat16B;
8151   switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
8152     case NEON_LD1_b:
8153     case NEON_LD1_b_post:
8154     case NEON_LD2_b:
8155     case NEON_LD2_b_post:
8156     case NEON_LD3_b:
8157     case NEON_LD3_b_post:
8158     case NEON_LD4_b:
8159     case NEON_LD4_b_post:
8160       do_load = true;
8161       VIXL_FALLTHROUGH();
8162     case NEON_ST1_b:
8163     case NEON_ST1_b_post:
8164     case NEON_ST2_b:
8165     case NEON_ST2_b_post:
8166     case NEON_ST3_b:
8167     case NEON_ST3_b_post:
8168     case NEON_ST4_b:
8169     case NEON_ST4_b_post:
8170       break;
8171 
8172     case NEON_LD1_h:
8173     case NEON_LD1_h_post:
8174     case NEON_LD2_h:
8175     case NEON_LD2_h_post:
8176     case NEON_LD3_h:
8177     case NEON_LD3_h_post:
8178     case NEON_LD4_h:
8179     case NEON_LD4_h_post:
8180       do_load = true;
8181       VIXL_FALLTHROUGH();
8182     case NEON_ST1_h:
8183     case NEON_ST1_h_post:
8184     case NEON_ST2_h:
8185     case NEON_ST2_h_post:
8186     case NEON_ST3_h:
8187     case NEON_ST3_h_post:
8188     case NEON_ST4_h:
8189     case NEON_ST4_h_post:
8190       vf = kFormat8H;
8191       break;
8192     case NEON_LD1_s:
8193     case NEON_LD1_s_post:
8194     case NEON_LD2_s:
8195     case NEON_LD2_s_post:
8196     case NEON_LD3_s:
8197     case NEON_LD3_s_post:
8198     case NEON_LD4_s:
8199     case NEON_LD4_s_post:
8200       do_load = true;
8201       VIXL_FALLTHROUGH();
8202     case NEON_ST1_s:
8203     case NEON_ST1_s_post:
8204     case NEON_ST2_s:
8205     case NEON_ST2_s_post:
8206     case NEON_ST3_s:
8207     case NEON_ST3_s_post:
8208     case NEON_ST4_s:
8209     case NEON_ST4_s_post: {
8210       VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
8211       VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
8212                          NEON_LD1_d_post);
8213       VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
8214       VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
8215                          NEON_ST1_d_post);
8216       vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
8217       break;
8218     }
8219 
8220     case NEON_LD1R:
8221     case NEON_LD1R_post:
8222     case NEON_LD2R:
8223     case NEON_LD2R_post:
8224     case NEON_LD3R:
8225     case NEON_LD3R_post:
8226     case NEON_LD4R:
8227     case NEON_LD4R_post:
8228       vf = vf_t;
8229       do_load = true;
8230       replicating = true;
8231       break;
8232 
8233     default:
8234       VIXL_UNIMPLEMENTED();
8235   }
8236 
8237   int index_shift = LaneSizeInBytesLog2FromFormat(vf);
8238   int lane = instr->GetNEONLSIndex(index_shift);
8239   int reg_count = 0;
8240   int rt2 = (rt + 1) % kNumberOfVRegisters;
8241   int rt3 = (rt2 + 1) % kNumberOfVRegisters;
8242   int rt4 = (rt3 + 1) % kNumberOfVRegisters;
8243   switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
8244     case NEONLoadStoreSingle1:
8245       reg_count = 1;
8246       if (replicating) {
8247         VIXL_ASSERT(do_load);
8248         ld1r(vf, ReadVRegister(rt), addr);
8249       } else if (do_load) {
8250         ld1(vf, ReadVRegister(rt), lane, addr);
8251       } else {
8252         st1(vf, ReadVRegister(rt), lane, addr);
8253       }
8254       break;
8255     case NEONLoadStoreSingle2:
8256       reg_count = 2;
8257       if (replicating) {
8258         VIXL_ASSERT(do_load);
8259         ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr);
8260       } else if (do_load) {
8261         ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
8262       } else {
8263         st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr);
8264       }
8265       break;
8266     case NEONLoadStoreSingle3:
8267       reg_count = 3;
8268       if (replicating) {
8269         VIXL_ASSERT(do_load);
8270         ld3r(vf,
8271              ReadVRegister(rt),
8272              ReadVRegister(rt2),
8273              ReadVRegister(rt3),
8274              addr);
8275       } else if (do_load) {
8276         ld3(vf,
8277             ReadVRegister(rt),
8278             ReadVRegister(rt2),
8279             ReadVRegister(rt3),
8280             lane,
8281             addr);
8282       } else {
8283         st3(vf,
8284             ReadVRegister(rt),
8285             ReadVRegister(rt2),
8286             ReadVRegister(rt3),
8287             lane,
8288             addr);
8289       }
8290       break;
8291     case NEONLoadStoreSingle4:
8292       reg_count = 4;
8293       if (replicating) {
8294         VIXL_ASSERT(do_load);
8295         ld4r(vf,
8296              ReadVRegister(rt),
8297              ReadVRegister(rt2),
8298              ReadVRegister(rt3),
8299              ReadVRegister(rt4),
8300              addr);
8301       } else if (do_load) {
8302         ld4(vf,
8303             ReadVRegister(rt),
8304             ReadVRegister(rt2),
8305             ReadVRegister(rt3),
8306             ReadVRegister(rt4),
8307             lane,
8308             addr);
8309       } else {
8310         st4(vf,
8311             ReadVRegister(rt),
8312             ReadVRegister(rt2),
8313             ReadVRegister(rt3),
8314             ReadVRegister(rt4),
8315             lane,
8316             addr);
8317       }
8318       break;
8319     default:
8320       VIXL_UNIMPLEMENTED();
8321   }
8322 
8323   // Trace registers and/or memory writes.
8324   PrintRegisterFormat print_format =
8325       GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8326   if (do_load) {
8327     if (ShouldTraceVRegs()) {
8328       if (replicating) {
8329         PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
8330       } else {
8331         PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
8332       }
8333     }
8334   } else {
8335     if (ShouldTraceWrites()) {
8336       // Stores don't represent a change to the source register's value, so only
8337       // print the relevant part of the value.
8338       print_format = GetPrintRegPartial(print_format);
8339       PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
8340     }
8341   }
8342 
8343   if (addr_mode == PostIndex) {
8344     int rm = instr->GetRm();
8345     int lane_size = LaneSizeInBytesFromFormat(vf);
8346     WriteXRegister(instr->GetRn(),
8347                    addr + ((rm == 31) ? (reg_count * lane_size)
8348                                       : ReadXRegister(rm)));
8349   }
8350 }
8351 
8352 
VisitNEONLoadStoreSingleStruct(const Instruction * instr)8353 void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
8354   NEONLoadStoreSingleStructHelper(instr, Offset);
8355 }
8356 
8357 
VisitNEONLoadStoreSingleStructPostIndex(const Instruction * instr)8358 void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
8359     const Instruction* instr) {
8360   NEONLoadStoreSingleStructHelper(instr, PostIndex);
8361 }
8362 
8363 
VisitNEONModifiedImmediate(const Instruction * instr)8364 void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
8365   SimVRegister& rd = ReadVRegister(instr->GetRd());
8366   int cmode = instr->GetNEONCmode();
8367   int cmode_3_1 = (cmode >> 1) & 7;
8368   int cmode_3 = (cmode >> 3) & 1;
8369   int cmode_2 = (cmode >> 2) & 1;
8370   int cmode_1 = (cmode >> 1) & 1;
8371   int cmode_0 = cmode & 1;
8372   int half_enc = instr->ExtractBit(11);
8373   int q = instr->GetNEONQ();
8374   int op_bit = instr->GetNEONModImmOp();
8375   uint64_t imm8 = instr->GetImmNEONabcdefgh();
8376   // Find the format and immediate value
8377   uint64_t imm = 0;
8378   VectorFormat vform = kFormatUndefined;
8379   switch (cmode_3_1) {
8380     case 0x0:
8381     case 0x1:
8382     case 0x2:
8383     case 0x3:
8384       vform = (q == 1) ? kFormat4S : kFormat2S;
8385       imm = imm8 << (8 * cmode_3_1);
8386       break;
8387     case 0x4:
8388     case 0x5:
8389       vform = (q == 1) ? kFormat8H : kFormat4H;
8390       imm = imm8 << (8 * cmode_1);
8391       break;
8392     case 0x6:
8393       vform = (q == 1) ? kFormat4S : kFormat2S;
8394       if (cmode_0 == 0) {
8395         imm = imm8 << 8 | 0x000000ff;
8396       } else {
8397         imm = imm8 << 16 | 0x0000ffff;
8398       }
8399       break;
8400     case 0x7:
8401       if (cmode_0 == 0 && op_bit == 0) {
8402         vform = q ? kFormat16B : kFormat8B;
8403         imm = imm8;
8404       } else if (cmode_0 == 0 && op_bit == 1) {
8405         vform = q ? kFormat2D : kFormat1D;
8406         imm = 0;
8407         for (int i = 0; i < 8; ++i) {
8408           if (imm8 & (1 << i)) {
8409             imm |= (UINT64_C(0xff) << (8 * i));
8410           }
8411         }
8412       } else {  // cmode_0 == 1, cmode == 0xf.
8413         if (half_enc == 1) {
8414           vform = q ? kFormat8H : kFormat4H;
8415           imm = Float16ToRawbits(instr->GetImmNEONFP16());
8416         } else if (op_bit == 0) {
8417           vform = q ? kFormat4S : kFormat2S;
8418           imm = FloatToRawbits(instr->GetImmNEONFP32());
8419         } else if (q == 1) {
8420           vform = kFormat2D;
8421           imm = DoubleToRawbits(instr->GetImmNEONFP64());
8422         } else {
8423           VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
8424           VisitUnallocated(instr);
8425         }
8426       }
8427       break;
8428     default:
8429       VIXL_UNREACHABLE();
8430       break;
8431   }
8432 
8433   // Find the operation
8434   NEONModifiedImmediateOp op;
8435   if (cmode_3 == 0) {
8436     if (cmode_0 == 0) {
8437       op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8438     } else {  // cmode<0> == '1'
8439       op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8440     }
8441   } else {  // cmode<3> == '1'
8442     if (cmode_2 == 0) {
8443       if (cmode_0 == 0) {
8444         op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8445       } else {  // cmode<0> == '1'
8446         op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8447       }
8448     } else {  // cmode<2> == '1'
8449       if (cmode_1 == 0) {
8450         op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8451       } else {  // cmode<1> == '1'
8452         if (cmode_0 == 0) {
8453           op = NEONModifiedImmediate_MOVI;
8454         } else {  // cmode<0> == '1'
8455           op = NEONModifiedImmediate_MOVI;
8456         }
8457       }
8458     }
8459   }
8460 
8461   // Call the logic function
8462   if (op == NEONModifiedImmediate_ORR) {
8463     orr(vform, rd, rd, imm);
8464   } else if (op == NEONModifiedImmediate_BIC) {
8465     bic(vform, rd, rd, imm);
8466   } else if (op == NEONModifiedImmediate_MOVI) {
8467     movi(vform, rd, imm);
8468   } else if (op == NEONModifiedImmediate_MVNI) {
8469     mvni(vform, rd, imm);
8470   } else {
8471     VisitUnimplemented(instr);
8472   }
8473 }
8474 
8475 
VisitNEONScalar2RegMisc(const Instruction * instr)8476 void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
8477   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8478   VectorFormat vf = nfd.GetVectorFormat();
8479 
8480   SimVRegister& rd = ReadVRegister(instr->GetRd());
8481   SimVRegister& rn = ReadVRegister(instr->GetRn());
8482 
8483   if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
8484     // These instructions all use a two bit size field, except NOT and RBIT,
8485     // which use the field to encode the operation.
8486     switch (instr->Mask(NEONScalar2RegMiscMask)) {
8487       case NEON_CMEQ_zero_scalar:
8488         cmp(vf, rd, rn, 0, eq);
8489         break;
8490       case NEON_CMGE_zero_scalar:
8491         cmp(vf, rd, rn, 0, ge);
8492         break;
8493       case NEON_CMGT_zero_scalar:
8494         cmp(vf, rd, rn, 0, gt);
8495         break;
8496       case NEON_CMLT_zero_scalar:
8497         cmp(vf, rd, rn, 0, lt);
8498         break;
8499       case NEON_CMLE_zero_scalar:
8500         cmp(vf, rd, rn, 0, le);
8501         break;
8502       case NEON_ABS_scalar:
8503         abs(vf, rd, rn);
8504         break;
8505       case NEON_SQABS_scalar:
8506         abs(vf, rd, rn).SignedSaturate(vf);
8507         break;
8508       case NEON_NEG_scalar:
8509         neg(vf, rd, rn);
8510         break;
8511       case NEON_SQNEG_scalar:
8512         neg(vf, rd, rn).SignedSaturate(vf);
8513         break;
8514       case NEON_SUQADD_scalar:
8515         suqadd(vf, rd, rd, rn);
8516         break;
8517       case NEON_USQADD_scalar:
8518         usqadd(vf, rd, rd, rn);
8519         break;
8520       default:
8521         VIXL_UNIMPLEMENTED();
8522         break;
8523     }
8524   } else {
8525     VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8526     FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8527 
8528     // These instructions all use a one bit size field, except SQXTUN, SQXTN
8529     // and UQXTN, which use a two bit size field.
8530     switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
8531       case NEON_FRECPE_scalar:
8532         frecpe(fpf, rd, rn, fpcr_rounding);
8533         break;
8534       case NEON_FRECPX_scalar:
8535         frecpx(fpf, rd, rn);
8536         break;
8537       case NEON_FRSQRTE_scalar:
8538         frsqrte(fpf, rd, rn);
8539         break;
8540       case NEON_FCMGT_zero_scalar:
8541         fcmp_zero(fpf, rd, rn, gt);
8542         break;
8543       case NEON_FCMGE_zero_scalar:
8544         fcmp_zero(fpf, rd, rn, ge);
8545         break;
8546       case NEON_FCMEQ_zero_scalar:
8547         fcmp_zero(fpf, rd, rn, eq);
8548         break;
8549       case NEON_FCMLE_zero_scalar:
8550         fcmp_zero(fpf, rd, rn, le);
8551         break;
8552       case NEON_FCMLT_zero_scalar:
8553         fcmp_zero(fpf, rd, rn, lt);
8554         break;
8555       case NEON_SCVTF_scalar:
8556         scvtf(fpf, rd, rn, 0, fpcr_rounding);
8557         break;
8558       case NEON_UCVTF_scalar:
8559         ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8560         break;
8561       case NEON_FCVTNS_scalar:
8562         fcvts(fpf, rd, rn, FPTieEven);
8563         break;
8564       case NEON_FCVTNU_scalar:
8565         fcvtu(fpf, rd, rn, FPTieEven);
8566         break;
8567       case NEON_FCVTPS_scalar:
8568         fcvts(fpf, rd, rn, FPPositiveInfinity);
8569         break;
8570       case NEON_FCVTPU_scalar:
8571         fcvtu(fpf, rd, rn, FPPositiveInfinity);
8572         break;
8573       case NEON_FCVTMS_scalar:
8574         fcvts(fpf, rd, rn, FPNegativeInfinity);
8575         break;
8576       case NEON_FCVTMU_scalar:
8577         fcvtu(fpf, rd, rn, FPNegativeInfinity);
8578         break;
8579       case NEON_FCVTZS_scalar:
8580         fcvts(fpf, rd, rn, FPZero);
8581         break;
8582       case NEON_FCVTZU_scalar:
8583         fcvtu(fpf, rd, rn, FPZero);
8584         break;
8585       case NEON_FCVTAS_scalar:
8586         fcvts(fpf, rd, rn, FPTieAway);
8587         break;
8588       case NEON_FCVTAU_scalar:
8589         fcvtu(fpf, rd, rn, FPTieAway);
8590         break;
8591       case NEON_FCVTXN_scalar:
8592         // Unlike all of the other FP instructions above, fcvtxn encodes dest
8593         // size S as size<0>=1. There's only one case, so we ignore the form.
8594         VIXL_ASSERT(instr->ExtractBit(22) == 1);
8595         fcvtxn(kFormatS, rd, rn);
8596         break;
8597       default:
8598         switch (instr->Mask(NEONScalar2RegMiscMask)) {
8599           case NEON_SQXTN_scalar:
8600             sqxtn(vf, rd, rn);
8601             break;
8602           case NEON_UQXTN_scalar:
8603             uqxtn(vf, rd, rn);
8604             break;
8605           case NEON_SQXTUN_scalar:
8606             sqxtun(vf, rd, rn);
8607             break;
8608           default:
8609             VIXL_UNIMPLEMENTED();
8610         }
8611     }
8612   }
8613 }
8614 
8615 
VisitNEONScalar2RegMiscFP16(const Instruction * instr)8616 void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
8617   VectorFormat fpf = kFormatH;
8618   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8619 
8620   SimVRegister& rd = ReadVRegister(instr->GetRd());
8621   SimVRegister& rn = ReadVRegister(instr->GetRn());
8622 
8623   switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
8624     case NEON_FRECPE_H_scalar:
8625       frecpe(fpf, rd, rn, fpcr_rounding);
8626       break;
8627     case NEON_FRECPX_H_scalar:
8628       frecpx(fpf, rd, rn);
8629       break;
8630     case NEON_FRSQRTE_H_scalar:
8631       frsqrte(fpf, rd, rn);
8632       break;
8633     case NEON_FCMGT_H_zero_scalar:
8634       fcmp_zero(fpf, rd, rn, gt);
8635       break;
8636     case NEON_FCMGE_H_zero_scalar:
8637       fcmp_zero(fpf, rd, rn, ge);
8638       break;
8639     case NEON_FCMEQ_H_zero_scalar:
8640       fcmp_zero(fpf, rd, rn, eq);
8641       break;
8642     case NEON_FCMLE_H_zero_scalar:
8643       fcmp_zero(fpf, rd, rn, le);
8644       break;
8645     case NEON_FCMLT_H_zero_scalar:
8646       fcmp_zero(fpf, rd, rn, lt);
8647       break;
8648     case NEON_SCVTF_H_scalar:
8649       scvtf(fpf, rd, rn, 0, fpcr_rounding);
8650       break;
8651     case NEON_UCVTF_H_scalar:
8652       ucvtf(fpf, rd, rn, 0, fpcr_rounding);
8653       break;
8654     case NEON_FCVTNS_H_scalar:
8655       fcvts(fpf, rd, rn, FPTieEven);
8656       break;
8657     case NEON_FCVTNU_H_scalar:
8658       fcvtu(fpf, rd, rn, FPTieEven);
8659       break;
8660     case NEON_FCVTPS_H_scalar:
8661       fcvts(fpf, rd, rn, FPPositiveInfinity);
8662       break;
8663     case NEON_FCVTPU_H_scalar:
8664       fcvtu(fpf, rd, rn, FPPositiveInfinity);
8665       break;
8666     case NEON_FCVTMS_H_scalar:
8667       fcvts(fpf, rd, rn, FPNegativeInfinity);
8668       break;
8669     case NEON_FCVTMU_H_scalar:
8670       fcvtu(fpf, rd, rn, FPNegativeInfinity);
8671       break;
8672     case NEON_FCVTZS_H_scalar:
8673       fcvts(fpf, rd, rn, FPZero);
8674       break;
8675     case NEON_FCVTZU_H_scalar:
8676       fcvtu(fpf, rd, rn, FPZero);
8677       break;
8678     case NEON_FCVTAS_H_scalar:
8679       fcvts(fpf, rd, rn, FPTieAway);
8680       break;
8681     case NEON_FCVTAU_H_scalar:
8682       fcvtu(fpf, rd, rn, FPTieAway);
8683       break;
8684   }
8685 }
8686 
8687 
VisitNEONScalar3Diff(const Instruction * instr)8688 void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
8689   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8690   VectorFormat vf = nfd.GetVectorFormat();
8691 
8692   SimVRegister& rd = ReadVRegister(instr->GetRd());
8693   SimVRegister& rn = ReadVRegister(instr->GetRn());
8694   SimVRegister& rm = ReadVRegister(instr->GetRm());
8695   switch (instr->Mask(NEONScalar3DiffMask)) {
8696     case NEON_SQDMLAL_scalar:
8697       sqdmlal(vf, rd, rn, rm);
8698       break;
8699     case NEON_SQDMLSL_scalar:
8700       sqdmlsl(vf, rd, rn, rm);
8701       break;
8702     case NEON_SQDMULL_scalar:
8703       sqdmull(vf, rd, rn, rm);
8704       break;
8705     default:
8706       VIXL_UNIMPLEMENTED();
8707   }
8708 }
8709 
8710 
VisitNEONScalar3Same(const Instruction * instr)8711 void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
8712   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8713   VectorFormat vf = nfd.GetVectorFormat();
8714 
8715   SimVRegister& rd = ReadVRegister(instr->GetRd());
8716   SimVRegister& rn = ReadVRegister(instr->GetRn());
8717   SimVRegister& rm = ReadVRegister(instr->GetRm());
8718 
8719   if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
8720     vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8721     switch (instr->Mask(NEONScalar3SameFPMask)) {
8722       case NEON_FMULX_scalar:
8723         fmulx(vf, rd, rn, rm);
8724         break;
8725       case NEON_FACGE_scalar:
8726         fabscmp(vf, rd, rn, rm, ge);
8727         break;
8728       case NEON_FACGT_scalar:
8729         fabscmp(vf, rd, rn, rm, gt);
8730         break;
8731       case NEON_FCMEQ_scalar:
8732         fcmp(vf, rd, rn, rm, eq);
8733         break;
8734       case NEON_FCMGE_scalar:
8735         fcmp(vf, rd, rn, rm, ge);
8736         break;
8737       case NEON_FCMGT_scalar:
8738         fcmp(vf, rd, rn, rm, gt);
8739         break;
8740       case NEON_FRECPS_scalar:
8741         frecps(vf, rd, rn, rm);
8742         break;
8743       case NEON_FRSQRTS_scalar:
8744         frsqrts(vf, rd, rn, rm);
8745         break;
8746       case NEON_FABD_scalar:
8747         fabd(vf, rd, rn, rm);
8748         break;
8749       default:
8750         VIXL_UNIMPLEMENTED();
8751     }
8752   } else {
8753     switch (instr->Mask(NEONScalar3SameMask)) {
8754       case NEON_ADD_scalar:
8755         add(vf, rd, rn, rm);
8756         break;
8757       case NEON_SUB_scalar:
8758         sub(vf, rd, rn, rm);
8759         break;
8760       case NEON_CMEQ_scalar:
8761         cmp(vf, rd, rn, rm, eq);
8762         break;
8763       case NEON_CMGE_scalar:
8764         cmp(vf, rd, rn, rm, ge);
8765         break;
8766       case NEON_CMGT_scalar:
8767         cmp(vf, rd, rn, rm, gt);
8768         break;
8769       case NEON_CMHI_scalar:
8770         cmp(vf, rd, rn, rm, hi);
8771         break;
8772       case NEON_CMHS_scalar:
8773         cmp(vf, rd, rn, rm, hs);
8774         break;
8775       case NEON_CMTST_scalar:
8776         cmptst(vf, rd, rn, rm);
8777         break;
8778       case NEON_USHL_scalar:
8779         ushl(vf, rd, rn, rm);
8780         break;
8781       case NEON_SSHL_scalar:
8782         sshl(vf, rd, rn, rm);
8783         break;
8784       case NEON_SQDMULH_scalar:
8785         sqdmulh(vf, rd, rn, rm);
8786         break;
8787       case NEON_SQRDMULH_scalar:
8788         sqrdmulh(vf, rd, rn, rm);
8789         break;
8790       case NEON_UQADD_scalar:
8791         add(vf, rd, rn, rm).UnsignedSaturate(vf);
8792         break;
8793       case NEON_SQADD_scalar:
8794         add(vf, rd, rn, rm).SignedSaturate(vf);
8795         break;
8796       case NEON_UQSUB_scalar:
8797         sub(vf, rd, rn, rm).UnsignedSaturate(vf);
8798         break;
8799       case NEON_SQSUB_scalar:
8800         sub(vf, rd, rn, rm).SignedSaturate(vf);
8801         break;
8802       case NEON_UQSHL_scalar:
8803         ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
8804         break;
8805       case NEON_SQSHL_scalar:
8806         sshl(vf, rd, rn, rm).SignedSaturate(vf);
8807         break;
8808       case NEON_URSHL_scalar:
8809         ushl(vf, rd, rn, rm).Round(vf);
8810         break;
8811       case NEON_SRSHL_scalar:
8812         sshl(vf, rd, rn, rm).Round(vf);
8813         break;
8814       case NEON_UQRSHL_scalar:
8815         ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
8816         break;
8817       case NEON_SQRSHL_scalar:
8818         sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
8819         break;
8820       default:
8821         VIXL_UNIMPLEMENTED();
8822     }
8823   }
8824 }
8825 
VisitNEONScalar3SameFP16(const Instruction * instr)8826 void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
8827   SimVRegister& rd = ReadVRegister(instr->GetRd());
8828   SimVRegister& rn = ReadVRegister(instr->GetRn());
8829   SimVRegister& rm = ReadVRegister(instr->GetRm());
8830 
8831   switch (instr->Mask(NEONScalar3SameFP16Mask)) {
8832     case NEON_FABD_H_scalar:
8833       fabd(kFormatH, rd, rn, rm);
8834       break;
8835     case NEON_FMULX_H_scalar:
8836       fmulx(kFormatH, rd, rn, rm);
8837       break;
8838     case NEON_FCMEQ_H_scalar:
8839       fcmp(kFormatH, rd, rn, rm, eq);
8840       break;
8841     case NEON_FCMGE_H_scalar:
8842       fcmp(kFormatH, rd, rn, rm, ge);
8843       break;
8844     case NEON_FCMGT_H_scalar:
8845       fcmp(kFormatH, rd, rn, rm, gt);
8846       break;
8847     case NEON_FACGE_H_scalar:
8848       fabscmp(kFormatH, rd, rn, rm, ge);
8849       break;
8850     case NEON_FACGT_H_scalar:
8851       fabscmp(kFormatH, rd, rn, rm, gt);
8852       break;
8853     case NEON_FRECPS_H_scalar:
8854       frecps(kFormatH, rd, rn, rm);
8855       break;
8856     case NEON_FRSQRTS_H_scalar:
8857       frsqrts(kFormatH, rd, rn, rm);
8858       break;
8859     default:
8860       VIXL_UNREACHABLE();
8861   }
8862 }
8863 
8864 
VisitNEONScalar3SameExtra(const Instruction * instr)8865 void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
8866   NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8867   VectorFormat vf = nfd.GetVectorFormat();
8868 
8869   SimVRegister& rd = ReadVRegister(instr->GetRd());
8870   SimVRegister& rn = ReadVRegister(instr->GetRn());
8871   SimVRegister& rm = ReadVRegister(instr->GetRm());
8872 
8873   switch (instr->Mask(NEONScalar3SameExtraMask)) {
8874     case NEON_SQRDMLAH_scalar:
8875       sqrdmlah(vf, rd, rn, rm);
8876       break;
8877     case NEON_SQRDMLSH_scalar:
8878       sqrdmlsh(vf, rd, rn, rm);
8879       break;
8880     default:
8881       VIXL_UNIMPLEMENTED();
8882   }
8883 }
8884 
VisitNEONScalarByIndexedElement(const Instruction * instr)8885 void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
8886   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
8887   VectorFormat vf = nfd.GetVectorFormat();
8888   VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
8889 
8890   SimVRegister& rd = ReadVRegister(instr->GetRd());
8891   SimVRegister& rn = ReadVRegister(instr->GetRn());
8892   ByElementOp Op = NULL;
8893 
8894   int rm_reg = instr->GetRm();
8895   int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8896   if (instr->GetNEONSize() == 1) {
8897     rm_reg &= 0xf;
8898     index = (index << 1) | instr->GetNEONM();
8899   }
8900 
8901   switch (instr->Mask(NEONScalarByIndexedElementMask)) {
8902     case NEON_SQDMULL_byelement_scalar:
8903       Op = &Simulator::sqdmull;
8904       break;
8905     case NEON_SQDMLAL_byelement_scalar:
8906       Op = &Simulator::sqdmlal;
8907       break;
8908     case NEON_SQDMLSL_byelement_scalar:
8909       Op = &Simulator::sqdmlsl;
8910       break;
8911     case NEON_SQDMULH_byelement_scalar:
8912       Op = &Simulator::sqdmulh;
8913       vf = vf_r;
8914       break;
8915     case NEON_SQRDMULH_byelement_scalar:
8916       Op = &Simulator::sqrdmulh;
8917       vf = vf_r;
8918       break;
8919     case NEON_SQRDMLAH_byelement_scalar:
8920       Op = &Simulator::sqrdmlah;
8921       vf = vf_r;
8922       break;
8923     case NEON_SQRDMLSH_byelement_scalar:
8924       Op = &Simulator::sqrdmlsh;
8925       vf = vf_r;
8926       break;
8927     default:
8928       vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8929       index = instr->GetNEONH();
8930       if (instr->GetFPType() == 0) {
8931         index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
8932         rm_reg &= 0xf;
8933         vf = kFormatH;
8934       } else if ((instr->GetFPType() & 1) == 0) {
8935         index = (index << 1) | instr->GetNEONL();
8936       }
8937       switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
8938         case NEON_FMUL_H_byelement_scalar:
8939         case NEON_FMUL_byelement_scalar:
8940           Op = &Simulator::fmul;
8941           break;
8942         case NEON_FMLA_H_byelement_scalar:
8943         case NEON_FMLA_byelement_scalar:
8944           Op = &Simulator::fmla;
8945           break;
8946         case NEON_FMLS_H_byelement_scalar:
8947         case NEON_FMLS_byelement_scalar:
8948           Op = &Simulator::fmls;
8949           break;
8950         case NEON_FMULX_H_byelement_scalar:
8951         case NEON_FMULX_byelement_scalar:
8952           Op = &Simulator::fmulx;
8953           break;
8954         default:
8955           VIXL_UNIMPLEMENTED();
8956       }
8957   }
8958 
8959   (this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
8960 }
8961 
8962 
VisitNEONScalarCopy(const Instruction * instr)8963 void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
8964   NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
8965   VectorFormat vf = nfd.GetVectorFormat();
8966 
8967   SimVRegister& rd = ReadVRegister(instr->GetRd());
8968   SimVRegister& rn = ReadVRegister(instr->GetRn());
8969 
8970   if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
8971     int imm5 = instr->GetImmNEON5();
8972     int tz = CountTrailingZeros(imm5, 32);
8973     int rn_index = ExtractSignedBitfield32(31, tz + 1, imm5);
8974     dup_element(vf, rd, rn, rn_index);
8975   } else {
8976     VIXL_UNIMPLEMENTED();
8977   }
8978 }
8979 
8980 
VisitNEONScalarPairwise(const Instruction * instr)8981 void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
8982   NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
8983   VectorFormat vf = nfd.GetVectorFormat();
8984 
8985   SimVRegister& rd = ReadVRegister(instr->GetRd());
8986   SimVRegister& rn = ReadVRegister(instr->GetRn());
8987   switch (instr->Mask(NEONScalarPairwiseMask)) {
8988     case NEON_ADDP_scalar: {
8989       // All pairwise operations except ADDP use bit U to differentiate FP16
8990       // from FP32/FP64 variations.
8991       NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
8992       addp(nfd_addp.GetVectorFormat(), rd, rn);
8993       break;
8994     }
8995     case NEON_FADDP_h_scalar:
8996     case NEON_FADDP_scalar:
8997       faddp(vf, rd, rn);
8998       break;
8999     case NEON_FMAXP_h_scalar:
9000     case NEON_FMAXP_scalar:
9001       fmaxp(vf, rd, rn);
9002       break;
9003     case NEON_FMAXNMP_h_scalar:
9004     case NEON_FMAXNMP_scalar:
9005       fmaxnmp(vf, rd, rn);
9006       break;
9007     case NEON_FMINP_h_scalar:
9008     case NEON_FMINP_scalar:
9009       fminp(vf, rd, rn);
9010       break;
9011     case NEON_FMINNMP_h_scalar:
9012     case NEON_FMINNMP_scalar:
9013       fminnmp(vf, rd, rn);
9014       break;
9015     default:
9016       VIXL_UNIMPLEMENTED();
9017   }
9018 }
9019 
9020 
VisitNEONScalarShiftImmediate(const Instruction * instr)9021 void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
9022   SimVRegister& rd = ReadVRegister(instr->GetRd());
9023   SimVRegister& rn = ReadVRegister(instr->GetRn());
9024   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9025 
9026   static const NEONFormatMap map = {{22, 21, 20, 19},
9027                                     {NF_UNDEF,
9028                                      NF_B,
9029                                      NF_H,
9030                                      NF_H,
9031                                      NF_S,
9032                                      NF_S,
9033                                      NF_S,
9034                                      NF_S,
9035                                      NF_D,
9036                                      NF_D,
9037                                      NF_D,
9038                                      NF_D,
9039                                      NF_D,
9040                                      NF_D,
9041                                      NF_D,
9042                                      NF_D}};
9043   NEONFormatDecoder nfd(instr, &map);
9044   VectorFormat vf = nfd.GetVectorFormat();
9045 
9046   int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
9047   int immh_immb = instr->GetImmNEONImmhImmb();
9048   int right_shift = (16 << highest_set_bit) - immh_immb;
9049   int left_shift = immh_immb - (8 << highest_set_bit);
9050   switch (instr->Mask(NEONScalarShiftImmediateMask)) {
9051     case NEON_SHL_scalar:
9052       shl(vf, rd, rn, left_shift);
9053       break;
9054     case NEON_SLI_scalar:
9055       sli(vf, rd, rn, left_shift);
9056       break;
9057     case NEON_SQSHL_imm_scalar:
9058       sqshl(vf, rd, rn, left_shift);
9059       break;
9060     case NEON_UQSHL_imm_scalar:
9061       uqshl(vf, rd, rn, left_shift);
9062       break;
9063     case NEON_SQSHLU_scalar:
9064       sqshlu(vf, rd, rn, left_shift);
9065       break;
9066     case NEON_SRI_scalar:
9067       sri(vf, rd, rn, right_shift);
9068       break;
9069     case NEON_SSHR_scalar:
9070       sshr(vf, rd, rn, right_shift);
9071       break;
9072     case NEON_USHR_scalar:
9073       ushr(vf, rd, rn, right_shift);
9074       break;
9075     case NEON_SRSHR_scalar:
9076       sshr(vf, rd, rn, right_shift).Round(vf);
9077       break;
9078     case NEON_URSHR_scalar:
9079       ushr(vf, rd, rn, right_shift).Round(vf);
9080       break;
9081     case NEON_SSRA_scalar:
9082       ssra(vf, rd, rn, right_shift);
9083       break;
9084     case NEON_USRA_scalar:
9085       usra(vf, rd, rn, right_shift);
9086       break;
9087     case NEON_SRSRA_scalar:
9088       srsra(vf, rd, rn, right_shift);
9089       break;
9090     case NEON_URSRA_scalar:
9091       ursra(vf, rd, rn, right_shift);
9092       break;
9093     case NEON_UQSHRN_scalar:
9094       uqshrn(vf, rd, rn, right_shift);
9095       break;
9096     case NEON_UQRSHRN_scalar:
9097       uqrshrn(vf, rd, rn, right_shift);
9098       break;
9099     case NEON_SQSHRN_scalar:
9100       sqshrn(vf, rd, rn, right_shift);
9101       break;
9102     case NEON_SQRSHRN_scalar:
9103       sqrshrn(vf, rd, rn, right_shift);
9104       break;
9105     case NEON_SQSHRUN_scalar:
9106       sqshrun(vf, rd, rn, right_shift);
9107       break;
9108     case NEON_SQRSHRUN_scalar:
9109       sqrshrun(vf, rd, rn, right_shift);
9110       break;
9111     case NEON_FCVTZS_imm_scalar:
9112       fcvts(vf, rd, rn, FPZero, right_shift);
9113       break;
9114     case NEON_FCVTZU_imm_scalar:
9115       fcvtu(vf, rd, rn, FPZero, right_shift);
9116       break;
9117     case NEON_SCVTF_imm_scalar:
9118       scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9119       break;
9120     case NEON_UCVTF_imm_scalar:
9121       ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9122       break;
9123     default:
9124       VIXL_UNIMPLEMENTED();
9125   }
9126 }
9127 
9128 
VisitNEONShiftImmediate(const Instruction * instr)9129 void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
9130   SimVRegister& rd = ReadVRegister(instr->GetRd());
9131   SimVRegister& rn = ReadVRegister(instr->GetRn());
9132   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9133 
9134   // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
9135   // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
9136   static const NEONFormatMap map = {{22, 21, 20, 19, 30},
9137                                     {NF_UNDEF, NF_UNDEF, NF_8B,    NF_16B,
9138                                      NF_4H,    NF_8H,    NF_4H,    NF_8H,
9139                                      NF_2S,    NF_4S,    NF_2S,    NF_4S,
9140                                      NF_2S,    NF_4S,    NF_2S,    NF_4S,
9141                                      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
9142                                      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
9143                                      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D,
9144                                      NF_UNDEF, NF_2D,    NF_UNDEF, NF_2D}};
9145   NEONFormatDecoder nfd(instr, &map);
9146   VectorFormat vf = nfd.GetVectorFormat();
9147 
9148   // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
9149   static const NEONFormatMap map_l =
9150       {{22, 21, 20, 19},
9151        {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
9152   VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
9153 
9154   int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
9155   int immh_immb = instr->GetImmNEONImmhImmb();
9156   int right_shift = (16 << highest_set_bit) - immh_immb;
9157   int left_shift = immh_immb - (8 << highest_set_bit);
9158 
9159   switch (instr->Mask(NEONShiftImmediateMask)) {
9160     case NEON_SHL:
9161       shl(vf, rd, rn, left_shift);
9162       break;
9163     case NEON_SLI:
9164       sli(vf, rd, rn, left_shift);
9165       break;
9166     case NEON_SQSHLU:
9167       sqshlu(vf, rd, rn, left_shift);
9168       break;
9169     case NEON_SRI:
9170       sri(vf, rd, rn, right_shift);
9171       break;
9172     case NEON_SSHR:
9173       sshr(vf, rd, rn, right_shift);
9174       break;
9175     case NEON_USHR:
9176       ushr(vf, rd, rn, right_shift);
9177       break;
9178     case NEON_SRSHR:
9179       sshr(vf, rd, rn, right_shift).Round(vf);
9180       break;
9181     case NEON_URSHR:
9182       ushr(vf, rd, rn, right_shift).Round(vf);
9183       break;
9184     case NEON_SSRA:
9185       ssra(vf, rd, rn, right_shift);
9186       break;
9187     case NEON_USRA:
9188       usra(vf, rd, rn, right_shift);
9189       break;
9190     case NEON_SRSRA:
9191       srsra(vf, rd, rn, right_shift);
9192       break;
9193     case NEON_URSRA:
9194       ursra(vf, rd, rn, right_shift);
9195       break;
9196     case NEON_SQSHL_imm:
9197       sqshl(vf, rd, rn, left_shift);
9198       break;
9199     case NEON_UQSHL_imm:
9200       uqshl(vf, rd, rn, left_shift);
9201       break;
9202     case NEON_SCVTF_imm:
9203       scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9204       break;
9205     case NEON_UCVTF_imm:
9206       ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9207       break;
9208     case NEON_FCVTZS_imm:
9209       fcvts(vf, rd, rn, FPZero, right_shift);
9210       break;
9211     case NEON_FCVTZU_imm:
9212       fcvtu(vf, rd, rn, FPZero, right_shift);
9213       break;
9214     case NEON_SSHLL:
9215       vf = vf_l;
9216       if (instr->Mask(NEON_Q)) {
9217         sshll2(vf, rd, rn, left_shift);
9218       } else {
9219         sshll(vf, rd, rn, left_shift);
9220       }
9221       break;
9222     case NEON_USHLL:
9223       vf = vf_l;
9224       if (instr->Mask(NEON_Q)) {
9225         ushll2(vf, rd, rn, left_shift);
9226       } else {
9227         ushll(vf, rd, rn, left_shift);
9228       }
9229       break;
9230     case NEON_SHRN:
9231       if (instr->Mask(NEON_Q)) {
9232         shrn2(vf, rd, rn, right_shift);
9233       } else {
9234         shrn(vf, rd, rn, right_shift);
9235       }
9236       break;
9237     case NEON_RSHRN:
9238       if (instr->Mask(NEON_Q)) {
9239         rshrn2(vf, rd, rn, right_shift);
9240       } else {
9241         rshrn(vf, rd, rn, right_shift);
9242       }
9243       break;
9244     case NEON_UQSHRN:
9245       if (instr->Mask(NEON_Q)) {
9246         uqshrn2(vf, rd, rn, right_shift);
9247       } else {
9248         uqshrn(vf, rd, rn, right_shift);
9249       }
9250       break;
9251     case NEON_UQRSHRN:
9252       if (instr->Mask(NEON_Q)) {
9253         uqrshrn2(vf, rd, rn, right_shift);
9254       } else {
9255         uqrshrn(vf, rd, rn, right_shift);
9256       }
9257       break;
9258     case NEON_SQSHRN:
9259       if (instr->Mask(NEON_Q)) {
9260         sqshrn2(vf, rd, rn, right_shift);
9261       } else {
9262         sqshrn(vf, rd, rn, right_shift);
9263       }
9264       break;
9265     case NEON_SQRSHRN:
9266       if (instr->Mask(NEON_Q)) {
9267         sqrshrn2(vf, rd, rn, right_shift);
9268       } else {
9269         sqrshrn(vf, rd, rn, right_shift);
9270       }
9271       break;
9272     case NEON_SQSHRUN:
9273       if (instr->Mask(NEON_Q)) {
9274         sqshrun2(vf, rd, rn, right_shift);
9275       } else {
9276         sqshrun(vf, rd, rn, right_shift);
9277       }
9278       break;
9279     case NEON_SQRSHRUN:
9280       if (instr->Mask(NEON_Q)) {
9281         sqrshrun2(vf, rd, rn, right_shift);
9282       } else {
9283         sqrshrun(vf, rd, rn, right_shift);
9284       }
9285       break;
9286     default:
9287       VIXL_UNIMPLEMENTED();
9288   }
9289 }
9290 
9291 
VisitNEONTable(const Instruction * instr)9292 void Simulator::VisitNEONTable(const Instruction* instr) {
9293   NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
9294   VectorFormat vf = nfd.GetVectorFormat();
9295 
9296   SimVRegister& rd = ReadVRegister(instr->GetRd());
9297   SimVRegister& rn = ReadVRegister(instr->GetRn());
9298   SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
9299   SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
9300   SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
9301   SimVRegister& rm = ReadVRegister(instr->GetRm());
9302 
9303   switch (instr->Mask(NEONTableMask)) {
9304     case NEON_TBL_1v:
9305       tbl(vf, rd, rn, rm);
9306       break;
9307     case NEON_TBL_2v:
9308       tbl(vf, rd, rn, rn2, rm);
9309       break;
9310     case NEON_TBL_3v:
9311       tbl(vf, rd, rn, rn2, rn3, rm);
9312       break;
9313     case NEON_TBL_4v:
9314       tbl(vf, rd, rn, rn2, rn3, rn4, rm);
9315       break;
9316     case NEON_TBX_1v:
9317       tbx(vf, rd, rn, rm);
9318       break;
9319     case NEON_TBX_2v:
9320       tbx(vf, rd, rn, rn2, rm);
9321       break;
9322     case NEON_TBX_3v:
9323       tbx(vf, rd, rn, rn2, rn3, rm);
9324       break;
9325     case NEON_TBX_4v:
9326       tbx(vf, rd, rn, rn2, rn3, rn4, rm);
9327       break;
9328     default:
9329       VIXL_UNIMPLEMENTED();
9330   }
9331 }
9332 
9333 
VisitNEONPerm(const Instruction * instr)9334 void Simulator::VisitNEONPerm(const Instruction* instr) {
9335   NEONFormatDecoder nfd(instr);
9336   VectorFormat vf = nfd.GetVectorFormat();
9337 
9338   SimVRegister& rd = ReadVRegister(instr->GetRd());
9339   SimVRegister& rn = ReadVRegister(instr->GetRn());
9340   SimVRegister& rm = ReadVRegister(instr->GetRm());
9341 
9342   switch (instr->Mask(NEONPermMask)) {
9343     case NEON_TRN1:
9344       trn1(vf, rd, rn, rm);
9345       break;
9346     case NEON_TRN2:
9347       trn2(vf, rd, rn, rm);
9348       break;
9349     case NEON_UZP1:
9350       uzp1(vf, rd, rn, rm);
9351       break;
9352     case NEON_UZP2:
9353       uzp2(vf, rd, rn, rm);
9354       break;
9355     case NEON_ZIP1:
9356       zip1(vf, rd, rn, rm);
9357       break;
9358     case NEON_ZIP2:
9359       zip2(vf, rd, rn, rm);
9360       break;
9361     default:
9362       VIXL_UNIMPLEMENTED();
9363   }
9364 }
9365 
VisitSVEAddressGeneration(const Instruction * instr)9366 void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
9367   SimVRegister& zd = ReadVRegister(instr->GetRd());
9368   SimVRegister& zn = ReadVRegister(instr->GetRn());
9369   SimVRegister& zm = ReadVRegister(instr->GetRm());
9370   SimVRegister temp;
9371 
9372   VectorFormat vform = kFormatVnD;
9373   mov(vform, temp, zm);
9374 
9375   switch (instr->Mask(SVEAddressGenerationMask)) {
9376     case ADR_z_az_d_s32_scaled:
9377       sxt(vform, temp, temp, kSRegSize);
9378       break;
9379     case ADR_z_az_d_u32_scaled:
9380       uxt(vform, temp, temp, kSRegSize);
9381       break;
9382     case ADR_z_az_s_same_scaled:
9383       vform = kFormatVnS;
9384       break;
9385     case ADR_z_az_d_same_scaled:
9386       // Nothing to do.
9387       break;
9388     default:
9389       VIXL_UNIMPLEMENTED();
9390       break;
9391   }
9392 
9393   int shift_amount = instr->ExtractBits(11, 10);
9394   shl(vform, temp, temp, shift_amount);
9395   add(vform, zd, zn, temp);
9396 }
9397 
VisitSVEBitwiseLogicalWithImm_Unpredicated(const Instruction * instr)9398 void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
9399     const Instruction* instr) {
9400   Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
9401   switch (op) {
9402     case AND_z_zi:
9403     case EOR_z_zi:
9404     case ORR_z_zi: {
9405       int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9406       uint64_t imm = instr->GetSVEImmLogical();
9407       // Valid immediate is a non-zero bits
9408       VIXL_ASSERT(imm != 0);
9409       SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
9410                               op),
9411                           SVEFormatFromLaneSizeInBytesLog2(lane_size),
9412                           ReadVRegister(instr->GetRd()),
9413                           imm);
9414       break;
9415     }
9416     default:
9417       VIXL_UNIMPLEMENTED();
9418       break;
9419   }
9420 }
9421 
VisitSVEBroadcastBitmaskImm(const Instruction * instr)9422 void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
9423   switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
9424     case DUPM_z_i: {
9425       /* DUPM uses the same lane size and immediate encoding as bitwise logical
9426        * immediate instructions. */
9427       int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9428       uint64_t imm = instr->GetSVEImmLogical();
9429       VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9430       dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
9431       break;
9432     }
9433     default:
9434       VIXL_UNIMPLEMENTED();
9435       break;
9436   }
9437 }
9438 
VisitSVEBitwiseLogicalUnpredicated(const Instruction * instr)9439 void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
9440   SimVRegister& zd = ReadVRegister(instr->GetRd());
9441   SimVRegister& zn = ReadVRegister(instr->GetRn());
9442   SimVRegister& zm = ReadVRegister(instr->GetRm());
9443   Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
9444 
9445   LogicalOp logical_op = LogicalOpMask;
9446   switch (op) {
9447     case AND_z_zz:
9448       logical_op = AND;
9449       break;
9450     case BIC_z_zz:
9451       logical_op = BIC;
9452       break;
9453     case EOR_z_zz:
9454       logical_op = EOR;
9455       break;
9456     case ORR_z_zz:
9457       logical_op = ORR;
9458       break;
9459     default:
9460       VIXL_UNIMPLEMENTED();
9461       break;
9462   }
9463   // Lane size of registers is irrelevant to the bitwise operations, so perform
9464   // the operation on D-sized lanes.
9465   SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
9466 }
9467 
VisitSVEBitwiseShiftByImm_Predicated(const Instruction * instr)9468 void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
9469   SimVRegister& zdn = ReadVRegister(instr->GetRd());
9470   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9471 
9472   SimVRegister scratch;
9473   SimVRegister result;
9474 
9475   bool for_division = false;
9476   Shift shift_op = NO_SHIFT;
9477   switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
9478     case ASRD_z_p_zi:
9479       shift_op = ASR;
9480       for_division = true;
9481       break;
9482     case ASR_z_p_zi:
9483       shift_op = ASR;
9484       break;
9485     case LSL_z_p_zi:
9486       shift_op = LSL;
9487       break;
9488     case LSR_z_p_zi:
9489       shift_op = LSR;
9490       break;
9491     default:
9492       VIXL_UNIMPLEMENTED();
9493       break;
9494   }
9495 
9496   std::pair<int, int> shift_and_lane_size =
9497       instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
9498   unsigned lane_size = shift_and_lane_size.second;
9499   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9500   int shift_dist = shift_and_lane_size.first;
9501 
9502   if ((shift_op == ASR) && for_division) {
9503     asrd(vform, result, zdn, shift_dist);
9504   } else {
9505     if (shift_op == LSL) {
9506       // Shift distance is computed differently for LSL. Convert the result.
9507       shift_dist = (8 << lane_size) - shift_dist;
9508     }
9509     dup_immediate(vform, scratch, shift_dist);
9510     SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);
9511   }
9512   mov_merging(vform, zdn, pg, result);
9513 }
9514 
VisitSVEBitwiseShiftByVector_Predicated(const Instruction * instr)9515 void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
9516     const Instruction* instr) {
9517   VectorFormat vform = instr->GetSVEVectorFormat();
9518   SimVRegister& zdn = ReadVRegister(instr->GetRd());
9519   SimVRegister& zm = ReadVRegister(instr->GetRn());
9520   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9521   SimVRegister result;
9522 
9523   // SVE uses the whole (saturated) lane for the shift amount.
9524   bool shift_in_ls_byte = false;
9525 
9526   switch (form_hash_) {
9527     case "asrr_z_p_zz"_h:
9528       sshr(vform, result, zm, zdn);
9529       break;
9530     case "asr_z_p_zz"_h:
9531       sshr(vform, result, zdn, zm);
9532       break;
9533     case "lslr_z_p_zz"_h:
9534       sshl(vform, result, zm, zdn, shift_in_ls_byte);
9535       break;
9536     case "lsl_z_p_zz"_h:
9537       sshl(vform, result, zdn, zm, shift_in_ls_byte);
9538       break;
9539     case "lsrr_z_p_zz"_h:
9540       ushr(vform, result, zm, zdn);
9541       break;
9542     case "lsr_z_p_zz"_h:
9543       ushr(vform, result, zdn, zm);
9544       break;
9545     case "sqrshl_z_p_zz"_h:
9546       sshl(vform, result, zdn, zm, shift_in_ls_byte)
9547           .Round(vform)
9548           .SignedSaturate(vform);
9549       break;
9550     case "sqrshlr_z_p_zz"_h:
9551       sshl(vform, result, zm, zdn, shift_in_ls_byte)
9552           .Round(vform)
9553           .SignedSaturate(vform);
9554       break;
9555     case "sqshl_z_p_zz"_h:
9556       sshl(vform, result, zdn, zm, shift_in_ls_byte).SignedSaturate(vform);
9557       break;
9558     case "sqshlr_z_p_zz"_h:
9559       sshl(vform, result, zm, zdn, shift_in_ls_byte).SignedSaturate(vform);
9560       break;
9561     case "srshl_z_p_zz"_h:
9562       sshl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9563       break;
9564     case "srshlr_z_p_zz"_h:
9565       sshl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
9566       break;
9567     case "uqrshl_z_p_zz"_h:
9568       ushl(vform, result, zdn, zm, shift_in_ls_byte)
9569           .Round(vform)
9570           .UnsignedSaturate(vform);
9571       break;
9572     case "uqrshlr_z_p_zz"_h:
9573       ushl(vform, result, zm, zdn, shift_in_ls_byte)
9574           .Round(vform)
9575           .UnsignedSaturate(vform);
9576       break;
9577     case "uqshl_z_p_zz"_h:
9578       ushl(vform, result, zdn, zm, shift_in_ls_byte).UnsignedSaturate(vform);
9579       break;
9580     case "uqshlr_z_p_zz"_h:
9581       ushl(vform, result, zm, zdn, shift_in_ls_byte).UnsignedSaturate(vform);
9582       break;
9583     case "urshl_z_p_zz"_h:
9584       ushl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
9585       break;
9586     case "urshlr_z_p_zz"_h:
9587       ushl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
9588       break;
9589     default:
9590       VIXL_UNIMPLEMENTED();
9591       break;
9592   }
9593   mov_merging(vform, zdn, pg, result);
9594 }
9595 
VisitSVEBitwiseShiftByWideElements_Predicated(const Instruction * instr)9596 void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
9597     const Instruction* instr) {
9598   VectorFormat vform = instr->GetSVEVectorFormat();
9599   SimVRegister& zdn = ReadVRegister(instr->GetRd());
9600   SimVRegister& zm = ReadVRegister(instr->GetRn());
9601   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9602 
9603   SimVRegister result;
9604   Shift shift_op = ASR;
9605 
9606   switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
9607     case ASR_z_p_zw:
9608       break;
9609     case LSL_z_p_zw:
9610       shift_op = LSL;
9611       break;
9612     case LSR_z_p_zw:
9613       shift_op = LSR;
9614       break;
9615     default:
9616       VIXL_UNIMPLEMENTED();
9617       break;
9618   }
9619   SVEBitwiseShiftHelper(shift_op,
9620                         vform,
9621                         result,
9622                         zdn,
9623                         zm,
9624                         /* is_wide_elements = */ true);
9625   mov_merging(vform, zdn, pg, result);
9626 }
9627 
VisitSVEBitwiseShiftUnpredicated(const Instruction * instr)9628 void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
9629   SimVRegister& zd = ReadVRegister(instr->GetRd());
9630   SimVRegister& zn = ReadVRegister(instr->GetRn());
9631 
9632   Shift shift_op = NO_SHIFT;
9633   switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9634     case ASR_z_zi:
9635     case ASR_z_zw:
9636       shift_op = ASR;
9637       break;
9638     case LSL_z_zi:
9639     case LSL_z_zw:
9640       shift_op = LSL;
9641       break;
9642     case LSR_z_zi:
9643     case LSR_z_zw:
9644       shift_op = LSR;
9645       break;
9646     default:
9647       VIXL_UNIMPLEMENTED();
9648       break;
9649   }
9650 
9651   switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
9652     case ASR_z_zi:
9653     case LSL_z_zi:
9654     case LSR_z_zi: {
9655       SimVRegister scratch;
9656       std::pair<int, int> shift_and_lane_size =
9657           instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
9658       unsigned lane_size = shift_and_lane_size.second;
9659       VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
9660       VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9661       int shift_dist = shift_and_lane_size.first;
9662       if (shift_op == LSL) {
9663         // Shift distance is computed differently for LSL. Convert the result.
9664         shift_dist = (8 << lane_size) - shift_dist;
9665       }
9666       dup_immediate(vform, scratch, shift_dist);
9667       SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
9668       break;
9669     }
9670     case ASR_z_zw:
9671     case LSL_z_zw:
9672     case LSR_z_zw:
9673       SVEBitwiseShiftHelper(shift_op,
9674                             instr->GetSVEVectorFormat(),
9675                             zd,
9676                             zn,
9677                             ReadVRegister(instr->GetRm()),
9678                             true);
9679       break;
9680     default:
9681       VIXL_UNIMPLEMENTED();
9682       break;
9683   }
9684 }
9685 
VisitSVEIncDecRegisterByElementCount(const Instruction * instr)9686 void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
9687   // Although the instructions have a separate encoding class, the lane size is
9688   // encoded in the same way as most other SVE instructions.
9689   VectorFormat vform = instr->GetSVEVectorFormat();
9690 
9691   int pattern = instr->GetImmSVEPredicateConstraint();
9692   int count = GetPredicateConstraintLaneCount(vform, pattern);
9693   int multiplier = instr->ExtractBits(19, 16) + 1;
9694 
9695   switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
9696     case DECB_r_rs:
9697     case DECD_r_rs:
9698     case DECH_r_rs:
9699     case DECW_r_rs:
9700       count = -count;
9701       break;
9702     case INCB_r_rs:
9703     case INCD_r_rs:
9704     case INCH_r_rs:
9705     case INCW_r_rs:
9706       // Nothing to do.
9707       break;
9708     default:
9709       VIXL_UNIMPLEMENTED();
9710       return;
9711   }
9712 
9713   WriteXRegister(instr->GetRd(),
9714                  IncDecN(ReadXRegister(instr->GetRd()),
9715                          count * multiplier,
9716                          kXRegSize));
9717 }
9718 
VisitSVEIncDecVectorByElementCount(const Instruction * instr)9719 void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
9720   VectorFormat vform = instr->GetSVEVectorFormat();
9721   if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9722     VIXL_UNIMPLEMENTED();
9723   }
9724 
9725   int pattern = instr->GetImmSVEPredicateConstraint();
9726   int count = GetPredicateConstraintLaneCount(vform, pattern);
9727   int multiplier = instr->ExtractBits(19, 16) + 1;
9728 
9729   switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
9730     case DECD_z_zs:
9731     case DECH_z_zs:
9732     case DECW_z_zs:
9733       count = -count;
9734       break;
9735     case INCD_z_zs:
9736     case INCH_z_zs:
9737     case INCW_z_zs:
9738       // Nothing to do.
9739       break;
9740     default:
9741       VIXL_UNIMPLEMENTED();
9742       break;
9743   }
9744 
9745   SimVRegister& zd = ReadVRegister(instr->GetRd());
9746   SimVRegister scratch;
9747   dup_immediate(vform,
9748                 scratch,
9749                 IncDecN(0,
9750                         count * multiplier,
9751                         LaneSizeInBitsFromFormat(vform)));
9752   add(vform, zd, zd, scratch);
9753 }
9754 
VisitSVESaturatingIncDecRegisterByElementCount(const Instruction * instr)9755 void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
9756     const Instruction* instr) {
9757   // Although the instructions have a separate encoding class, the lane size is
9758   // encoded in the same way as most other SVE instructions.
9759   VectorFormat vform = instr->GetSVEVectorFormat();
9760 
9761   int pattern = instr->GetImmSVEPredicateConstraint();
9762   int count = GetPredicateConstraintLaneCount(vform, pattern);
9763   int multiplier = instr->ExtractBits(19, 16) + 1;
9764 
9765   unsigned width = kXRegSize;
9766   bool is_signed = false;
9767 
9768   switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
9769     case SQDECB_r_rs_sx:
9770     case SQDECD_r_rs_sx:
9771     case SQDECH_r_rs_sx:
9772     case SQDECW_r_rs_sx:
9773       width = kWRegSize;
9774       VIXL_FALLTHROUGH();
9775     case SQDECB_r_rs_x:
9776     case SQDECD_r_rs_x:
9777     case SQDECH_r_rs_x:
9778     case SQDECW_r_rs_x:
9779       is_signed = true;
9780       count = -count;
9781       break;
9782     case SQINCB_r_rs_sx:
9783     case SQINCD_r_rs_sx:
9784     case SQINCH_r_rs_sx:
9785     case SQINCW_r_rs_sx:
9786       width = kWRegSize;
9787       VIXL_FALLTHROUGH();
9788     case SQINCB_r_rs_x:
9789     case SQINCD_r_rs_x:
9790     case SQINCH_r_rs_x:
9791     case SQINCW_r_rs_x:
9792       is_signed = true;
9793       break;
9794     case UQDECB_r_rs_uw:
9795     case UQDECD_r_rs_uw:
9796     case UQDECH_r_rs_uw:
9797     case UQDECW_r_rs_uw:
9798       width = kWRegSize;
9799       VIXL_FALLTHROUGH();
9800     case UQDECB_r_rs_x:
9801     case UQDECD_r_rs_x:
9802     case UQDECH_r_rs_x:
9803     case UQDECW_r_rs_x:
9804       count = -count;
9805       break;
9806     case UQINCB_r_rs_uw:
9807     case UQINCD_r_rs_uw:
9808     case UQINCH_r_rs_uw:
9809     case UQINCW_r_rs_uw:
9810       width = kWRegSize;
9811       VIXL_FALLTHROUGH();
9812     case UQINCB_r_rs_x:
9813     case UQINCD_r_rs_x:
9814     case UQINCH_r_rs_x:
9815     case UQINCW_r_rs_x:
9816       // Nothing to do.
9817       break;
9818     default:
9819       VIXL_UNIMPLEMENTED();
9820       break;
9821   }
9822 
9823   WriteXRegister(instr->GetRd(),
9824                  IncDecN(ReadXRegister(instr->GetRd()),
9825                          count * multiplier,
9826                          width,
9827                          true,
9828                          is_signed));
9829 }
9830 
VisitSVESaturatingIncDecVectorByElementCount(const Instruction * instr)9831 void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
9832     const Instruction* instr) {
9833   VectorFormat vform = instr->GetSVEVectorFormat();
9834   if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9835     VIXL_UNIMPLEMENTED();
9836   }
9837 
9838   int pattern = instr->GetImmSVEPredicateConstraint();
9839   int count = GetPredicateConstraintLaneCount(vform, pattern);
9840   int multiplier = instr->ExtractBits(19, 16) + 1;
9841 
9842   SimVRegister& zd = ReadVRegister(instr->GetRd());
9843   SimVRegister scratch;
9844   dup_immediate(vform,
9845                 scratch,
9846                 IncDecN(0,
9847                         count * multiplier,
9848                         LaneSizeInBitsFromFormat(vform)));
9849 
9850   switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
9851     case SQDECD_z_zs:
9852     case SQDECH_z_zs:
9853     case SQDECW_z_zs:
9854       sub(vform, zd, zd, scratch).SignedSaturate(vform);
9855       break;
9856     case SQINCD_z_zs:
9857     case SQINCH_z_zs:
9858     case SQINCW_z_zs:
9859       add(vform, zd, zd, scratch).SignedSaturate(vform);
9860       break;
9861     case UQDECD_z_zs:
9862     case UQDECH_z_zs:
9863     case UQDECW_z_zs:
9864       sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
9865       break;
9866     case UQINCD_z_zs:
9867     case UQINCH_z_zs:
9868     case UQINCW_z_zs:
9869       add(vform, zd, zd, scratch).UnsignedSaturate(vform);
9870       break;
9871     default:
9872       VIXL_UNIMPLEMENTED();
9873       break;
9874   }
9875 }
9876 
VisitSVEElementCount(const Instruction * instr)9877 void Simulator::VisitSVEElementCount(const Instruction* instr) {
9878   switch (instr->Mask(SVEElementCountMask)) {
9879     case CNTB_r_s:
9880     case CNTD_r_s:
9881     case CNTH_r_s:
9882     case CNTW_r_s:
9883       // All handled below.
9884       break;
9885     default:
9886       VIXL_UNIMPLEMENTED();
9887       break;
9888   }
9889 
9890   // Although the instructions are separated, the lane size is encoded in the
9891   // same way as most other SVE instructions.
9892   VectorFormat vform = instr->GetSVEVectorFormat();
9893 
9894   int pattern = instr->GetImmSVEPredicateConstraint();
9895   int count = GetPredicateConstraintLaneCount(vform, pattern);
9896   int multiplier = instr->ExtractBits(19, 16) + 1;
9897   WriteXRegister(instr->GetRd(), count * multiplier);
9898 }
9899 
VisitSVEFPAccumulatingReduction(const Instruction * instr)9900 void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
9901   VectorFormat vform = instr->GetSVEVectorFormat();
9902   SimVRegister& vdn = ReadVRegister(instr->GetRd());
9903   SimVRegister& zm = ReadVRegister(instr->GetRn());
9904   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9905 
9906   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9907 
9908   switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
9909     case FADDA_v_p_z:
9910       fadda(vform, vdn, pg, zm);
9911       break;
9912     default:
9913       VIXL_UNIMPLEMENTED();
9914       break;
9915   }
9916 }
9917 
VisitSVEFPArithmetic_Predicated(const Instruction * instr)9918 void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
9919   VectorFormat vform = instr->GetSVEVectorFormat();
9920   SimVRegister& zdn = ReadVRegister(instr->GetRd());
9921   SimVRegister& zm = ReadVRegister(instr->GetRn());
9922   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9923 
9924   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
9925 
9926   SimVRegister result;
9927   switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
9928     case FABD_z_p_zz:
9929       fabd(vform, result, zdn, zm);
9930       break;
9931     case FADD_z_p_zz:
9932       fadd(vform, result, zdn, zm);
9933       break;
9934     case FDIVR_z_p_zz:
9935       fdiv(vform, result, zm, zdn);
9936       break;
9937     case FDIV_z_p_zz:
9938       fdiv(vform, result, zdn, zm);
9939       break;
9940     case FMAXNM_z_p_zz:
9941       fmaxnm(vform, result, zdn, zm);
9942       break;
9943     case FMAX_z_p_zz:
9944       fmax(vform, result, zdn, zm);
9945       break;
9946     case FMINNM_z_p_zz:
9947       fminnm(vform, result, zdn, zm);
9948       break;
9949     case FMIN_z_p_zz:
9950       fmin(vform, result, zdn, zm);
9951       break;
9952     case FMULX_z_p_zz:
9953       fmulx(vform, result, zdn, zm);
9954       break;
9955     case FMUL_z_p_zz:
9956       fmul(vform, result, zdn, zm);
9957       break;
9958     case FSCALE_z_p_zz:
9959       fscale(vform, result, zdn, zm);
9960       break;
9961     case FSUBR_z_p_zz:
9962       fsub(vform, result, zm, zdn);
9963       break;
9964     case FSUB_z_p_zz:
9965       fsub(vform, result, zdn, zm);
9966       break;
9967     default:
9968       VIXL_UNIMPLEMENTED();
9969       break;
9970   }
9971   mov_merging(vform, zdn, pg, result);
9972 }
9973 
VisitSVEFPArithmeticWithImm_Predicated(const Instruction * instr)9974 void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
9975     const Instruction* instr) {
9976   VectorFormat vform = instr->GetSVEVectorFormat();
9977   if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
9978     VIXL_UNIMPLEMENTED();
9979   }
9980 
9981   SimVRegister& zdn = ReadVRegister(instr->GetRd());
9982   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9983   SimVRegister result;
9984 
9985   int i1 = instr->ExtractBit(5);
9986   SimVRegister add_sub_imm, min_max_imm, mul_imm;
9987   uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);
9988   uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);
9989   uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);
9990   dup_immediate(vform, add_sub_imm, i1 ? one : half);
9991   dup_immediate(vform, min_max_imm, i1 ? one : 0);
9992   dup_immediate(vform, mul_imm, i1 ? two : half);
9993 
9994   switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
9995     case FADD_z_p_zs:
9996       fadd(vform, result, zdn, add_sub_imm);
9997       break;
9998     case FMAXNM_z_p_zs:
9999       fmaxnm(vform, result, zdn, min_max_imm);
10000       break;
10001     case FMAX_z_p_zs:
10002       fmax(vform, result, zdn, min_max_imm);
10003       break;
10004     case FMINNM_z_p_zs:
10005       fminnm(vform, result, zdn, min_max_imm);
10006       break;
10007     case FMIN_z_p_zs:
10008       fmin(vform, result, zdn, min_max_imm);
10009       break;
10010     case FMUL_z_p_zs:
10011       fmul(vform, result, zdn, mul_imm);
10012       break;
10013     case FSUBR_z_p_zs:
10014       fsub(vform, result, add_sub_imm, zdn);
10015       break;
10016     case FSUB_z_p_zs:
10017       fsub(vform, result, zdn, add_sub_imm);
10018       break;
10019     default:
10020       VIXL_UNIMPLEMENTED();
10021       break;
10022   }
10023   mov_merging(vform, zdn, pg, result);
10024 }
10025 
VisitSVEFPTrigMulAddCoefficient(const Instruction * instr)10026 void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
10027   VectorFormat vform = instr->GetSVEVectorFormat();
10028   SimVRegister& zd = ReadVRegister(instr->GetRd());
10029   SimVRegister& zm = ReadVRegister(instr->GetRn());
10030 
10031   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10032 
10033   switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
10034     case FTMAD_z_zzi:
10035       ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
10036       break;
10037     default:
10038       VIXL_UNIMPLEMENTED();
10039       break;
10040   }
10041 }
10042 
VisitSVEFPArithmeticUnpredicated(const Instruction * instr)10043 void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
10044   VectorFormat vform = instr->GetSVEVectorFormat();
10045   SimVRegister& zd = ReadVRegister(instr->GetRd());
10046   SimVRegister& zn = ReadVRegister(instr->GetRn());
10047   SimVRegister& zm = ReadVRegister(instr->GetRm());
10048 
10049   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10050 
10051   switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
10052     case FADD_z_zz:
10053       fadd(vform, zd, zn, zm);
10054       break;
10055     case FMUL_z_zz:
10056       fmul(vform, zd, zn, zm);
10057       break;
10058     case FRECPS_z_zz:
10059       frecps(vform, zd, zn, zm);
10060       break;
10061     case FRSQRTS_z_zz:
10062       frsqrts(vform, zd, zn, zm);
10063       break;
10064     case FSUB_z_zz:
10065       fsub(vform, zd, zn, zm);
10066       break;
10067     case FTSMUL_z_zz:
10068       ftsmul(vform, zd, zn, zm);
10069       break;
10070     default:
10071       VIXL_UNIMPLEMENTED();
10072       break;
10073   }
10074 }
10075 
VisitSVEFPCompareVectors(const Instruction * instr)10076 void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
10077   SimPRegister& pd = ReadPRegister(instr->GetPd());
10078   SimVRegister& zn = ReadVRegister(instr->GetRn());
10079   SimVRegister& zm = ReadVRegister(instr->GetRm());
10080   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10081   VectorFormat vform = instr->GetSVEVectorFormat();
10082   SimVRegister result;
10083 
10084   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10085 
10086   switch (instr->Mask(SVEFPCompareVectorsMask)) {
10087     case FACGE_p_p_zz:
10088       fabscmp(vform, result, zn, zm, ge);
10089       break;
10090     case FACGT_p_p_zz:
10091       fabscmp(vform, result, zn, zm, gt);
10092       break;
10093     case FCMEQ_p_p_zz:
10094       fcmp(vform, result, zn, zm, eq);
10095       break;
10096     case FCMGE_p_p_zz:
10097       fcmp(vform, result, zn, zm, ge);
10098       break;
10099     case FCMGT_p_p_zz:
10100       fcmp(vform, result, zn, zm, gt);
10101       break;
10102     case FCMNE_p_p_zz:
10103       fcmp(vform, result, zn, zm, ne);
10104       break;
10105     case FCMUO_p_p_zz:
10106       fcmp(vform, result, zn, zm, uo);
10107       break;
10108     default:
10109       VIXL_UNIMPLEMENTED();
10110       break;
10111   }
10112 
10113   ExtractFromSimVRegister(vform, pd, result);
10114   mov_zeroing(pd, pg, pd);
10115 }
10116 
VisitSVEFPCompareWithZero(const Instruction * instr)10117 void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
10118   SimPRegister& pd = ReadPRegister(instr->GetPd());
10119   SimVRegister& zn = ReadVRegister(instr->GetRn());
10120   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10121   VectorFormat vform = instr->GetSVEVectorFormat();
10122 
10123   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10124 
10125   SimVRegister result;
10126   SimVRegister zeros;
10127   dup_immediate(kFormatVnD, zeros, 0);
10128 
10129   switch (instr->Mask(SVEFPCompareWithZeroMask)) {
10130     case FCMEQ_p_p_z0:
10131       fcmp(vform, result, zn, zeros, eq);
10132       break;
10133     case FCMGE_p_p_z0:
10134       fcmp(vform, result, zn, zeros, ge);
10135       break;
10136     case FCMGT_p_p_z0:
10137       fcmp(vform, result, zn, zeros, gt);
10138       break;
10139     case FCMLE_p_p_z0:
10140       fcmp(vform, result, zn, zeros, le);
10141       break;
10142     case FCMLT_p_p_z0:
10143       fcmp(vform, result, zn, zeros, lt);
10144       break;
10145     case FCMNE_p_p_z0:
10146       fcmp(vform, result, zn, zeros, ne);
10147       break;
10148     default:
10149       VIXL_UNIMPLEMENTED();
10150       break;
10151   }
10152 
10153   ExtractFromSimVRegister(vform, pd, result);
10154   mov_zeroing(pd, pg, pd);
10155 }
10156 
VisitSVEFPComplexAddition(const Instruction * instr)10157 void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
10158   VectorFormat vform = instr->GetSVEVectorFormat();
10159 
10160   if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10161     VIXL_UNIMPLEMENTED();
10162   }
10163 
10164   SimVRegister& zdn = ReadVRegister(instr->GetRd());
10165   SimVRegister& zm = ReadVRegister(instr->GetRn());
10166   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10167   int rot = instr->ExtractBit(16);
10168 
10169   SimVRegister result;
10170 
10171   switch (instr->Mask(SVEFPComplexAdditionMask)) {
10172     case FCADD_z_p_zz:
10173       fcadd(vform, result, zdn, zm, rot);
10174       break;
10175     default:
10176       VIXL_UNIMPLEMENTED();
10177       break;
10178   }
10179   mov_merging(vform, zdn, pg, result);
10180 }
10181 
VisitSVEFPComplexMulAdd(const Instruction * instr)10182 void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
10183   VectorFormat vform = instr->GetSVEVectorFormat();
10184 
10185   if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10186     VIXL_UNIMPLEMENTED();
10187   }
10188 
10189   SimVRegister& zda = ReadVRegister(instr->GetRd());
10190   SimVRegister& zn = ReadVRegister(instr->GetRn());
10191   SimVRegister& zm = ReadVRegister(instr->GetRm());
10192   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10193   int rot = instr->ExtractBits(14, 13);
10194 
10195   SimVRegister result;
10196 
10197   switch (instr->Mask(SVEFPComplexMulAddMask)) {
10198     case FCMLA_z_p_zzz:
10199       fcmla(vform, result, zn, zm, zda, rot);
10200       break;
10201     default:
10202       VIXL_UNIMPLEMENTED();
10203       break;
10204   }
10205   mov_merging(vform, zda, pg, result);
10206 }
10207 
VisitSVEFPComplexMulAddIndex(const Instruction * instr)10208 void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
10209   SimVRegister& zda = ReadVRegister(instr->GetRd());
10210   SimVRegister& zn = ReadVRegister(instr->GetRn());
10211   int rot = instr->ExtractBits(11, 10);
10212   unsigned zm_code = instr->GetRm();
10213   int index = -1;
10214   VectorFormat vform, vform_dup;
10215 
10216   switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
10217     case FCMLA_z_zzzi_h:
10218       vform = kFormatVnH;
10219       vform_dup = kFormatVnS;
10220       index = zm_code >> 3;
10221       zm_code &= 0x7;
10222       break;
10223     case FCMLA_z_zzzi_s:
10224       vform = kFormatVnS;
10225       vform_dup = kFormatVnD;
10226       index = zm_code >> 4;
10227       zm_code &= 0xf;
10228       break;
10229     default:
10230       VIXL_UNIMPLEMENTED();
10231       break;
10232   }
10233 
10234   if (index >= 0) {
10235     SimVRegister temp;
10236     dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);
10237     fcmla(vform, zda, zn, temp, zda, rot);
10238   }
10239 }
10240 
10241 typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,
10242                                                   LogicVRegister dst,
10243                                                   const LogicVRegister& src);
10244 
VisitSVEFPFastReduction(const Instruction * instr)10245 void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
10246   VectorFormat vform = instr->GetSVEVectorFormat();
10247   SimVRegister& vd = ReadVRegister(instr->GetRd());
10248   SimVRegister& zn = ReadVRegister(instr->GetRn());
10249   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10250   int lane_size = LaneSizeInBitsFromFormat(vform);
10251 
10252   uint64_t inactive_value = 0;
10253   FastReduceFn fn = nullptr;
10254 
10255   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10256 
10257   switch (instr->Mask(SVEFPFastReductionMask)) {
10258     case FADDV_v_p_z:
10259       fn = &Simulator::faddv;
10260       break;
10261     case FMAXNMV_v_p_z:
10262       inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10263       fn = &Simulator::fmaxnmv;
10264       break;
10265     case FMAXV_v_p_z:
10266       inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);
10267       fn = &Simulator::fmaxv;
10268       break;
10269     case FMINNMV_v_p_z:
10270       inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10271       fn = &Simulator::fminnmv;
10272       break;
10273     case FMINV_v_p_z:
10274       inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);
10275       fn = &Simulator::fminv;
10276       break;
10277     default:
10278       VIXL_UNIMPLEMENTED();
10279       break;
10280   }
10281 
10282   SimVRegister scratch;
10283   dup_immediate(vform, scratch, inactive_value);
10284   mov_merging(vform, scratch, pg, zn);
10285   if (fn != nullptr) (this->*fn)(vform, vd, scratch);
10286 }
10287 
VisitSVEFPMulIndex(const Instruction * instr)10288 void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
10289   VectorFormat vform = kFormatUndefined;
10290 
10291   switch (instr->Mask(SVEFPMulIndexMask)) {
10292     case FMUL_z_zzi_d:
10293       vform = kFormatVnD;
10294       break;
10295     case FMUL_z_zzi_h_i3h:
10296     case FMUL_z_zzi_h:
10297       vform = kFormatVnH;
10298       break;
10299     case FMUL_z_zzi_s:
10300       vform = kFormatVnS;
10301       break;
10302     default:
10303       VIXL_UNIMPLEMENTED();
10304       break;
10305   }
10306 
10307   SimVRegister& zd = ReadVRegister(instr->GetRd());
10308   SimVRegister& zn = ReadVRegister(instr->GetRn());
10309   SimVRegister temp;
10310 
10311   dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
10312   fmul(vform, zd, zn, temp);
10313 }
10314 
VisitSVEFPMulAdd(const Instruction * instr)10315 void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
10316   VectorFormat vform = instr->GetSVEVectorFormat();
10317   SimVRegister& zd = ReadVRegister(instr->GetRd());
10318   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10319   SimVRegister result;
10320 
10321   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10322 
10323   if (instr->ExtractBit(15) == 0) {
10324     // Floating-point multiply-accumulate writing addend.
10325     SimVRegister& zm = ReadVRegister(instr->GetRm());
10326     SimVRegister& zn = ReadVRegister(instr->GetRn());
10327 
10328     switch (instr->Mask(SVEFPMulAddMask)) {
10329       // zda = zda + zn * zm
10330       case FMLA_z_p_zzz:
10331         fmla(vform, result, zd, zn, zm);
10332         break;
10333       // zda = -zda + -zn * zm
10334       case FNMLA_z_p_zzz:
10335         fneg(vform, result, zd);
10336         fmls(vform, result, result, zn, zm);
10337         break;
10338       // zda = zda + -zn * zm
10339       case FMLS_z_p_zzz:
10340         fmls(vform, result, zd, zn, zm);
10341         break;
10342       // zda = -zda + zn * zm
10343       case FNMLS_z_p_zzz:
10344         fneg(vform, result, zd);
10345         fmla(vform, result, result, zn, zm);
10346         break;
10347       default:
10348         VIXL_UNIMPLEMENTED();
10349         break;
10350     }
10351   } else {
10352     // Floating-point multiply-accumulate writing multiplicand.
10353     SimVRegister& za = ReadVRegister(instr->GetRm());
10354     SimVRegister& zm = ReadVRegister(instr->GetRn());
10355 
10356     switch (instr->Mask(SVEFPMulAddMask)) {
10357       // zdn = za + zdn * zm
10358       case FMAD_z_p_zzz:
10359         fmla(vform, result, za, zd, zm);
10360         break;
10361       // zdn = -za + -zdn * zm
10362       case FNMAD_z_p_zzz:
10363         fneg(vform, result, za);
10364         fmls(vform, result, result, zd, zm);
10365         break;
10366       // zdn = za + -zdn * zm
10367       case FMSB_z_p_zzz:
10368         fmls(vform, result, za, zd, zm);
10369         break;
10370       // zdn = -za + zdn * zm
10371       case FNMSB_z_p_zzz:
10372         fneg(vform, result, za);
10373         fmla(vform, result, result, zd, zm);
10374         break;
10375       default:
10376         VIXL_UNIMPLEMENTED();
10377         break;
10378     }
10379   }
10380 
10381   mov_merging(vform, zd, pg, result);
10382 }
10383 
VisitSVEFPMulAddIndex(const Instruction * instr)10384 void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
10385   VectorFormat vform = kFormatUndefined;
10386 
10387   switch (instr->Mask(SVEFPMulAddIndexMask)) {
10388     case FMLA_z_zzzi_d:
10389     case FMLS_z_zzzi_d:
10390       vform = kFormatVnD;
10391       break;
10392     case FMLA_z_zzzi_s:
10393     case FMLS_z_zzzi_s:
10394       vform = kFormatVnS;
10395       break;
10396     case FMLA_z_zzzi_h:
10397     case FMLS_z_zzzi_h:
10398     case FMLA_z_zzzi_h_i3h:
10399     case FMLS_z_zzzi_h_i3h:
10400       vform = kFormatVnH;
10401       break;
10402     default:
10403       VIXL_UNIMPLEMENTED();
10404       break;
10405   }
10406 
10407   SimVRegister& zd = ReadVRegister(instr->GetRd());
10408   SimVRegister& zn = ReadVRegister(instr->GetRn());
10409   SimVRegister temp;
10410 
10411   dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
10412   if (instr->ExtractBit(10) == 1) {
10413     fmls(vform, zd, zd, zn, temp);
10414   } else {
10415     fmla(vform, zd, zd, zn, temp);
10416   }
10417 }
10418 
VisitSVEFPConvertToInt(const Instruction * instr)10419 void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
10420   SimVRegister& zd = ReadVRegister(instr->GetRd());
10421   SimVRegister& zn = ReadVRegister(instr->GetRn());
10422   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10423   int dst_data_size;
10424   int src_data_size;
10425 
10426   switch (instr->Mask(SVEFPConvertToIntMask)) {
10427     case FCVTZS_z_p_z_d2w:
10428     case FCVTZU_z_p_z_d2w:
10429       dst_data_size = kSRegSize;
10430       src_data_size = kDRegSize;
10431       break;
10432     case FCVTZS_z_p_z_d2x:
10433     case FCVTZU_z_p_z_d2x:
10434       dst_data_size = kDRegSize;
10435       src_data_size = kDRegSize;
10436       break;
10437     case FCVTZS_z_p_z_fp162h:
10438     case FCVTZU_z_p_z_fp162h:
10439       dst_data_size = kHRegSize;
10440       src_data_size = kHRegSize;
10441       break;
10442     case FCVTZS_z_p_z_fp162w:
10443     case FCVTZU_z_p_z_fp162w:
10444       dst_data_size = kSRegSize;
10445       src_data_size = kHRegSize;
10446       break;
10447     case FCVTZS_z_p_z_fp162x:
10448     case FCVTZU_z_p_z_fp162x:
10449       dst_data_size = kDRegSize;
10450       src_data_size = kHRegSize;
10451       break;
10452     case FCVTZS_z_p_z_s2w:
10453     case FCVTZU_z_p_z_s2w:
10454       dst_data_size = kSRegSize;
10455       src_data_size = kSRegSize;
10456       break;
10457     case FCVTZS_z_p_z_s2x:
10458     case FCVTZU_z_p_z_s2x:
10459       dst_data_size = kDRegSize;
10460       src_data_size = kSRegSize;
10461       break;
10462     default:
10463       VIXL_UNIMPLEMENTED();
10464       dst_data_size = 0;
10465       src_data_size = 0;
10466       break;
10467   }
10468 
10469   VectorFormat vform =
10470       SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10471 
10472   if (instr->ExtractBit(16) == 0) {
10473     fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10474   } else {
10475     fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10476   }
10477 }
10478 
VisitSVEFPConvertPrecision(const Instruction * instr)10479 void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
10480   SimVRegister& zd = ReadVRegister(instr->GetRd());
10481   SimVRegister& zn = ReadVRegister(instr->GetRn());
10482   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10483   VectorFormat dst_data_size = kFormatUndefined;
10484   VectorFormat src_data_size = kFormatUndefined;
10485 
10486   switch (instr->Mask(SVEFPConvertPrecisionMask)) {
10487     case FCVT_z_p_z_d2h:
10488       dst_data_size = kFormatVnH;
10489       src_data_size = kFormatVnD;
10490       break;
10491     case FCVT_z_p_z_d2s:
10492       dst_data_size = kFormatVnS;
10493       src_data_size = kFormatVnD;
10494       break;
10495     case FCVT_z_p_z_h2d:
10496       dst_data_size = kFormatVnD;
10497       src_data_size = kFormatVnH;
10498       break;
10499     case FCVT_z_p_z_h2s:
10500       dst_data_size = kFormatVnS;
10501       src_data_size = kFormatVnH;
10502       break;
10503     case FCVT_z_p_z_s2d:
10504       dst_data_size = kFormatVnD;
10505       src_data_size = kFormatVnS;
10506       break;
10507     case FCVT_z_p_z_s2h:
10508       dst_data_size = kFormatVnH;
10509       src_data_size = kFormatVnS;
10510       break;
10511     default:
10512       VIXL_UNIMPLEMENTED();
10513       break;
10514   }
10515 
10516   fcvt(dst_data_size, src_data_size, zd, pg, zn);
10517 }
10518 
VisitSVEFPUnaryOp(const Instruction * instr)10519 void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
10520   SimVRegister& zd = ReadVRegister(instr->GetRd());
10521   SimVRegister& zn = ReadVRegister(instr->GetRn());
10522   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10523   VectorFormat vform = instr->GetSVEVectorFormat();
10524   SimVRegister result;
10525 
10526   switch (instr->Mask(SVEFPUnaryOpMask)) {
10527     case FRECPX_z_p_z:
10528       frecpx(vform, result, zn);
10529       break;
10530     case FSQRT_z_p_z:
10531       fsqrt(vform, result, zn);
10532       break;
10533     default:
10534       VIXL_UNIMPLEMENTED();
10535       break;
10536   }
10537   mov_merging(vform, zd, pg, result);
10538 }
10539 
VisitSVEFPRoundToIntegralValue(const Instruction * instr)10540 void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
10541   SimVRegister& zd = ReadVRegister(instr->GetRd());
10542   SimVRegister& zn = ReadVRegister(instr->GetRn());
10543   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10544   VectorFormat vform = instr->GetSVEVectorFormat();
10545   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10546   bool exact_exception = false;
10547 
10548   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10549 
10550   switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
10551     case FRINTA_z_p_z:
10552       fpcr_rounding = FPTieAway;
10553       break;
10554     case FRINTI_z_p_z:
10555       break;  // Use FPCR rounding mode.
10556     case FRINTM_z_p_z:
10557       fpcr_rounding = FPNegativeInfinity;
10558       break;
10559     case FRINTN_z_p_z:
10560       fpcr_rounding = FPTieEven;
10561       break;
10562     case FRINTP_z_p_z:
10563       fpcr_rounding = FPPositiveInfinity;
10564       break;
10565     case FRINTX_z_p_z:
10566       exact_exception = true;
10567       break;
10568     case FRINTZ_z_p_z:
10569       fpcr_rounding = FPZero;
10570       break;
10571     default:
10572       VIXL_UNIMPLEMENTED();
10573       break;
10574   }
10575 
10576   SimVRegister result;
10577   frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);
10578   mov_merging(vform, zd, pg, result);
10579 }
10580 
VisitSVEIntConvertToFP(const Instruction * instr)10581 void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
10582   SimVRegister& zd = ReadVRegister(instr->GetRd());
10583   SimVRegister& zn = ReadVRegister(instr->GetRn());
10584   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10585   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10586   int dst_data_size;
10587   int src_data_size;
10588 
10589   switch (instr->Mask(SVEIntConvertToFPMask)) {
10590     case SCVTF_z_p_z_h2fp16:
10591     case UCVTF_z_p_z_h2fp16:
10592       dst_data_size = kHRegSize;
10593       src_data_size = kHRegSize;
10594       break;
10595     case SCVTF_z_p_z_w2d:
10596     case UCVTF_z_p_z_w2d:
10597       dst_data_size = kDRegSize;
10598       src_data_size = kSRegSize;
10599       break;
10600     case SCVTF_z_p_z_w2fp16:
10601     case UCVTF_z_p_z_w2fp16:
10602       dst_data_size = kHRegSize;
10603       src_data_size = kSRegSize;
10604       break;
10605     case SCVTF_z_p_z_w2s:
10606     case UCVTF_z_p_z_w2s:
10607       dst_data_size = kSRegSize;
10608       src_data_size = kSRegSize;
10609       break;
10610     case SCVTF_z_p_z_x2d:
10611     case UCVTF_z_p_z_x2d:
10612       dst_data_size = kDRegSize;
10613       src_data_size = kDRegSize;
10614       break;
10615     case SCVTF_z_p_z_x2fp16:
10616     case UCVTF_z_p_z_x2fp16:
10617       dst_data_size = kHRegSize;
10618       src_data_size = kDRegSize;
10619       break;
10620     case SCVTF_z_p_z_x2s:
10621     case UCVTF_z_p_z_x2s:
10622       dst_data_size = kSRegSize;
10623       src_data_size = kDRegSize;
10624       break;
10625     default:
10626       VIXL_UNIMPLEMENTED();
10627       dst_data_size = 0;
10628       src_data_size = 0;
10629       break;
10630   }
10631 
10632   VectorFormat vform =
10633       SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10634 
10635   if (instr->ExtractBit(16) == 0) {
10636     scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10637   } else {
10638     ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
10639   }
10640 }
10641 
VisitSVEFPUnaryOpUnpredicated(const Instruction * instr)10642 void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
10643   VectorFormat vform = instr->GetSVEVectorFormat();
10644   SimVRegister& zd = ReadVRegister(instr->GetRd());
10645   SimVRegister& zn = ReadVRegister(instr->GetRn());
10646   FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
10647 
10648   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10649 
10650   switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
10651     case FRECPE_z_z:
10652       frecpe(vform, zd, zn, fpcr_rounding);
10653       break;
10654     case FRSQRTE_z_z:
10655       frsqrte(vform, zd, zn);
10656       break;
10657     default:
10658       VIXL_UNIMPLEMENTED();
10659       break;
10660   }
10661 }
10662 
VisitSVEIncDecByPredicateCount(const Instruction * instr)10663 void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
10664   VectorFormat vform = instr->GetSVEVectorFormat();
10665   SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
10666 
10667   int count = CountActiveLanes(vform, pg);
10668 
10669   if (instr->ExtractBit(11) == 0) {
10670     SimVRegister& zdn = ReadVRegister(instr->GetRd());
10671     switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10672       case DECP_z_p_z:
10673         sub_uint(vform, zdn, zdn, count);
10674         break;
10675       case INCP_z_p_z:
10676         add_uint(vform, zdn, zdn, count);
10677         break;
10678       case SQDECP_z_p_z:
10679         sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
10680         break;
10681       case SQINCP_z_p_z:
10682         add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
10683         break;
10684       case UQDECP_z_p_z:
10685         sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
10686         break;
10687       case UQINCP_z_p_z:
10688         add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
10689         break;
10690       default:
10691         VIXL_UNIMPLEMENTED();
10692         break;
10693     }
10694   } else {
10695     bool is_saturating = (instr->ExtractBit(18) == 0);
10696     bool decrement =
10697         is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
10698     bool is_signed = (instr->ExtractBit(16) == 0);
10699     bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
10700     unsigned width = sf ? kXRegSize : kWRegSize;
10701 
10702     switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
10703       case DECP_r_p_r:
10704       case INCP_r_p_r:
10705       case SQDECP_r_p_r_sx:
10706       case SQDECP_r_p_r_x:
10707       case SQINCP_r_p_r_sx:
10708       case SQINCP_r_p_r_x:
10709       case UQDECP_r_p_r_uw:
10710       case UQDECP_r_p_r_x:
10711       case UQINCP_r_p_r_uw:
10712       case UQINCP_r_p_r_x:
10713         WriteXRegister(instr->GetRd(),
10714                        IncDecN(ReadXRegister(instr->GetRd()),
10715                                decrement ? -count : count,
10716                                width,
10717                                is_saturating,
10718                                is_signed));
10719         break;
10720       default:
10721         VIXL_UNIMPLEMENTED();
10722         break;
10723     }
10724   }
10725 }
10726 
IncDecN(uint64_t acc,int64_t delta,unsigned n,bool is_saturating,bool is_signed)10727 uint64_t Simulator::IncDecN(uint64_t acc,
10728                             int64_t delta,
10729                             unsigned n,
10730                             bool is_saturating,
10731                             bool is_signed) {
10732   VIXL_ASSERT(n <= 64);
10733   VIXL_ASSERT(IsIntN(n, delta));
10734 
10735   uint64_t sign_mask = UINT64_C(1) << (n - 1);
10736   uint64_t mask = GetUintMask(n);
10737 
10738   acc &= mask;  // Ignore initial accumulator high bits.
10739   uint64_t result = (acc + delta) & mask;
10740 
10741   bool result_negative = ((result & sign_mask) != 0);
10742 
10743   if (is_saturating) {
10744     if (is_signed) {
10745       bool acc_negative = ((acc & sign_mask) != 0);
10746       bool delta_negative = delta < 0;
10747 
10748       // If the signs of the operands are the same, but different from the
10749       // result, there was an overflow.
10750       if ((acc_negative == delta_negative) &&
10751           (acc_negative != result_negative)) {
10752         if (result_negative) {
10753           // Saturate to [..., INT<n>_MAX].
10754           result_negative = false;
10755           result = mask & ~sign_mask;  // E.g. 0x000000007fffffff
10756         } else {
10757           // Saturate to [INT<n>_MIN, ...].
10758           result_negative = true;
10759           result = ~mask | sign_mask;  // E.g. 0xffffffff80000000
10760         }
10761       }
10762     } else {
10763       if ((delta < 0) && (result > acc)) {
10764         // Saturate to [0, ...].
10765         result = 0;
10766       } else if ((delta > 0) && (result < acc)) {
10767         // Saturate to [..., UINT<n>_MAX].
10768         result = mask;
10769       }
10770     }
10771   }
10772 
10773   // Sign-extend if necessary.
10774   if (result_negative && is_signed) result |= ~mask;
10775 
10776   return result;
10777 }
10778 
VisitSVEIndexGeneration(const Instruction * instr)10779 void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
10780   VectorFormat vform = instr->GetSVEVectorFormat();
10781   SimVRegister& zd = ReadVRegister(instr->GetRd());
10782   switch (instr->Mask(SVEIndexGenerationMask)) {
10783     case INDEX_z_ii:
10784     case INDEX_z_ir:
10785     case INDEX_z_ri:
10786     case INDEX_z_rr: {
10787       uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
10788                                              : instr->ExtractSignedBits(9, 5);
10789       uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
10790                                             : instr->ExtractSignedBits(20, 16);
10791       index(vform, zd, start, step);
10792       break;
10793     }
10794     default:
10795       VIXL_UNIMPLEMENTED();
10796       break;
10797   }
10798 }
10799 
VisitSVEIntArithmeticUnpredicated(const Instruction * instr)10800 void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
10801   VectorFormat vform = instr->GetSVEVectorFormat();
10802   SimVRegister& zd = ReadVRegister(instr->GetRd());
10803   SimVRegister& zn = ReadVRegister(instr->GetRn());
10804   SimVRegister& zm = ReadVRegister(instr->GetRm());
10805   switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
10806     case ADD_z_zz:
10807       add(vform, zd, zn, zm);
10808       break;
10809     case SQADD_z_zz:
10810       add(vform, zd, zn, zm).SignedSaturate(vform);
10811       break;
10812     case SQSUB_z_zz:
10813       sub(vform, zd, zn, zm).SignedSaturate(vform);
10814       break;
10815     case SUB_z_zz:
10816       sub(vform, zd, zn, zm);
10817       break;
10818     case UQADD_z_zz:
10819       add(vform, zd, zn, zm).UnsignedSaturate(vform);
10820       break;
10821     case UQSUB_z_zz:
10822       sub(vform, zd, zn, zm).UnsignedSaturate(vform);
10823       break;
10824     default:
10825       VIXL_UNIMPLEMENTED();
10826       break;
10827   }
10828 }
10829 
VisitSVEIntAddSubtractVectors_Predicated(const Instruction * instr)10830 void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
10831     const Instruction* instr) {
10832   VectorFormat vform = instr->GetSVEVectorFormat();
10833   SimVRegister& zdn = ReadVRegister(instr->GetRd());
10834   SimVRegister& zm = ReadVRegister(instr->GetRn());
10835   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10836   SimVRegister result;
10837 
10838   switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
10839     case ADD_z_p_zz:
10840       add(vform, result, zdn, zm);
10841       break;
10842     case SUBR_z_p_zz:
10843       sub(vform, result, zm, zdn);
10844       break;
10845     case SUB_z_p_zz:
10846       sub(vform, result, zdn, zm);
10847       break;
10848     default:
10849       VIXL_UNIMPLEMENTED();
10850       break;
10851   }
10852   mov_merging(vform, zdn, pg, result);
10853 }
10854 
VisitSVEBitwiseLogical_Predicated(const Instruction * instr)10855 void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
10856   VectorFormat vform = instr->GetSVEVectorFormat();
10857   SimVRegister& zdn = ReadVRegister(instr->GetRd());
10858   SimVRegister& zm = ReadVRegister(instr->GetRn());
10859   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10860   SimVRegister result;
10861 
10862   switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
10863     case AND_z_p_zz:
10864       SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
10865       break;
10866     case BIC_z_p_zz:
10867       SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
10868       break;
10869     case EOR_z_p_zz:
10870       SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
10871       break;
10872     case ORR_z_p_zz:
10873       SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
10874       break;
10875     default:
10876       VIXL_UNIMPLEMENTED();
10877       break;
10878   }
10879   mov_merging(vform, zdn, pg, result);
10880 }
10881 
VisitSVEIntMulVectors_Predicated(const Instruction * instr)10882 void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
10883   VectorFormat vform = instr->GetSVEVectorFormat();
10884   SimVRegister& zdn = ReadVRegister(instr->GetRd());
10885   SimVRegister& zm = ReadVRegister(instr->GetRn());
10886   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10887   SimVRegister result;
10888 
10889   switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
10890     case MUL_z_p_zz:
10891       mul(vform, result, zdn, zm);
10892       break;
10893     case SMULH_z_p_zz:
10894       smulh(vform, result, zdn, zm);
10895       break;
10896     case UMULH_z_p_zz:
10897       umulh(vform, result, zdn, zm);
10898       break;
10899     default:
10900       VIXL_UNIMPLEMENTED();
10901       break;
10902   }
10903   mov_merging(vform, zdn, pg, result);
10904 }
10905 
VisitSVEIntMinMaxDifference_Predicated(const Instruction * instr)10906 void Simulator::VisitSVEIntMinMaxDifference_Predicated(
10907     const Instruction* instr) {
10908   VectorFormat vform = instr->GetSVEVectorFormat();
10909   SimVRegister& zdn = ReadVRegister(instr->GetRd());
10910   SimVRegister& zm = ReadVRegister(instr->GetRn());
10911   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10912   SimVRegister result;
10913 
10914   switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
10915     case SABD_z_p_zz:
10916       absdiff(vform, result, zdn, zm, true);
10917       break;
10918     case SMAX_z_p_zz:
10919       smax(vform, result, zdn, zm);
10920       break;
10921     case SMIN_z_p_zz:
10922       smin(vform, result, zdn, zm);
10923       break;
10924     case UABD_z_p_zz:
10925       absdiff(vform, result, zdn, zm, false);
10926       break;
10927     case UMAX_z_p_zz:
10928       umax(vform, result, zdn, zm);
10929       break;
10930     case UMIN_z_p_zz:
10931       umin(vform, result, zdn, zm);
10932       break;
10933     default:
10934       VIXL_UNIMPLEMENTED();
10935       break;
10936   }
10937   mov_merging(vform, zdn, pg, result);
10938 }
10939 
VisitSVEIntMulImm_Unpredicated(const Instruction * instr)10940 void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
10941   VectorFormat vform = instr->GetSVEVectorFormat();
10942   SimVRegister& zd = ReadVRegister(instr->GetRd());
10943   SimVRegister scratch;
10944 
10945   switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
10946     case MUL_z_zi:
10947       dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
10948       mul(vform, zd, zd, scratch);
10949       break;
10950     default:
10951       VIXL_UNIMPLEMENTED();
10952       break;
10953   }
10954 }
10955 
VisitSVEIntDivideVectors_Predicated(const Instruction * instr)10956 void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
10957   VectorFormat vform = instr->GetSVEVectorFormat();
10958   SimVRegister& zdn = ReadVRegister(instr->GetRd());
10959   SimVRegister& zm = ReadVRegister(instr->GetRn());
10960   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10961   SimVRegister result;
10962 
10963   VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
10964 
10965   switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
10966     case SDIVR_z_p_zz:
10967       sdiv(vform, result, zm, zdn);
10968       break;
10969     case SDIV_z_p_zz:
10970       sdiv(vform, result, zdn, zm);
10971       break;
10972     case UDIVR_z_p_zz:
10973       udiv(vform, result, zm, zdn);
10974       break;
10975     case UDIV_z_p_zz:
10976       udiv(vform, result, zdn, zm);
10977       break;
10978     default:
10979       VIXL_UNIMPLEMENTED();
10980       break;
10981   }
10982   mov_merging(vform, zdn, pg, result);
10983 }
10984 
VisitSVEIntMinMaxImm_Unpredicated(const Instruction * instr)10985 void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
10986   VectorFormat vform = instr->GetSVEVectorFormat();
10987   SimVRegister& zd = ReadVRegister(instr->GetRd());
10988   SimVRegister scratch;
10989 
10990   uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
10991   int64_t signed_imm = instr->GetImmSVEIntWideSigned();
10992 
10993   switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
10994     case SMAX_z_zi:
10995       dup_immediate(vform, scratch, signed_imm);
10996       smax(vform, zd, zd, scratch);
10997       break;
10998     case SMIN_z_zi:
10999       dup_immediate(vform, scratch, signed_imm);
11000       smin(vform, zd, zd, scratch);
11001       break;
11002     case UMAX_z_zi:
11003       dup_immediate(vform, scratch, unsigned_imm);
11004       umax(vform, zd, zd, scratch);
11005       break;
11006     case UMIN_z_zi:
11007       dup_immediate(vform, scratch, unsigned_imm);
11008       umin(vform, zd, zd, scratch);
11009       break;
11010     default:
11011       VIXL_UNIMPLEMENTED();
11012       break;
11013   }
11014 }
11015 
VisitSVEIntCompareScalarCountAndLimit(const Instruction * instr)11016 void Simulator::VisitSVEIntCompareScalarCountAndLimit(
11017     const Instruction* instr) {
11018   unsigned rn_code = instr->GetRn();
11019   unsigned rm_code = instr->GetRm();
11020   SimPRegister& pd = ReadPRegister(instr->GetPd());
11021   VectorFormat vform = instr->GetSVEVectorFormat();
11022 
11023   bool is_64_bit = instr->ExtractBit(12) == 1;
11024   int rsize = is_64_bit ? kXRegSize : kWRegSize;
11025   uint64_t mask = is_64_bit ? kXRegMask : kWRegMask;
11026 
11027   uint64_t usrc1 = ReadXRegister(rn_code);
11028   int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
11029   uint64_t usrc2 = ssrc2 & mask;
11030 
11031   bool reverse = (form_hash_ == "whilege_p_p_rr"_h) ||
11032                  (form_hash_ == "whilegt_p_p_rr"_h) ||
11033                  (form_hash_ == "whilehi_p_p_rr"_h) ||
11034                  (form_hash_ == "whilehs_p_p_rr"_h);
11035 
11036   int lane_count = LaneCountFromFormat(vform);
11037   bool last = true;
11038   for (int i = 0; i < lane_count; i++) {
11039     usrc1 &= mask;
11040     int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1);
11041 
11042     bool cond = false;
11043     switch (form_hash_) {
11044       case "whilele_p_p_rr"_h:
11045         cond = ssrc1 <= ssrc2;
11046         break;
11047       case "whilelo_p_p_rr"_h:
11048         cond = usrc1 < usrc2;
11049         break;
11050       case "whilels_p_p_rr"_h:
11051         cond = usrc1 <= usrc2;
11052         break;
11053       case "whilelt_p_p_rr"_h:
11054         cond = ssrc1 < ssrc2;
11055         break;
11056       case "whilege_p_p_rr"_h:
11057         cond = ssrc1 >= ssrc2;
11058         break;
11059       case "whilegt_p_p_rr"_h:
11060         cond = ssrc1 > ssrc2;
11061         break;
11062       case "whilehi_p_p_rr"_h:
11063         cond = usrc1 > usrc2;
11064         break;
11065       case "whilehs_p_p_rr"_h:
11066         cond = usrc1 >= usrc2;
11067         break;
11068       default:
11069         VIXL_UNIMPLEMENTED();
11070         break;
11071     }
11072     last = last && cond;
11073     LogicPRegister dst(pd);
11074     int lane = reverse ? ((lane_count - 1) - i) : i;
11075     dst.SetActive(vform, lane, last);
11076     usrc1 += reverse ? -1 : 1;
11077   }
11078 
11079   PredTest(vform, GetPTrue(), pd);
11080   LogSystemRegister(NZCV);
11081 }
11082 
VisitSVEConditionallyTerminateScalars(const Instruction * instr)11083 void Simulator::VisitSVEConditionallyTerminateScalars(
11084     const Instruction* instr) {
11085   unsigned rn_code = instr->GetRn();
11086   unsigned rm_code = instr->GetRm();
11087   bool is_64_bit = instr->ExtractBit(22) == 1;
11088   uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
11089   uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
11090   bool term = false;
11091   switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
11092     case CTERMEQ_rr:
11093       term = src1 == src2;
11094       break;
11095     case CTERMNE_rr:
11096       term = src1 != src2;
11097       break;
11098     default:
11099       VIXL_UNIMPLEMENTED();
11100       break;
11101   }
11102   ReadNzcv().SetN(term ? 1 : 0);
11103   ReadNzcv().SetV(term ? 0 : !ReadC());
11104   LogSystemRegister(NZCV);
11105 }
11106 
VisitSVEIntCompareSignedImm(const Instruction * instr)11107 void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
11108   bool commute_inputs = false;
11109   Condition cond = al;
11110   switch (instr->Mask(SVEIntCompareSignedImmMask)) {
11111     case CMPEQ_p_p_zi:
11112       cond = eq;
11113       break;
11114     case CMPGE_p_p_zi:
11115       cond = ge;
11116       break;
11117     case CMPGT_p_p_zi:
11118       cond = gt;
11119       break;
11120     case CMPLE_p_p_zi:
11121       cond = ge;
11122       commute_inputs = true;
11123       break;
11124     case CMPLT_p_p_zi:
11125       cond = gt;
11126       commute_inputs = true;
11127       break;
11128     case CMPNE_p_p_zi:
11129       cond = ne;
11130       break;
11131     default:
11132       VIXL_UNIMPLEMENTED();
11133       break;
11134   }
11135 
11136   VectorFormat vform = instr->GetSVEVectorFormat();
11137   SimVRegister src2;
11138   dup_immediate(vform,
11139                 src2,
11140                 ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
11141   SVEIntCompareVectorsHelper(cond,
11142                              vform,
11143                              ReadPRegister(instr->GetPd()),
11144                              ReadPRegister(instr->GetPgLow8()),
11145                              commute_inputs ? src2
11146                                             : ReadVRegister(instr->GetRn()),
11147                              commute_inputs ? ReadVRegister(instr->GetRn())
11148                                             : src2);
11149 }
11150 
VisitSVEIntCompareUnsignedImm(const Instruction * instr)11151 void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
11152   bool commute_inputs = false;
11153   Condition cond = al;
11154   switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
11155     case CMPHI_p_p_zi:
11156       cond = hi;
11157       break;
11158     case CMPHS_p_p_zi:
11159       cond = hs;
11160       break;
11161     case CMPLO_p_p_zi:
11162       cond = hi;
11163       commute_inputs = true;
11164       break;
11165     case CMPLS_p_p_zi:
11166       cond = hs;
11167       commute_inputs = true;
11168       break;
11169     default:
11170       VIXL_UNIMPLEMENTED();
11171       break;
11172   }
11173 
11174   VectorFormat vform = instr->GetSVEVectorFormat();
11175   SimVRegister src2;
11176   dup_immediate(vform, src2, instr->ExtractBits(20, 14));
11177   SVEIntCompareVectorsHelper(cond,
11178                              vform,
11179                              ReadPRegister(instr->GetPd()),
11180                              ReadPRegister(instr->GetPgLow8()),
11181                              commute_inputs ? src2
11182                                             : ReadVRegister(instr->GetRn()),
11183                              commute_inputs ? ReadVRegister(instr->GetRn())
11184                                             : src2);
11185 }
11186 
VisitSVEIntCompareVectors(const Instruction * instr)11187 void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
11188   Instr op = instr->Mask(SVEIntCompareVectorsMask);
11189   bool is_wide_elements = false;
11190   switch (op) {
11191     case CMPEQ_p_p_zw:
11192     case CMPGE_p_p_zw:
11193     case CMPGT_p_p_zw:
11194     case CMPHI_p_p_zw:
11195     case CMPHS_p_p_zw:
11196     case CMPLE_p_p_zw:
11197     case CMPLO_p_p_zw:
11198     case CMPLS_p_p_zw:
11199     case CMPLT_p_p_zw:
11200     case CMPNE_p_p_zw:
11201       is_wide_elements = true;
11202       break;
11203   }
11204 
11205   Condition cond;
11206   switch (op) {
11207     case CMPEQ_p_p_zw:
11208     case CMPEQ_p_p_zz:
11209       cond = eq;
11210       break;
11211     case CMPGE_p_p_zw:
11212     case CMPGE_p_p_zz:
11213       cond = ge;
11214       break;
11215     case CMPGT_p_p_zw:
11216     case CMPGT_p_p_zz:
11217       cond = gt;
11218       break;
11219     case CMPHI_p_p_zw:
11220     case CMPHI_p_p_zz:
11221       cond = hi;
11222       break;
11223     case CMPHS_p_p_zw:
11224     case CMPHS_p_p_zz:
11225       cond = hs;
11226       break;
11227     case CMPNE_p_p_zw:
11228     case CMPNE_p_p_zz:
11229       cond = ne;
11230       break;
11231     case CMPLE_p_p_zw:
11232       cond = le;
11233       break;
11234     case CMPLO_p_p_zw:
11235       cond = lo;
11236       break;
11237     case CMPLS_p_p_zw:
11238       cond = ls;
11239       break;
11240     case CMPLT_p_p_zw:
11241       cond = lt;
11242       break;
11243     default:
11244       VIXL_UNIMPLEMENTED();
11245       cond = al;
11246       break;
11247   }
11248 
11249   SVEIntCompareVectorsHelper(cond,
11250                              instr->GetSVEVectorFormat(),
11251                              ReadPRegister(instr->GetPd()),
11252                              ReadPRegister(instr->GetPgLow8()),
11253                              ReadVRegister(instr->GetRn()),
11254                              ReadVRegister(instr->GetRm()),
11255                              is_wide_elements);
11256 }
11257 
VisitSVEFPExponentialAccelerator(const Instruction * instr)11258 void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
11259   VectorFormat vform = instr->GetSVEVectorFormat();
11260   SimVRegister& zd = ReadVRegister(instr->GetRd());
11261   SimVRegister& zn = ReadVRegister(instr->GetRn());
11262 
11263   VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11264               (vform == kFormatVnD));
11265 
11266   switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
11267     case FEXPA_z_z:
11268       fexpa(vform, zd, zn);
11269       break;
11270     default:
11271       VIXL_UNIMPLEMENTED();
11272       break;
11273   }
11274 }
11275 
VisitSVEFPTrigSelectCoefficient(const Instruction * instr)11276 void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
11277   VectorFormat vform = instr->GetSVEVectorFormat();
11278   SimVRegister& zd = ReadVRegister(instr->GetRd());
11279   SimVRegister& zn = ReadVRegister(instr->GetRn());
11280   SimVRegister& zm = ReadVRegister(instr->GetRm());
11281 
11282   VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11283               (vform == kFormatVnD));
11284 
11285   switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
11286     case FTSSEL_z_zz:
11287       ftssel(vform, zd, zn, zm);
11288       break;
11289     default:
11290       VIXL_UNIMPLEMENTED();
11291       break;
11292   }
11293 }
11294 
VisitSVEConstructivePrefix_Unpredicated(const Instruction * instr)11295 void Simulator::VisitSVEConstructivePrefix_Unpredicated(
11296     const Instruction* instr) {
11297   SimVRegister& zd = ReadVRegister(instr->GetRd());
11298   SimVRegister& zn = ReadVRegister(instr->GetRn());
11299 
11300   switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
11301     case MOVPRFX_z_z:
11302       mov(kFormatVnD, zd, zn);  // The lane size is arbitrary.
11303       break;
11304     default:
11305       VIXL_UNIMPLEMENTED();
11306       break;
11307   }
11308 }
11309 
VisitSVEIntMulAddPredicated(const Instruction * instr)11310 void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
11311   VectorFormat vform = instr->GetSVEVectorFormat();
11312 
11313   SimVRegister& zd = ReadVRegister(instr->GetRd());
11314   SimVRegister& zm = ReadVRegister(instr->GetRm());
11315 
11316   SimVRegister result;
11317   switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
11318     case MLA_z_p_zzz:
11319       mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
11320       break;
11321     case MLS_z_p_zzz:
11322       mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
11323       break;
11324     case MAD_z_p_zzz:
11325       // 'za' is encoded in 'Rn'.
11326       mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
11327       break;
11328     case MSB_z_p_zzz: {
11329       // 'za' is encoded in 'Rn'.
11330       mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
11331       break;
11332     }
11333     default:
11334       VIXL_UNIMPLEMENTED();
11335       break;
11336   }
11337   mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
11338 }
11339 
VisitSVEIntMulAddUnpredicated(const Instruction * instr)11340 void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
11341   VectorFormat vform = instr->GetSVEVectorFormat();
11342   SimVRegister& zda = ReadVRegister(instr->GetRd());
11343   SimVRegister& zn = ReadVRegister(instr->GetRn());
11344   SimVRegister& zm = ReadVRegister(instr->GetRm());
11345 
11346   switch (form_hash_) {
11347     case "sdot_z_zzz"_h:
11348       sdot(vform, zda, zn, zm);
11349       break;
11350     case "udot_z_zzz"_h:
11351       udot(vform, zda, zn, zm);
11352       break;
11353     case "usdot_z_zzz_s"_h:
11354       usdot(vform, zda, zn, zm);
11355       break;
11356     default:
11357       VIXL_UNIMPLEMENTED();
11358       break;
11359   }
11360 }
11361 
VisitSVEMovprfx(const Instruction * instr)11362 void Simulator::VisitSVEMovprfx(const Instruction* instr) {
11363   VectorFormat vform = instr->GetSVEVectorFormat();
11364   SimVRegister& zn = ReadVRegister(instr->GetRn());
11365   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11366   SimVRegister& zd = ReadVRegister(instr->GetRd());
11367 
11368   switch (instr->Mask(SVEMovprfxMask)) {
11369     case MOVPRFX_z_p_z:
11370       if (instr->ExtractBit(16)) {
11371         mov_merging(vform, zd, pg, zn);
11372       } else {
11373         mov_zeroing(vform, zd, pg, zn);
11374       }
11375       break;
11376     default:
11377       VIXL_UNIMPLEMENTED();
11378       break;
11379   }
11380 }
11381 
VisitSVEIntReduction(const Instruction * instr)11382 void Simulator::VisitSVEIntReduction(const Instruction* instr) {
11383   VectorFormat vform = instr->GetSVEVectorFormat();
11384   SimVRegister& vd = ReadVRegister(instr->GetRd());
11385   SimVRegister& zn = ReadVRegister(instr->GetRn());
11386   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11387 
11388   if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
11389     switch (instr->Mask(SVEIntReductionLogicalMask)) {
11390       case ANDV_r_p_z:
11391         andv(vform, vd, pg, zn);
11392         break;
11393       case EORV_r_p_z:
11394         eorv(vform, vd, pg, zn);
11395         break;
11396       case ORV_r_p_z:
11397         orv(vform, vd, pg, zn);
11398         break;
11399       default:
11400         VIXL_UNIMPLEMENTED();
11401         break;
11402     }
11403   } else {
11404     switch (instr->Mask(SVEIntReductionMask)) {
11405       case SADDV_r_p_z:
11406         saddv(vform, vd, pg, zn);
11407         break;
11408       case SMAXV_r_p_z:
11409         smaxv(vform, vd, pg, zn);
11410         break;
11411       case SMINV_r_p_z:
11412         sminv(vform, vd, pg, zn);
11413         break;
11414       case UADDV_r_p_z:
11415         uaddv(vform, vd, pg, zn);
11416         break;
11417       case UMAXV_r_p_z:
11418         umaxv(vform, vd, pg, zn);
11419         break;
11420       case UMINV_r_p_z:
11421         uminv(vform, vd, pg, zn);
11422         break;
11423       default:
11424         VIXL_UNIMPLEMENTED();
11425         break;
11426     }
11427   }
11428 }
11429 
VisitSVEIntUnaryArithmeticPredicated(const Instruction * instr)11430 void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
11431   VectorFormat vform = instr->GetSVEVectorFormat();
11432   SimVRegister& zn = ReadVRegister(instr->GetRn());
11433 
11434   SimVRegister result;
11435   switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
11436     case ABS_z_p_z:
11437       abs(vform, result, zn);
11438       break;
11439     case CLS_z_p_z:
11440       cls(vform, result, zn);
11441       break;
11442     case CLZ_z_p_z:
11443       clz(vform, result, zn);
11444       break;
11445     case CNOT_z_p_z:
11446       cnot(vform, result, zn);
11447       break;
11448     case CNT_z_p_z:
11449       cnt(vform, result, zn);
11450       break;
11451     case FABS_z_p_z:
11452       fabs_(vform, result, zn);
11453       break;
11454     case FNEG_z_p_z:
11455       fneg(vform, result, zn);
11456       break;
11457     case NEG_z_p_z:
11458       neg(vform, result, zn);
11459       break;
11460     case NOT_z_p_z:
11461       not_(vform, result, zn);
11462       break;
11463     case SXTB_z_p_z:
11464     case SXTH_z_p_z:
11465     case SXTW_z_p_z:
11466       sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
11467       break;
11468     case UXTB_z_p_z:
11469     case UXTH_z_p_z:
11470     case UXTW_z_p_z:
11471       uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
11472       break;
11473     default:
11474       VIXL_UNIMPLEMENTED();
11475       break;
11476   }
11477 
11478   SimVRegister& zd = ReadVRegister(instr->GetRd());
11479   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11480   mov_merging(vform, zd, pg, result);
11481 }
11482 
VisitSVECopyFPImm_Predicated(const Instruction * instr)11483 void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
11484   // There is only one instruction in this group.
11485   VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
11486 
11487   VectorFormat vform = instr->GetSVEVectorFormat();
11488   SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
11489   SimVRegister& zd = ReadVRegister(instr->GetRd());
11490 
11491   if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
11492 
11493   SimVRegister result;
11494   switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
11495     case FCPY_z_p_i: {
11496       int imm8 = instr->ExtractBits(12, 5);
11497       uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
11498                                            Instruction::Imm8ToFP64(imm8));
11499       dup_immediate(vform, result, value);
11500       break;
11501     }
11502     default:
11503       VIXL_UNIMPLEMENTED();
11504       break;
11505   }
11506   mov_merging(vform, zd, pg, result);
11507 }
11508 
VisitSVEIntAddSubtractImm_Unpredicated(const Instruction * instr)11509 void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
11510     const Instruction* instr) {
11511   VectorFormat vform = instr->GetSVEVectorFormat();
11512   SimVRegister& zd = ReadVRegister(instr->GetRd());
11513   SimVRegister scratch;
11514 
11515   uint64_t imm = instr->GetImmSVEIntWideUnsigned();
11516   imm <<= instr->ExtractBit(13) * 8;
11517 
11518   switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
11519     case ADD_z_zi:
11520       add_uint(vform, zd, zd, imm);
11521       break;
11522     case SQADD_z_zi:
11523       add_uint(vform, zd, zd, imm).SignedSaturate(vform);
11524       break;
11525     case SQSUB_z_zi:
11526       sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
11527       break;
11528     case SUBR_z_zi:
11529       dup_immediate(vform, scratch, imm);
11530       sub(vform, zd, scratch, zd);
11531       break;
11532     case SUB_z_zi:
11533       sub_uint(vform, zd, zd, imm);
11534       break;
11535     case UQADD_z_zi:
11536       add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11537       break;
11538     case UQSUB_z_zi:
11539       sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11540       break;
11541     default:
11542       break;
11543   }
11544 }
11545 
VisitSVEBroadcastIntImm_Unpredicated(const Instruction * instr)11546 void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
11547   SimVRegister& zd = ReadVRegister(instr->GetRd());
11548 
11549   VectorFormat format = instr->GetSVEVectorFormat();
11550   int64_t imm = instr->GetImmSVEIntWideSigned();
11551   int shift = instr->ExtractBit(13) * 8;
11552   imm *= 1 << shift;
11553 
11554   switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
11555     case DUP_z_i:
11556       // The encoding of byte-sized lanes with lsl #8 is undefined.
11557       if ((format == kFormatVnB) && (shift == 8)) {
11558         VIXL_UNIMPLEMENTED();
11559       } else {
11560         dup_immediate(format, zd, imm);
11561       }
11562       break;
11563     default:
11564       VIXL_UNIMPLEMENTED();
11565       break;
11566   }
11567 }
11568 
VisitSVEBroadcastFPImm_Unpredicated(const Instruction * instr)11569 void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
11570   VectorFormat vform = instr->GetSVEVectorFormat();
11571   SimVRegister& zd = ReadVRegister(instr->GetRd());
11572 
11573   switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
11574     case FDUP_z_i:
11575       switch (vform) {
11576         case kFormatVnH:
11577           dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
11578           break;
11579         case kFormatVnS:
11580           dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
11581           break;
11582         case kFormatVnD:
11583           dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
11584           break;
11585         default:
11586           VIXL_UNIMPLEMENTED();
11587       }
11588       break;
11589     default:
11590       VIXL_UNIMPLEMENTED();
11591       break;
11592   }
11593 }
11594 
VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(const Instruction * instr)11595 void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
11596     const Instruction* instr) {
11597   switch (instr->Mask(
11598       SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
11599     case LD1H_z_p_bz_s_x32_scaled:
11600     case LD1SH_z_p_bz_s_x32_scaled:
11601     case LDFF1H_z_p_bz_s_x32_scaled:
11602     case LDFF1SH_z_p_bz_s_x32_scaled:
11603       break;
11604     default:
11605       VIXL_UNIMPLEMENTED();
11606       break;
11607   }
11608 
11609   SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11610   SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
11611 }
11612 
VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(const Instruction * instr)11613 void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
11614     const Instruction* instr) {
11615   switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
11616     case LD1B_z_p_bz_s_x32_unscaled:
11617     case LD1H_z_p_bz_s_x32_unscaled:
11618     case LD1SB_z_p_bz_s_x32_unscaled:
11619     case LD1SH_z_p_bz_s_x32_unscaled:
11620     case LD1W_z_p_bz_s_x32_unscaled:
11621     case LDFF1B_z_p_bz_s_x32_unscaled:
11622     case LDFF1H_z_p_bz_s_x32_unscaled:
11623     case LDFF1SB_z_p_bz_s_x32_unscaled:
11624     case LDFF1SH_z_p_bz_s_x32_unscaled:
11625     case LDFF1W_z_p_bz_s_x32_unscaled:
11626       break;
11627     default:
11628       VIXL_UNIMPLEMENTED();
11629       break;
11630   }
11631 
11632   SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11633   SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
11634 }
11635 
VisitSVE32BitGatherLoad_VectorPlusImm(const Instruction * instr)11636 void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
11637     const Instruction* instr) {
11638   switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
11639     case LD1B_z_p_ai_s:
11640       VIXL_UNIMPLEMENTED();
11641       break;
11642     case LD1H_z_p_ai_s:
11643       VIXL_UNIMPLEMENTED();
11644       break;
11645     case LD1SB_z_p_ai_s:
11646       VIXL_UNIMPLEMENTED();
11647       break;
11648     case LD1SH_z_p_ai_s:
11649       VIXL_UNIMPLEMENTED();
11650       break;
11651     case LD1W_z_p_ai_s:
11652       VIXL_UNIMPLEMENTED();
11653       break;
11654     case LDFF1B_z_p_ai_s:
11655       VIXL_UNIMPLEMENTED();
11656       break;
11657     case LDFF1H_z_p_ai_s:
11658       VIXL_UNIMPLEMENTED();
11659       break;
11660     case LDFF1SB_z_p_ai_s:
11661       VIXL_UNIMPLEMENTED();
11662       break;
11663     case LDFF1SH_z_p_ai_s:
11664       VIXL_UNIMPLEMENTED();
11665       break;
11666     case LDFF1W_z_p_ai_s:
11667       VIXL_UNIMPLEMENTED();
11668       break;
11669     default:
11670       VIXL_UNIMPLEMENTED();
11671       break;
11672   }
11673 }
11674 
VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(const Instruction * instr)11675 void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
11676     const Instruction* instr) {
11677   switch (
11678       instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
11679     case LD1W_z_p_bz_s_x32_scaled:
11680     case LDFF1W_z_p_bz_s_x32_scaled:
11681       break;
11682     default:
11683       VIXL_UNIMPLEMENTED();
11684       break;
11685   }
11686 
11687   SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11688   SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
11689 }
11690 
VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(const Instruction * instr)11691 void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
11692     const Instruction* instr) {
11693   switch (
11694       instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
11695     // Ignore prefetch hint instructions.
11696     case PRFB_i_p_bz_s_x32_scaled:
11697     case PRFD_i_p_bz_s_x32_scaled:
11698     case PRFH_i_p_bz_s_x32_scaled:
11699     case PRFW_i_p_bz_s_x32_scaled:
11700       break;
11701     default:
11702       VIXL_UNIMPLEMENTED();
11703       break;
11704   }
11705 }
11706 
VisitSVE32BitGatherPrefetch_VectorPlusImm(const Instruction * instr)11707 void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
11708     const Instruction* instr) {
11709   switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
11710     // Ignore prefetch hint instructions.
11711     case PRFB_i_p_ai_s:
11712     case PRFD_i_p_ai_s:
11713     case PRFH_i_p_ai_s:
11714     case PRFW_i_p_ai_s:
11715       break;
11716     default:
11717       VIXL_UNIMPLEMENTED();
11718       break;
11719   }
11720 }
11721 
VisitSVEContiguousPrefetch_ScalarPlusImm(const Instruction * instr)11722 void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
11723     const Instruction* instr) {
11724   switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
11725     // Ignore prefetch hint instructions.
11726     case PRFB_i_p_bi_s:
11727     case PRFD_i_p_bi_s:
11728     case PRFH_i_p_bi_s:
11729     case PRFW_i_p_bi_s:
11730       break;
11731     default:
11732       VIXL_UNIMPLEMENTED();
11733       break;
11734   }
11735 }
11736 
VisitSVEContiguousPrefetch_ScalarPlusScalar(const Instruction * instr)11737 void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
11738     const Instruction* instr) {
11739   switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
11740     // Ignore prefetch hint instructions.
11741     case PRFB_i_p_br_s:
11742     case PRFD_i_p_br_s:
11743     case PRFH_i_p_br_s:
11744     case PRFW_i_p_br_s:
11745       if (instr->GetRm() == kZeroRegCode) {
11746         VIXL_UNIMPLEMENTED();
11747       }
11748       break;
11749     default:
11750       VIXL_UNIMPLEMENTED();
11751       break;
11752   }
11753 }
11754 
VisitSVELoadAndBroadcastElement(const Instruction * instr)11755 void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
11756   bool is_signed;
11757   switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
11758     case LD1RB_z_p_bi_u8:
11759     case LD1RB_z_p_bi_u16:
11760     case LD1RB_z_p_bi_u32:
11761     case LD1RB_z_p_bi_u64:
11762     case LD1RH_z_p_bi_u16:
11763     case LD1RH_z_p_bi_u32:
11764     case LD1RH_z_p_bi_u64:
11765     case LD1RW_z_p_bi_u32:
11766     case LD1RW_z_p_bi_u64:
11767     case LD1RD_z_p_bi_u64:
11768       is_signed = false;
11769       break;
11770     case LD1RSB_z_p_bi_s16:
11771     case LD1RSB_z_p_bi_s32:
11772     case LD1RSB_z_p_bi_s64:
11773     case LD1RSH_z_p_bi_s32:
11774     case LD1RSH_z_p_bi_s64:
11775     case LD1RSW_z_p_bi_s64:
11776       is_signed = true;
11777       break;
11778     default:
11779       // This encoding group is complete, so no other values should be possible.
11780       VIXL_UNREACHABLE();
11781       is_signed = false;
11782       break;
11783   }
11784 
11785   int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
11786   int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);
11787   VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
11788   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
11789   uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;
11790   uint64_t base = ReadXRegister(instr->GetRn()) + offset;
11791   VectorFormat unpack_vform =
11792       SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);
11793   SimVRegister temp;
11794   ld1r(vform, unpack_vform, temp, base, is_signed);
11795   mov_zeroing(vform,
11796               ReadVRegister(instr->GetRt()),
11797               ReadPRegister(instr->GetPgLow8()),
11798               temp);
11799 }
11800 
VisitSVELoadPredicateRegister(const Instruction * instr)11801 void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
11802   switch (instr->Mask(SVELoadPredicateRegisterMask)) {
11803     case LDR_p_bi: {
11804       SimPRegister& pt = ReadPRegister(instr->GetPt());
11805       int pl = GetPredicateLengthInBytes();
11806       int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11807       uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11808       uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
11809       for (int i = 0; i < pl; i++) {
11810         pt.Insert(i, MemRead<uint8_t>(address + i));
11811       }
11812       LogPRead(instr->GetPt(), address);
11813       break;
11814     }
11815     default:
11816       VIXL_UNIMPLEMENTED();
11817       break;
11818   }
11819 }
11820 
VisitSVELoadVectorRegister(const Instruction * instr)11821 void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
11822   switch (instr->Mask(SVELoadVectorRegisterMask)) {
11823     case LDR_z_bi: {
11824       SimVRegister& zt = ReadVRegister(instr->GetRt());
11825       int vl = GetVectorLengthInBytes();
11826       int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
11827       uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
11828       uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
11829       for (int i = 0; i < vl; i++) {
11830         zt.Insert(i, MemRead<uint8_t>(address + i));
11831       }
11832       LogZRead(instr->GetRt(), address);
11833       break;
11834     }
11835     default:
11836       VIXL_UNIMPLEMENTED();
11837       break;
11838   }
11839 }
11840 
VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(const Instruction * instr)11841 void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
11842     const Instruction* instr) {
11843   switch (instr->Mask(
11844       SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
11845     case LD1D_z_p_bz_d_x32_scaled:
11846     case LD1H_z_p_bz_d_x32_scaled:
11847     case LD1SH_z_p_bz_d_x32_scaled:
11848     case LD1SW_z_p_bz_d_x32_scaled:
11849     case LD1W_z_p_bz_d_x32_scaled:
11850     case LDFF1H_z_p_bz_d_x32_scaled:
11851     case LDFF1W_z_p_bz_d_x32_scaled:
11852     case LDFF1D_z_p_bz_d_x32_scaled:
11853     case LDFF1SH_z_p_bz_d_x32_scaled:
11854     case LDFF1SW_z_p_bz_d_x32_scaled:
11855       break;
11856     default:
11857       VIXL_UNIMPLEMENTED();
11858       break;
11859   }
11860 
11861   SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11862   SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
11863 }
11864 
VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(const Instruction * instr)11865 void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
11866     const Instruction* instr) {
11867   switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
11868     case LD1D_z_p_bz_d_64_scaled:
11869     case LD1H_z_p_bz_d_64_scaled:
11870     case LD1SH_z_p_bz_d_64_scaled:
11871     case LD1SW_z_p_bz_d_64_scaled:
11872     case LD1W_z_p_bz_d_64_scaled:
11873     case LDFF1H_z_p_bz_d_64_scaled:
11874     case LDFF1W_z_p_bz_d_64_scaled:
11875     case LDFF1D_z_p_bz_d_64_scaled:
11876     case LDFF1SH_z_p_bz_d_64_scaled:
11877     case LDFF1SW_z_p_bz_d_64_scaled:
11878       break;
11879     default:
11880       VIXL_UNIMPLEMENTED();
11881       break;
11882   }
11883 
11884   SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);
11885 }
11886 
VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(const Instruction * instr)11887 void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
11888     const Instruction* instr) {
11889   switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
11890     case LD1B_z_p_bz_d_64_unscaled:
11891     case LD1D_z_p_bz_d_64_unscaled:
11892     case LD1H_z_p_bz_d_64_unscaled:
11893     case LD1SB_z_p_bz_d_64_unscaled:
11894     case LD1SH_z_p_bz_d_64_unscaled:
11895     case LD1SW_z_p_bz_d_64_unscaled:
11896     case LD1W_z_p_bz_d_64_unscaled:
11897     case LDFF1B_z_p_bz_d_64_unscaled:
11898     case LDFF1D_z_p_bz_d_64_unscaled:
11899     case LDFF1H_z_p_bz_d_64_unscaled:
11900     case LDFF1SB_z_p_bz_d_64_unscaled:
11901     case LDFF1SH_z_p_bz_d_64_unscaled:
11902     case LDFF1SW_z_p_bz_d_64_unscaled:
11903     case LDFF1W_z_p_bz_d_64_unscaled:
11904       break;
11905     default:
11906       VIXL_UNIMPLEMENTED();
11907       break;
11908   }
11909 
11910   SVEGatherLoadScalarPlusVectorHelper(instr,
11911                                       kFormatVnD,
11912                                       NO_SVE_OFFSET_MODIFIER);
11913 }
11914 
VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(const Instruction * instr)11915 void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
11916     const Instruction* instr) {
11917   switch (instr->Mask(
11918       SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
11919     case LD1B_z_p_bz_d_x32_unscaled:
11920     case LD1D_z_p_bz_d_x32_unscaled:
11921     case LD1H_z_p_bz_d_x32_unscaled:
11922     case LD1SB_z_p_bz_d_x32_unscaled:
11923     case LD1SH_z_p_bz_d_x32_unscaled:
11924     case LD1SW_z_p_bz_d_x32_unscaled:
11925     case LD1W_z_p_bz_d_x32_unscaled:
11926     case LDFF1B_z_p_bz_d_x32_unscaled:
11927     case LDFF1H_z_p_bz_d_x32_unscaled:
11928     case LDFF1W_z_p_bz_d_x32_unscaled:
11929     case LDFF1D_z_p_bz_d_x32_unscaled:
11930     case LDFF1SB_z_p_bz_d_x32_unscaled:
11931     case LDFF1SH_z_p_bz_d_x32_unscaled:
11932     case LDFF1SW_z_p_bz_d_x32_unscaled:
11933       break;
11934     default:
11935       VIXL_UNIMPLEMENTED();
11936       break;
11937   }
11938 
11939   SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
11940   SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
11941 }
11942 
VisitSVE64BitGatherLoad_VectorPlusImm(const Instruction * instr)11943 void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
11944     const Instruction* instr) {
11945   switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
11946     case LD1B_z_p_ai_d:
11947     case LD1D_z_p_ai_d:
11948     case LD1H_z_p_ai_d:
11949     case LD1SB_z_p_ai_d:
11950     case LD1SH_z_p_ai_d:
11951     case LD1SW_z_p_ai_d:
11952     case LD1W_z_p_ai_d:
11953     case LDFF1B_z_p_ai_d:
11954     case LDFF1D_z_p_ai_d:
11955     case LDFF1H_z_p_ai_d:
11956     case LDFF1SB_z_p_ai_d:
11957     case LDFF1SH_z_p_ai_d:
11958     case LDFF1SW_z_p_ai_d:
11959     case LDFF1W_z_p_ai_d:
11960       break;
11961     default:
11962       VIXL_UNIMPLEMENTED();
11963       break;
11964   }
11965   bool is_signed = instr->ExtractBit(14) == 0;
11966   bool is_ff = instr->ExtractBit(13) == 1;
11967   // Note that these instructions don't use the Dtype encoding.
11968   int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
11969   uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
11970   LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
11971   addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
11972   if (is_ff) {
11973     VIXL_UNIMPLEMENTED();
11974   } else {
11975     SVEStructuredLoadHelper(kFormatVnD,
11976                             ReadPRegister(instr->GetPgLow8()),
11977                             instr->GetRt(),
11978                             addr,
11979                             is_signed);
11980   }
11981 }
11982 
VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(const Instruction * instr)11983 void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
11984     const Instruction* instr) {
11985   switch (
11986       instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
11987     // Ignore prefetch hint instructions.
11988     case PRFB_i_p_bz_d_64_scaled:
11989     case PRFD_i_p_bz_d_64_scaled:
11990     case PRFH_i_p_bz_d_64_scaled:
11991     case PRFW_i_p_bz_d_64_scaled:
11992       break;
11993     default:
11994       VIXL_UNIMPLEMENTED();
11995       break;
11996   }
11997 }
11998 
11999 void Simulator::
VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(const Instruction * instr)12000     VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
12001         const Instruction* instr) {
12002   switch (instr->Mask(
12003       SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
12004     // Ignore prefetch hint instructions.
12005     case PRFB_i_p_bz_d_x32_scaled:
12006     case PRFD_i_p_bz_d_x32_scaled:
12007     case PRFH_i_p_bz_d_x32_scaled:
12008     case PRFW_i_p_bz_d_x32_scaled:
12009       break;
12010     default:
12011       VIXL_UNIMPLEMENTED();
12012       break;
12013   }
12014 }
12015 
VisitSVE64BitGatherPrefetch_VectorPlusImm(const Instruction * instr)12016 void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
12017     const Instruction* instr) {
12018   switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
12019     // Ignore prefetch hint instructions.
12020     case PRFB_i_p_ai_d:
12021     case PRFD_i_p_ai_d:
12022     case PRFH_i_p_ai_d:
12023     case PRFW_i_p_ai_d:
12024       break;
12025     default:
12026       VIXL_UNIMPLEMENTED();
12027       break;
12028   }
12029 }
12030 
VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(const Instruction * instr)12031 void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
12032     const Instruction* instr) {
12033   bool is_signed;
12034   switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
12035     case LDFF1B_z_p_br_u8:
12036     case LDFF1B_z_p_br_u16:
12037     case LDFF1B_z_p_br_u32:
12038     case LDFF1B_z_p_br_u64:
12039     case LDFF1H_z_p_br_u16:
12040     case LDFF1H_z_p_br_u32:
12041     case LDFF1H_z_p_br_u64:
12042     case LDFF1W_z_p_br_u32:
12043     case LDFF1W_z_p_br_u64:
12044     case LDFF1D_z_p_br_u64:
12045       is_signed = false;
12046       break;
12047     case LDFF1SB_z_p_br_s16:
12048     case LDFF1SB_z_p_br_s32:
12049     case LDFF1SB_z_p_br_s64:
12050     case LDFF1SH_z_p_br_s32:
12051     case LDFF1SH_z_p_br_s64:
12052     case LDFF1SW_z_p_br_s64:
12053       is_signed = true;
12054       break;
12055     default:
12056       // This encoding group is complete, so no other values should be possible.
12057       VIXL_UNREACHABLE();
12058       is_signed = false;
12059       break;
12060   }
12061 
12062   int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12063   int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12064   VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12065   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12066   uint64_t offset = ReadXRegister(instr->GetRm());
12067   offset <<= msize_in_bytes_log2;
12068   LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12069   addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12070   SVEFaultTolerantLoadHelper(vform,
12071                              ReadPRegister(instr->GetPgLow8()),
12072                              instr->GetRt(),
12073                              addr,
12074                              kSVEFirstFaultLoad,
12075                              is_signed);
12076 }
12077 
VisitSVEContiguousNonFaultLoad_ScalarPlusImm(const Instruction * instr)12078 void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
12079     const Instruction* instr) {
12080   bool is_signed = false;
12081   switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
12082     case LDNF1B_z_p_bi_u16:
12083     case LDNF1B_z_p_bi_u32:
12084     case LDNF1B_z_p_bi_u64:
12085     case LDNF1B_z_p_bi_u8:
12086     case LDNF1D_z_p_bi_u64:
12087     case LDNF1H_z_p_bi_u16:
12088     case LDNF1H_z_p_bi_u32:
12089     case LDNF1H_z_p_bi_u64:
12090     case LDNF1W_z_p_bi_u32:
12091     case LDNF1W_z_p_bi_u64:
12092       break;
12093     case LDNF1SB_z_p_bi_s16:
12094     case LDNF1SB_z_p_bi_s32:
12095     case LDNF1SB_z_p_bi_s64:
12096     case LDNF1SH_z_p_bi_s32:
12097     case LDNF1SH_z_p_bi_s64:
12098     case LDNF1SW_z_p_bi_s64:
12099       is_signed = true;
12100       break;
12101     default:
12102       VIXL_UNIMPLEMENTED();
12103       break;
12104   }
12105   int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12106   int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12107   VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12108   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12109   int vl = GetVectorLengthInBytes();
12110   int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12111   uint64_t offset =
12112       (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
12113   LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12114   addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12115   SVEFaultTolerantLoadHelper(vform,
12116                              ReadPRegister(instr->GetPgLow8()),
12117                              instr->GetRt(),
12118                              addr,
12119                              kSVENonFaultLoad,
12120                              is_signed);
12121 }
12122 
VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(const Instruction * instr)12123 void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
12124     const Instruction* instr) {
12125   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12126   VectorFormat vform = kFormatUndefined;
12127 
12128   switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
12129     case LDNT1B_z_p_bi_contiguous:
12130       vform = kFormatVnB;
12131       break;
12132     case LDNT1D_z_p_bi_contiguous:
12133       vform = kFormatVnD;
12134       break;
12135     case LDNT1H_z_p_bi_contiguous:
12136       vform = kFormatVnH;
12137       break;
12138     case LDNT1W_z_p_bi_contiguous:
12139       vform = kFormatVnS;
12140       break;
12141     default:
12142       VIXL_UNIMPLEMENTED();
12143       break;
12144   }
12145   int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12146   int vl = GetVectorLengthInBytes();
12147   uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12148   LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12149   addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12150   SVEStructuredLoadHelper(vform,
12151                           pg,
12152                           instr->GetRt(),
12153                           addr,
12154                           /* is_signed = */ false);
12155 }
12156 
VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(const Instruction * instr)12157 void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
12158     const Instruction* instr) {
12159   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12160   VectorFormat vform = kFormatUndefined;
12161 
12162   switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
12163     case LDNT1B_z_p_br_contiguous:
12164       vform = kFormatVnB;
12165       break;
12166     case LDNT1D_z_p_br_contiguous:
12167       vform = kFormatVnD;
12168       break;
12169     case LDNT1H_z_p_br_contiguous:
12170       vform = kFormatVnH;
12171       break;
12172     case LDNT1W_z_p_br_contiguous:
12173       vform = kFormatVnS;
12174       break;
12175     default:
12176       VIXL_UNIMPLEMENTED();
12177       break;
12178   }
12179   int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12180   uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12181   LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12182   addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12183   SVEStructuredLoadHelper(vform,
12184                           pg,
12185                           instr->GetRt(),
12186                           addr,
12187                           /* is_signed = */ false);
12188 }
12189 
VisitSVELoadAndBroadcastQOWord_ScalarPlusImm(const Instruction * instr)12190 void Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm(
12191     const Instruction* instr) {
12192   SimVRegister& zt = ReadVRegister(instr->GetRt());
12193   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12194 
12195   uint64_t dwords = 2;
12196   VectorFormat vform_dst = kFormatVnQ;
12197   if ((form_hash_ == "ld1rob_z_p_bi_u8"_h) ||
12198       (form_hash_ == "ld1roh_z_p_bi_u16"_h) ||
12199       (form_hash_ == "ld1row_z_p_bi_u32"_h) ||
12200       (form_hash_ == "ld1rod_z_p_bi_u64"_h)) {
12201     dwords = 4;
12202     vform_dst = kFormatVnO;
12203   }
12204 
12205   uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12206   uint64_t offset =
12207       instr->ExtractSignedBits(19, 16) * dwords * kDRegSizeInBytes;
12208   int msz = instr->ExtractBits(24, 23);
12209   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12210 
12211   for (unsigned i = 0; i < dwords; i++) {
12212     ld1(kFormatVnD, zt, i, addr + offset + (i * kDRegSizeInBytes));
12213   }
12214   mov_zeroing(vform, zt, pg, zt);
12215   dup_element(vform_dst, zt, zt, 0);
12216 }
12217 
VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar(const Instruction * instr)12218 void Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar(
12219     const Instruction* instr) {
12220   SimVRegister& zt = ReadVRegister(instr->GetRt());
12221   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12222 
12223   uint64_t bytes = 16;
12224   VectorFormat vform_dst = kFormatVnQ;
12225   if ((form_hash_ == "ld1rob_z_p_br_contiguous"_h) ||
12226       (form_hash_ == "ld1roh_z_p_br_contiguous"_h) ||
12227       (form_hash_ == "ld1row_z_p_br_contiguous"_h) ||
12228       (form_hash_ == "ld1rod_z_p_br_contiguous"_h)) {
12229     bytes = 32;
12230     vform_dst = kFormatVnO;
12231   }
12232 
12233   uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12234   uint64_t offset = ReadXRegister(instr->GetRm());
12235   int msz = instr->ExtractBits(24, 23);
12236   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12237   offset <<= msz;
12238   for (unsigned i = 0; i < bytes; i++) {
12239     ld1(kFormatVnB, zt, i, addr + offset + i);
12240   }
12241   mov_zeroing(vform, zt, pg, zt);
12242   dup_element(vform_dst, zt, zt, 0);
12243 }
12244 
VisitSVELoadMultipleStructures_ScalarPlusImm(const Instruction * instr)12245 void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
12246     const Instruction* instr) {
12247   switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
12248     case LD2B_z_p_bi_contiguous:
12249     case LD2D_z_p_bi_contiguous:
12250     case LD2H_z_p_bi_contiguous:
12251     case LD2W_z_p_bi_contiguous:
12252     case LD3B_z_p_bi_contiguous:
12253     case LD3D_z_p_bi_contiguous:
12254     case LD3H_z_p_bi_contiguous:
12255     case LD3W_z_p_bi_contiguous:
12256     case LD4B_z_p_bi_contiguous:
12257     case LD4D_z_p_bi_contiguous:
12258     case LD4H_z_p_bi_contiguous:
12259     case LD4W_z_p_bi_contiguous: {
12260       int vl = GetVectorLengthInBytes();
12261       int msz = instr->ExtractBits(24, 23);
12262       int reg_count = instr->ExtractBits(22, 21) + 1;
12263       uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12264       LogicSVEAddressVector addr(
12265           ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12266       addr.SetMsizeInBytesLog2(msz);
12267       addr.SetRegCount(reg_count);
12268       SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12269                               ReadPRegister(instr->GetPgLow8()),
12270                               instr->GetRt(),
12271                               addr);
12272       break;
12273     }
12274     default:
12275       VIXL_UNIMPLEMENTED();
12276       break;
12277   }
12278 }
12279 
VisitSVELoadMultipleStructures_ScalarPlusScalar(const Instruction * instr)12280 void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
12281     const Instruction* instr) {
12282   switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
12283     case LD2B_z_p_br_contiguous:
12284     case LD2D_z_p_br_contiguous:
12285     case LD2H_z_p_br_contiguous:
12286     case LD2W_z_p_br_contiguous:
12287     case LD3B_z_p_br_contiguous:
12288     case LD3D_z_p_br_contiguous:
12289     case LD3H_z_p_br_contiguous:
12290     case LD3W_z_p_br_contiguous:
12291     case LD4B_z_p_br_contiguous:
12292     case LD4D_z_p_br_contiguous:
12293     case LD4H_z_p_br_contiguous:
12294     case LD4W_z_p_br_contiguous: {
12295       int msz = instr->ExtractBits(24, 23);
12296       uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12297       VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12298       LogicSVEAddressVector addr(
12299           ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12300       addr.SetMsizeInBytesLog2(msz);
12301       addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12302       SVEStructuredLoadHelper(vform,
12303                               ReadPRegister(instr->GetPgLow8()),
12304                               instr->GetRt(),
12305                               addr,
12306                               false);
12307       break;
12308     }
12309     default:
12310       VIXL_UNIMPLEMENTED();
12311       break;
12312   }
12313 }
12314 
VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(const Instruction * instr)12315 void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
12316     const Instruction* instr) {
12317   switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
12318     case ST1H_z_p_bz_s_x32_scaled:
12319     case ST1W_z_p_bz_s_x32_scaled: {
12320       unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12321       VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12322       int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12323       uint64_t base = ReadXRegister(instr->GetRn());
12324       SVEOffsetModifier mod =
12325           (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12326       LogicSVEAddressVector addr(base,
12327                                  &ReadVRegister(instr->GetRm()),
12328                                  kFormatVnS,
12329                                  mod,
12330                                  scale);
12331       addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12332       SVEStructuredStoreHelper(kFormatVnS,
12333                                ReadPRegister(instr->GetPgLow8()),
12334                                instr->GetRt(),
12335                                addr);
12336       break;
12337     }
12338     default:
12339       VIXL_UNIMPLEMENTED();
12340       break;
12341   }
12342 }
12343 
VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(const Instruction * instr)12344 void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
12345     const Instruction* instr) {
12346   switch (
12347       instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
12348     case ST1B_z_p_bz_s_x32_unscaled:
12349     case ST1H_z_p_bz_s_x32_unscaled:
12350     case ST1W_z_p_bz_s_x32_unscaled: {
12351       unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12352       VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12353       uint64_t base = ReadXRegister(instr->GetRn());
12354       SVEOffsetModifier mod =
12355           (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12356       LogicSVEAddressVector addr(base,
12357                                  &ReadVRegister(instr->GetRm()),
12358                                  kFormatVnS,
12359                                  mod);
12360       addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12361       SVEStructuredStoreHelper(kFormatVnS,
12362                                ReadPRegister(instr->GetPgLow8()),
12363                                instr->GetRt(),
12364                                addr);
12365       break;
12366     }
12367     default:
12368       VIXL_UNIMPLEMENTED();
12369       break;
12370   }
12371 }
12372 
VisitSVE32BitScatterStore_VectorPlusImm(const Instruction * instr)12373 void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
12374     const Instruction* instr) {
12375   int msz = 0;
12376   switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
12377     case ST1B_z_p_ai_s:
12378       msz = 0;
12379       break;
12380     case ST1H_z_p_ai_s:
12381       msz = 1;
12382       break;
12383     case ST1W_z_p_ai_s:
12384       msz = 2;
12385       break;
12386     default:
12387       VIXL_UNIMPLEMENTED();
12388       break;
12389   }
12390   uint64_t imm = instr->ExtractBits(20, 16) << msz;
12391   LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);
12392   addr.SetMsizeInBytesLog2(msz);
12393   SVEStructuredStoreHelper(kFormatVnS,
12394                            ReadPRegister(instr->GetPgLow8()),
12395                            instr->GetRt(),
12396                            addr);
12397 }
12398 
VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(const Instruction * instr)12399 void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
12400     const Instruction* instr) {
12401   switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
12402     case ST1D_z_p_bz_d_64_scaled:
12403     case ST1H_z_p_bz_d_64_scaled:
12404     case ST1W_z_p_bz_d_64_scaled: {
12405       unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12406       VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12407       int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12408       uint64_t base = ReadXRegister(instr->GetRn());
12409       LogicSVEAddressVector addr(base,
12410                                  &ReadVRegister(instr->GetRm()),
12411                                  kFormatVnD,
12412                                  SVE_LSL,
12413                                  scale);
12414       addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12415       SVEStructuredStoreHelper(kFormatVnD,
12416                                ReadPRegister(instr->GetPgLow8()),
12417                                instr->GetRt(),
12418                                addr);
12419       break;
12420     }
12421     default:
12422       VIXL_UNIMPLEMENTED();
12423       break;
12424   }
12425 }
12426 
VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(const Instruction * instr)12427 void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
12428     const Instruction* instr) {
12429   switch (
12430       instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
12431     case ST1B_z_p_bz_d_64_unscaled:
12432     case ST1D_z_p_bz_d_64_unscaled:
12433     case ST1H_z_p_bz_d_64_unscaled:
12434     case ST1W_z_p_bz_d_64_unscaled: {
12435       unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12436       VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12437       uint64_t base = ReadXRegister(instr->GetRn());
12438       LogicSVEAddressVector addr(base,
12439                                  &ReadVRegister(instr->GetRm()),
12440                                  kFormatVnD,
12441                                  NO_SVE_OFFSET_MODIFIER);
12442       addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12443       SVEStructuredStoreHelper(kFormatVnD,
12444                                ReadPRegister(instr->GetPgLow8()),
12445                                instr->GetRt(),
12446                                addr);
12447       break;
12448     }
12449     default:
12450       VIXL_UNIMPLEMENTED();
12451       break;
12452   }
12453 }
12454 
VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(const Instruction * instr)12455 void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
12456     const Instruction* instr) {
12457   switch (instr->Mask(
12458       SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
12459     case ST1D_z_p_bz_d_x32_scaled:
12460     case ST1H_z_p_bz_d_x32_scaled:
12461     case ST1W_z_p_bz_d_x32_scaled: {
12462       unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12463       VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12464       int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12465       uint64_t base = ReadXRegister(instr->GetRn());
12466       SVEOffsetModifier mod =
12467           (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12468       LogicSVEAddressVector addr(base,
12469                                  &ReadVRegister(instr->GetRm()),
12470                                  kFormatVnD,
12471                                  mod,
12472                                  scale);
12473       addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12474       SVEStructuredStoreHelper(kFormatVnD,
12475                                ReadPRegister(instr->GetPgLow8()),
12476                                instr->GetRt(),
12477                                addr);
12478       break;
12479     }
12480     default:
12481       VIXL_UNIMPLEMENTED();
12482       break;
12483   }
12484 }
12485 
12486 void Simulator::
VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(const Instruction * instr)12487     VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
12488         const Instruction* instr) {
12489   switch (instr->Mask(
12490       SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
12491     case ST1B_z_p_bz_d_x32_unscaled:
12492     case ST1D_z_p_bz_d_x32_unscaled:
12493     case ST1H_z_p_bz_d_x32_unscaled:
12494     case ST1W_z_p_bz_d_x32_unscaled: {
12495       unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12496       VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12497       uint64_t base = ReadXRegister(instr->GetRn());
12498       SVEOffsetModifier mod =
12499           (instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12500       LogicSVEAddressVector addr(base,
12501                                  &ReadVRegister(instr->GetRm()),
12502                                  kFormatVnD,
12503                                  mod);
12504       addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12505       SVEStructuredStoreHelper(kFormatVnD,
12506                                ReadPRegister(instr->GetPgLow8()),
12507                                instr->GetRt(),
12508                                addr);
12509       break;
12510     }
12511     default:
12512       VIXL_UNIMPLEMENTED();
12513       break;
12514   }
12515 }
12516 
VisitSVE64BitScatterStore_VectorPlusImm(const Instruction * instr)12517 void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
12518     const Instruction* instr) {
12519   int msz = 0;
12520   switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
12521     case ST1B_z_p_ai_d:
12522       msz = 0;
12523       break;
12524     case ST1D_z_p_ai_d:
12525       msz = 3;
12526       break;
12527     case ST1H_z_p_ai_d:
12528       msz = 1;
12529       break;
12530     case ST1W_z_p_ai_d:
12531       msz = 2;
12532       break;
12533     default:
12534       VIXL_UNIMPLEMENTED();
12535       break;
12536   }
12537   uint64_t imm = instr->ExtractBits(20, 16) << msz;
12538   LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
12539   addr.SetMsizeInBytesLog2(msz);
12540   SVEStructuredStoreHelper(kFormatVnD,
12541                            ReadPRegister(instr->GetPgLow8()),
12542                            instr->GetRt(),
12543                            addr);
12544 }
12545 
VisitSVEContiguousNonTemporalStore_ScalarPlusImm(const Instruction * instr)12546 void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
12547     const Instruction* instr) {
12548   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12549   VectorFormat vform = kFormatUndefined;
12550 
12551   switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
12552     case STNT1B_z_p_bi_contiguous:
12553       vform = kFormatVnB;
12554       break;
12555     case STNT1D_z_p_bi_contiguous:
12556       vform = kFormatVnD;
12557       break;
12558     case STNT1H_z_p_bi_contiguous:
12559       vform = kFormatVnH;
12560       break;
12561     case STNT1W_z_p_bi_contiguous:
12562       vform = kFormatVnS;
12563       break;
12564     default:
12565       VIXL_UNIMPLEMENTED();
12566       break;
12567   }
12568   int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12569   int vl = GetVectorLengthInBytes();
12570   uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12571   LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12572   addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12573   SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
12574 }
12575 
VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(const Instruction * instr)12576 void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
12577     const Instruction* instr) {
12578   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12579   VectorFormat vform = kFormatUndefined;
12580 
12581   switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
12582     case STNT1B_z_p_br_contiguous:
12583       vform = kFormatVnB;
12584       break;
12585     case STNT1D_z_p_br_contiguous:
12586       vform = kFormatVnD;
12587       break;
12588     case STNT1H_z_p_br_contiguous:
12589       vform = kFormatVnH;
12590       break;
12591     case STNT1W_z_p_br_contiguous:
12592       vform = kFormatVnS;
12593       break;
12594     default:
12595       VIXL_UNIMPLEMENTED();
12596       break;
12597   }
12598   int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12599   uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12600   LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12601   addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12602   SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
12603 }
12604 
VisitSVEContiguousStore_ScalarPlusImm(const Instruction * instr)12605 void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
12606     const Instruction* instr) {
12607   switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
12608     case ST1B_z_p_bi:
12609     case ST1D_z_p_bi:
12610     case ST1H_z_p_bi:
12611     case ST1W_z_p_bi: {
12612       int vl = GetVectorLengthInBytes();
12613       int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12614       int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
12615       VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
12616       int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12617       uint64_t offset =
12618           (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
12619       VectorFormat vform =
12620           SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12621       LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12622       addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12623       SVEStructuredStoreHelper(vform,
12624                                ReadPRegister(instr->GetPgLow8()),
12625                                instr->GetRt(),
12626                                addr);
12627       break;
12628     }
12629     default:
12630       VIXL_UNIMPLEMENTED();
12631       break;
12632   }
12633 }
12634 
VisitSVEContiguousStore_ScalarPlusScalar(const Instruction * instr)12635 void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
12636     const Instruction* instr) {
12637   switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
12638     case ST1B_z_p_br:
12639     case ST1D_z_p_br:
12640     case ST1H_z_p_br:
12641     case ST1W_z_p_br: {
12642       uint64_t offset = ReadXRegister(instr->GetRm());
12643       offset <<= instr->ExtractBits(24, 23);
12644       VectorFormat vform =
12645           SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
12646       LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
12647       addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
12648       SVEStructuredStoreHelper(vform,
12649                                ReadPRegister(instr->GetPgLow8()),
12650                                instr->GetRt(),
12651                                addr);
12652       break;
12653     }
12654     default:
12655       VIXL_UNIMPLEMENTED();
12656       break;
12657   }
12658 }
12659 
VisitSVECopySIMDFPScalarRegisterToVector_Predicated(const Instruction * instr)12660 void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
12661     const Instruction* instr) {
12662   VectorFormat vform = instr->GetSVEVectorFormat();
12663   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12664   SimVRegister z_result;
12665 
12666   switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
12667     case CPY_z_p_v:
12668       dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
12669       mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
12670       break;
12671     default:
12672       VIXL_UNIMPLEMENTED();
12673       break;
12674   }
12675 }
12676 
VisitSVEStoreMultipleStructures_ScalarPlusImm(const Instruction * instr)12677 void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
12678     const Instruction* instr) {
12679   switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
12680     case ST2B_z_p_bi_contiguous:
12681     case ST2D_z_p_bi_contiguous:
12682     case ST2H_z_p_bi_contiguous:
12683     case ST2W_z_p_bi_contiguous:
12684     case ST3B_z_p_bi_contiguous:
12685     case ST3D_z_p_bi_contiguous:
12686     case ST3H_z_p_bi_contiguous:
12687     case ST3W_z_p_bi_contiguous:
12688     case ST4B_z_p_bi_contiguous:
12689     case ST4D_z_p_bi_contiguous:
12690     case ST4H_z_p_bi_contiguous:
12691     case ST4W_z_p_bi_contiguous: {
12692       int vl = GetVectorLengthInBytes();
12693       int msz = instr->ExtractBits(24, 23);
12694       int reg_count = instr->ExtractBits(22, 21) + 1;
12695       uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12696       LogicSVEAddressVector addr(
12697           ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12698       addr.SetMsizeInBytesLog2(msz);
12699       addr.SetRegCount(reg_count);
12700       SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12701                                ReadPRegister(instr->GetPgLow8()),
12702                                instr->GetRt(),
12703                                addr);
12704       break;
12705     }
12706     default:
12707       VIXL_UNIMPLEMENTED();
12708       break;
12709   }
12710 }
12711 
VisitSVEStoreMultipleStructures_ScalarPlusScalar(const Instruction * instr)12712 void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
12713     const Instruction* instr) {
12714   switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
12715     case ST2B_z_p_br_contiguous:
12716     case ST2D_z_p_br_contiguous:
12717     case ST2H_z_p_br_contiguous:
12718     case ST2W_z_p_br_contiguous:
12719     case ST3B_z_p_br_contiguous:
12720     case ST3D_z_p_br_contiguous:
12721     case ST3H_z_p_br_contiguous:
12722     case ST3W_z_p_br_contiguous:
12723     case ST4B_z_p_br_contiguous:
12724     case ST4D_z_p_br_contiguous:
12725     case ST4H_z_p_br_contiguous:
12726     case ST4W_z_p_br_contiguous: {
12727       int msz = instr->ExtractBits(24, 23);
12728       uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12729       VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12730       LogicSVEAddressVector addr(
12731           ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12732       addr.SetMsizeInBytesLog2(msz);
12733       addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12734       SVEStructuredStoreHelper(vform,
12735                                ReadPRegister(instr->GetPgLow8()),
12736                                instr->GetRt(),
12737                                addr);
12738       break;
12739     }
12740     default:
12741       VIXL_UNIMPLEMENTED();
12742       break;
12743   }
12744 }
12745 
VisitSVEStorePredicateRegister(const Instruction * instr)12746 void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
12747   switch (instr->Mask(SVEStorePredicateRegisterMask)) {
12748     case STR_p_bi: {
12749       SimPRegister& pt = ReadPRegister(instr->GetPt());
12750       int pl = GetPredicateLengthInBytes();
12751       int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12752       uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12753       uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * pl;
12754       for (int i = 0; i < pl; i++) {
12755         MemWrite(address + i, pt.GetLane<uint8_t>(i));
12756       }
12757       LogPWrite(instr->GetPt(), address);
12758       break;
12759     }
12760     default:
12761       VIXL_UNIMPLEMENTED();
12762       break;
12763   }
12764 }
12765 
VisitSVEStoreVectorRegister(const Instruction * instr)12766 void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
12767   switch (instr->Mask(SVEStoreVectorRegisterMask)) {
12768     case STR_z_bi: {
12769       SimVRegister& zt = ReadVRegister(instr->GetRt());
12770       int vl = GetVectorLengthInBytes();
12771       int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12772       uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12773       uint64_t address = ReadXRegister(instr->GetRn()) + multiplier * vl;
12774       for (int i = 0; i < vl; i++) {
12775         MemWrite(address + i, zt.GetLane<uint8_t>(i));
12776       }
12777       LogZWrite(instr->GetRt(), address);
12778       break;
12779     }
12780     default:
12781       VIXL_UNIMPLEMENTED();
12782       break;
12783   }
12784 }
12785 
VisitSVEMulIndex(const Instruction * instr)12786 void Simulator::VisitSVEMulIndex(const Instruction* instr) {
12787   VectorFormat vform = instr->GetSVEVectorFormat();
12788   SimVRegister& zda = ReadVRegister(instr->GetRd());
12789   SimVRegister& zn = ReadVRegister(instr->GetRn());
12790   std::pair<int, int> zm_and_index = instr->GetSVEMulZmAndIndex();
12791   SimVRegister zm = ReadVRegister(zm_and_index.first);
12792   int index = zm_and_index.second;
12793 
12794   SimVRegister temp;
12795   dup_elements_to_segments(vform, temp, zm, index);
12796 
12797   switch (form_hash_) {
12798     case "sdot_z_zzzi_d"_h:
12799     case "sdot_z_zzzi_s"_h:
12800       sdot(vform, zda, zn, temp);
12801       break;
12802     case "udot_z_zzzi_d"_h:
12803     case "udot_z_zzzi_s"_h:
12804       udot(vform, zda, zn, temp);
12805       break;
12806     case "sudot_z_zzzi_s"_h:
12807       usdot(vform, zda, temp, zn);
12808       break;
12809     case "usdot_z_zzzi_s"_h:
12810       usdot(vform, zda, zn, temp);
12811       break;
12812     default:
12813       VIXL_UNIMPLEMENTED();
12814       break;
12815   }
12816 }
12817 
SimulateMatrixMul(const Instruction * instr)12818 void Simulator::SimulateMatrixMul(const Instruction* instr) {
12819   VectorFormat vform = kFormatVnS;
12820   SimVRegister& dn = ReadVRegister(instr->GetRd());
12821   SimVRegister& n = ReadVRegister(instr->GetRn());
12822   SimVRegister& m = ReadVRegister(instr->GetRm());
12823 
12824   bool n_signed = false;
12825   bool m_signed = false;
12826   switch (form_hash_) {
12827     case "smmla_asimdsame2_g"_h:
12828       vform = kFormat4S;
12829       VIXL_FALLTHROUGH();
12830     case "smmla_z_zzz"_h:
12831       n_signed = m_signed = true;
12832       break;
12833     case "ummla_asimdsame2_g"_h:
12834       vform = kFormat4S;
12835       VIXL_FALLTHROUGH();
12836     case "ummla_z_zzz"_h:
12837       // Nothing to do.
12838       break;
12839     case "usmmla_asimdsame2_g"_h:
12840       vform = kFormat4S;
12841       VIXL_FALLTHROUGH();
12842     case "usmmla_z_zzz"_h:
12843       m_signed = true;
12844       break;
12845     default:
12846       VIXL_UNIMPLEMENTED();
12847       break;
12848   }
12849   matmul(vform, dn, n, m, n_signed, m_signed);
12850 }
12851 
SimulateSVEFPMatrixMul(const Instruction * instr)12852 void Simulator::SimulateSVEFPMatrixMul(const Instruction* instr) {
12853   VectorFormat vform = instr->GetSVEVectorFormat();
12854   SimVRegister& zdn = ReadVRegister(instr->GetRd());
12855   SimVRegister& zn = ReadVRegister(instr->GetRn());
12856   SimVRegister& zm = ReadVRegister(instr->GetRm());
12857 
12858   switch (form_hash_) {
12859     case "fmmla_z_zzz_s"_h:
12860     case "fmmla_z_zzz_d"_h:
12861       fmatmul(vform, zdn, zn, zm);
12862       break;
12863     default:
12864       VIXL_UNIMPLEMENTED();
12865       break;
12866   }
12867 }
12868 
VisitSVEPartitionBreakCondition(const Instruction * instr)12869 void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
12870   SimPRegister& pd = ReadPRegister(instr->GetPd());
12871   SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12872   SimPRegister& pn = ReadPRegister(instr->GetPn());
12873   SimPRegister result;
12874 
12875   switch (instr->Mask(SVEPartitionBreakConditionMask)) {
12876     case BRKAS_p_p_p_z:
12877     case BRKA_p_p_p:
12878       brka(result, pg, pn);
12879       break;
12880     case BRKBS_p_p_p_z:
12881     case BRKB_p_p_p:
12882       brkb(result, pg, pn);
12883       break;
12884     default:
12885       VIXL_UNIMPLEMENTED();
12886       break;
12887   }
12888 
12889   if (instr->ExtractBit(4) == 1) {
12890     mov_merging(pd, pg, result);
12891   } else {
12892     mov_zeroing(pd, pg, result);
12893   }
12894 
12895   // Set flag if needed.
12896   if (instr->ExtractBit(22) == 1) {
12897     PredTest(kFormatVnB, pg, pd);
12898   }
12899 }
12900 
VisitSVEPropagateBreakToNextPartition(const Instruction * instr)12901 void Simulator::VisitSVEPropagateBreakToNextPartition(
12902     const Instruction* instr) {
12903   SimPRegister& pdm = ReadPRegister(instr->GetPd());
12904   SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
12905   SimPRegister& pn = ReadPRegister(instr->GetPn());
12906 
12907   switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
12908     case BRKNS_p_p_pp:
12909     case BRKN_p_p_pp:
12910       brkn(pdm, pg, pn);
12911       break;
12912     default:
12913       VIXL_UNIMPLEMENTED();
12914       break;
12915   }
12916 
12917   // Set flag if needed.
12918   if (instr->ExtractBit(22) == 1) {
12919     // Note that this ignores `pg`.
12920     PredTest(kFormatVnB, GetPTrue(), pdm);
12921   }
12922 }
12923 
VisitSVEUnpackPredicateElements(const Instruction * instr)12924 void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
12925   SimPRegister& pd = ReadPRegister(instr->GetPd());
12926   SimPRegister& pn = ReadPRegister(instr->GetPn());
12927 
12928   SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12929   SimVRegister zero;
12930   dup_immediate(kFormatVnB, zero, 0);
12931 
12932   switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
12933     case PUNPKHI_p_p:
12934       zip2(kFormatVnB, temp, temp, zero);
12935       break;
12936     case PUNPKLO_p_p:
12937       zip1(kFormatVnB, temp, temp, zero);
12938       break;
12939     default:
12940       VIXL_UNIMPLEMENTED();
12941       break;
12942   }
12943   Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
12944 }
12945 
VisitSVEPermutePredicateElements(const Instruction * instr)12946 void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
12947   VectorFormat vform = instr->GetSVEVectorFormat();
12948   SimPRegister& pd = ReadPRegister(instr->GetPd());
12949   SimPRegister& pn = ReadPRegister(instr->GetPn());
12950   SimPRegister& pm = ReadPRegister(instr->GetPm());
12951 
12952   SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
12953   SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
12954 
12955   switch (instr->Mask(SVEPermutePredicateElementsMask)) {
12956     case TRN1_p_pp:
12957       trn1(vform, temp0, temp0, temp1);
12958       break;
12959     case TRN2_p_pp:
12960       trn2(vform, temp0, temp0, temp1);
12961       break;
12962     case UZP1_p_pp:
12963       uzp1(vform, temp0, temp0, temp1);
12964       break;
12965     case UZP2_p_pp:
12966       uzp2(vform, temp0, temp0, temp1);
12967       break;
12968     case ZIP1_p_pp:
12969       zip1(vform, temp0, temp0, temp1);
12970       break;
12971     case ZIP2_p_pp:
12972       zip2(vform, temp0, temp0, temp1);
12973       break;
12974     default:
12975       VIXL_UNIMPLEMENTED();
12976       break;
12977   }
12978   Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);
12979 }
12980 
VisitSVEReversePredicateElements(const Instruction * instr)12981 void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
12982   switch (instr->Mask(SVEReversePredicateElementsMask)) {
12983     case REV_p_p: {
12984       VectorFormat vform = instr->GetSVEVectorFormat();
12985       SimPRegister& pn = ReadPRegister(instr->GetPn());
12986       SimPRegister& pd = ReadPRegister(instr->GetPd());
12987       SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
12988       rev(vform, temp, temp);
12989       Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
12990       break;
12991     }
12992     default:
12993       VIXL_UNIMPLEMENTED();
12994       break;
12995   }
12996 }
12997 
VisitSVEPermuteVectorExtract(const Instruction * instr)12998 void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
12999   SimVRegister& zdn = ReadVRegister(instr->GetRd());
13000   // Second source register "Zm" is encoded where "Zn" would usually be.
13001   SimVRegister& zm = ReadVRegister(instr->GetRn());
13002 
13003   int index = instr->GetSVEExtractImmediate();
13004   int vl = GetVectorLengthInBytes();
13005   index = (index >= vl) ? 0 : index;
13006 
13007   switch (instr->Mask(SVEPermuteVectorExtractMask)) {
13008     case EXT_z_zi_des:
13009       ext(kFormatVnB, zdn, zdn, zm, index);
13010       break;
13011     default:
13012       VIXL_UNIMPLEMENTED();
13013       break;
13014   }
13015 }
13016 
VisitSVEPermuteVectorInterleaving(const Instruction * instr)13017 void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
13018   VectorFormat vform = instr->GetSVEVectorFormat();
13019   SimVRegister& zd = ReadVRegister(instr->GetRd());
13020   SimVRegister& zn = ReadVRegister(instr->GetRn());
13021   SimVRegister& zm = ReadVRegister(instr->GetRm());
13022 
13023   switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
13024     case TRN1_z_zz:
13025       trn1(vform, zd, zn, zm);
13026       break;
13027     case TRN2_z_zz:
13028       trn2(vform, zd, zn, zm);
13029       break;
13030     case UZP1_z_zz:
13031       uzp1(vform, zd, zn, zm);
13032       break;
13033     case UZP2_z_zz:
13034       uzp2(vform, zd, zn, zm);
13035       break;
13036     case ZIP1_z_zz:
13037       zip1(vform, zd, zn, zm);
13038       break;
13039     case ZIP2_z_zz:
13040       zip2(vform, zd, zn, zm);
13041       break;
13042     default:
13043       VIXL_UNIMPLEMENTED();
13044       break;
13045   }
13046 }
13047 
VisitSVEConditionallyBroadcastElementToVector(const Instruction * instr)13048 void Simulator::VisitSVEConditionallyBroadcastElementToVector(
13049     const Instruction* instr) {
13050   VectorFormat vform = instr->GetSVEVectorFormat();
13051   SimVRegister& zdn = ReadVRegister(instr->GetRd());
13052   SimVRegister& zm = ReadVRegister(instr->GetRn());
13053   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13054 
13055   int active_offset = -1;
13056   switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
13057     case CLASTA_z_p_zz:
13058       active_offset = 1;
13059       break;
13060     case CLASTB_z_p_zz:
13061       active_offset = 0;
13062       break;
13063     default:
13064       VIXL_UNIMPLEMENTED();
13065       break;
13066   }
13067 
13068   if (active_offset >= 0) {
13069     std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13070     if (value.first) {
13071       dup_immediate(vform, zdn, value.second);
13072     } else {
13073       // Trigger a line of trace for the operation, even though it doesn't
13074       // change the register value.
13075       mov(vform, zdn, zdn);
13076     }
13077   }
13078 }
13079 
VisitSVEConditionallyExtractElementToSIMDFPScalar(const Instruction * instr)13080 void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
13081     const Instruction* instr) {
13082   VectorFormat vform = instr->GetSVEVectorFormat();
13083   SimVRegister& vdn = ReadVRegister(instr->GetRd());
13084   SimVRegister& zm = ReadVRegister(instr->GetRn());
13085   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13086 
13087   int active_offset = -1;
13088   switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
13089     case CLASTA_v_p_z:
13090       active_offset = 1;
13091       break;
13092     case CLASTB_v_p_z:
13093       active_offset = 0;
13094       break;
13095     default:
13096       VIXL_UNIMPLEMENTED();
13097       break;
13098   }
13099 
13100   if (active_offset >= 0) {
13101     LogicVRegister dst(vdn);
13102     uint64_t src1_value = dst.Uint(vform, 0);
13103     std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);
13104     dup_immediate(vform, vdn, 0);
13105     dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);
13106   }
13107 }
13108 
VisitSVEConditionallyExtractElementToGeneralRegister(const Instruction * instr)13109 void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
13110     const Instruction* instr) {
13111   VectorFormat vform = instr->GetSVEVectorFormat();
13112   SimVRegister& zm = ReadVRegister(instr->GetRn());
13113   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13114 
13115   int active_offset = -1;
13116   switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
13117     case CLASTA_r_p_z:
13118       active_offset = 1;
13119       break;
13120     case CLASTB_r_p_z:
13121       active_offset = 0;
13122       break;
13123     default:
13124       VIXL_UNIMPLEMENTED();
13125       break;
13126   }
13127 
13128   if (active_offset >= 0) {
13129     std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13130     uint64_t masked_src = ReadXRegister(instr->GetRd()) &
13131                           GetUintMask(LaneSizeInBitsFromFormat(vform));
13132     WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);
13133   }
13134 }
13135 
VisitSVEExtractElementToSIMDFPScalarRegister(const Instruction * instr)13136 void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
13137     const Instruction* instr) {
13138   VectorFormat vform = instr->GetSVEVectorFormat();
13139   SimVRegister& vdn = ReadVRegister(instr->GetRd());
13140   SimVRegister& zm = ReadVRegister(instr->GetRn());
13141   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13142 
13143   int active_offset = -1;
13144   switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
13145     case LASTA_v_p_z:
13146       active_offset = 1;
13147       break;
13148     case LASTB_v_p_z:
13149       active_offset = 0;
13150       break;
13151     default:
13152       VIXL_UNIMPLEMENTED();
13153       break;
13154   }
13155 
13156   if (active_offset >= 0) {
13157     LogicVRegister dst(vdn);
13158     std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13159     dup_immediate(vform, vdn, 0);
13160     dst.SetUint(vform, 0, value.second);
13161   }
13162 }
13163 
VisitSVEExtractElementToGeneralRegister(const Instruction * instr)13164 void Simulator::VisitSVEExtractElementToGeneralRegister(
13165     const Instruction* instr) {
13166   VectorFormat vform = instr->GetSVEVectorFormat();
13167   SimVRegister& zm = ReadVRegister(instr->GetRn());
13168   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13169 
13170   int active_offset = -1;
13171   switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
13172     case LASTA_r_p_z:
13173       active_offset = 1;
13174       break;
13175     case LASTB_r_p_z:
13176       active_offset = 0;
13177       break;
13178     default:
13179       VIXL_UNIMPLEMENTED();
13180       break;
13181   }
13182 
13183   if (active_offset >= 0) {
13184     std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13185     WriteXRegister(instr->GetRd(), value.second);
13186   }
13187 }
13188 
VisitSVECompressActiveElements(const Instruction * instr)13189 void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
13190   VectorFormat vform = instr->GetSVEVectorFormat();
13191   SimVRegister& zd = ReadVRegister(instr->GetRd());
13192   SimVRegister& zn = ReadVRegister(instr->GetRn());
13193   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13194 
13195   switch (instr->Mask(SVECompressActiveElementsMask)) {
13196     case COMPACT_z_p_z:
13197       compact(vform, zd, pg, zn);
13198       break;
13199     default:
13200       VIXL_UNIMPLEMENTED();
13201       break;
13202   }
13203 }
13204 
VisitSVECopyGeneralRegisterToVector_Predicated(const Instruction * instr)13205 void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
13206     const Instruction* instr) {
13207   VectorFormat vform = instr->GetSVEVectorFormat();
13208   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13209   SimVRegister z_result;
13210 
13211   switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
13212     case CPY_z_p_r:
13213       dup_immediate(vform,
13214                     z_result,
13215                     ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13216       mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
13217       break;
13218     default:
13219       VIXL_UNIMPLEMENTED();
13220       break;
13221   }
13222 }
13223 
VisitSVECopyIntImm_Predicated(const Instruction * instr)13224 void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
13225   VectorFormat vform = instr->GetSVEVectorFormat();
13226   SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
13227   SimVRegister& zd = ReadVRegister(instr->GetRd());
13228 
13229   SimVRegister result;
13230   switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
13231     case CPY_z_p_i: {
13232       // Use unsigned arithmetic to avoid undefined behaviour during the shift.
13233       uint64_t imm8 = instr->GetImmSVEIntWideSigned();
13234       dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
13235       break;
13236     }
13237     default:
13238       VIXL_UNIMPLEMENTED();
13239       break;
13240   }
13241 
13242   if (instr->ExtractBit(14) != 0) {
13243     mov_merging(vform, zd, pg, result);
13244   } else {
13245     mov_zeroing(vform, zd, pg, result);
13246   }
13247 }
13248 
VisitSVEReverseWithinElements(const Instruction * instr)13249 void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
13250   SimVRegister& zd = ReadVRegister(instr->GetRd());
13251   SimVRegister& zn = ReadVRegister(instr->GetRn());
13252   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13253   SimVRegister result;
13254 
13255   // In NEON, the chunk size in which elements are REVersed is in the
13256   // instruction mnemonic, and the element size attached to the register.
13257   // SVE reverses the semantics; the mapping to logic functions below is to
13258   // account for this.
13259   VectorFormat chunk_form = instr->GetSVEVectorFormat();
13260   VectorFormat element_form = kFormatUndefined;
13261 
13262   switch (instr->Mask(SVEReverseWithinElementsMask)) {
13263     case RBIT_z_p_z:
13264       rbit(chunk_form, result, zn);
13265       break;
13266     case REVB_z_z:
13267       VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
13268                   (chunk_form == kFormatVnD));
13269       element_form = kFormatVnB;
13270       break;
13271     case REVH_z_z:
13272       VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
13273       element_form = kFormatVnH;
13274       break;
13275     case REVW_z_z:
13276       VIXL_ASSERT(chunk_form == kFormatVnD);
13277       element_form = kFormatVnS;
13278       break;
13279     default:
13280       VIXL_UNIMPLEMENTED();
13281       break;
13282   }
13283 
13284   if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
13285     VIXL_ASSERT(element_form != kFormatUndefined);
13286     switch (chunk_form) {
13287       case kFormatVnH:
13288         rev16(element_form, result, zn);
13289         break;
13290       case kFormatVnS:
13291         rev32(element_form, result, zn);
13292         break;
13293       case kFormatVnD:
13294         rev64(element_form, result, zn);
13295         break;
13296       default:
13297         VIXL_UNIMPLEMENTED();
13298     }
13299   }
13300 
13301   mov_merging(chunk_form, zd, pg, result);
13302 }
13303 
VisitSVEVectorSplice(const Instruction * instr)13304 void Simulator::VisitSVEVectorSplice(const Instruction* instr) {
13305   VectorFormat vform = instr->GetSVEVectorFormat();
13306   SimVRegister& zd = ReadVRegister(instr->GetRd());
13307   SimVRegister& zn = ReadVRegister(instr->GetRn());
13308   SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
13309   SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13310 
13311   switch (form_hash_) {
13312     case "splice_z_p_zz_des"_h:
13313       splice(vform, zd, pg, zd, zn);
13314       break;
13315     case "splice_z_p_zz_con"_h:
13316       splice(vform, zd, pg, zn, zn2);
13317       break;
13318     default:
13319       VIXL_UNIMPLEMENTED();
13320       break;
13321   }
13322 }
13323 
VisitSVEBroadcastGeneralRegister(const Instruction * instr)13324 void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
13325   SimVRegister& zd = ReadVRegister(instr->GetRd());
13326   switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
13327     case DUP_z_r:
13328       dup_immediate(instr->GetSVEVectorFormat(),
13329                     zd,
13330                     ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13331       break;
13332     default:
13333       VIXL_UNIMPLEMENTED();
13334       break;
13335   }
13336 }
13337 
VisitSVEInsertSIMDFPScalarRegister(const Instruction * instr)13338 void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
13339   SimVRegister& zd = ReadVRegister(instr->GetRd());
13340   VectorFormat vform = instr->GetSVEVectorFormat();
13341   switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
13342     case INSR_z_v:
13343       insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
13344       break;
13345     default:
13346       VIXL_UNIMPLEMENTED();
13347       break;
13348   }
13349 }
13350 
VisitSVEInsertGeneralRegister(const Instruction * instr)13351 void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
13352   SimVRegister& zd = ReadVRegister(instr->GetRd());
13353   VectorFormat vform = instr->GetSVEVectorFormat();
13354   switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
13355     case INSR_z_r:
13356       insr(vform, zd, ReadXRegister(instr->GetRn()));
13357       break;
13358     default:
13359       VIXL_UNIMPLEMENTED();
13360       break;
13361   }
13362 }
13363 
VisitSVEBroadcastIndexElement(const Instruction * instr)13364 void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
13365   SimVRegister& zd = ReadVRegister(instr->GetRd());
13366   switch (instr->Mask(SVEBroadcastIndexElementMask)) {
13367     case DUP_z_zi: {
13368       std::pair<int, int> index_and_lane_size =
13369           instr->GetSVEPermuteIndexAndLaneSizeLog2();
13370       int index = index_and_lane_size.first;
13371       int lane_size_in_bytes_log_2 = index_and_lane_size.second;
13372       VectorFormat vform =
13373           SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
13374       if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
13375         // Out of bounds, set the destination register to zero.
13376         dup_immediate(kFormatVnD, zd, 0);
13377       } else {
13378         dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
13379       }
13380       return;
13381     }
13382     default:
13383       VIXL_UNIMPLEMENTED();
13384       break;
13385   }
13386 }
13387 
VisitSVEReverseVectorElements(const Instruction * instr)13388 void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
13389   SimVRegister& zd = ReadVRegister(instr->GetRd());
13390   VectorFormat vform = instr->GetSVEVectorFormat();
13391   switch (instr->Mask(SVEReverseVectorElementsMask)) {
13392     case REV_z_z:
13393       rev(vform, zd, ReadVRegister(instr->GetRn()));
13394       break;
13395     default:
13396       VIXL_UNIMPLEMENTED();
13397       break;
13398   }
13399 }
13400 
VisitSVEUnpackVectorElements(const Instruction * instr)13401 void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
13402   SimVRegister& zd = ReadVRegister(instr->GetRd());
13403   VectorFormat vform = instr->GetSVEVectorFormat();
13404   switch (instr->Mask(SVEUnpackVectorElementsMask)) {
13405     case SUNPKHI_z_z:
13406       unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
13407       break;
13408     case SUNPKLO_z_z:
13409       unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
13410       break;
13411     case UUNPKHI_z_z:
13412       unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
13413       break;
13414     case UUNPKLO_z_z:
13415       unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
13416       break;
13417     default:
13418       VIXL_UNIMPLEMENTED();
13419       break;
13420   }
13421 }
13422 
VisitSVETableLookup(const Instruction * instr)13423 void Simulator::VisitSVETableLookup(const Instruction* instr) {
13424   VectorFormat vform = instr->GetSVEVectorFormat();
13425   SimVRegister& zd = ReadVRegister(instr->GetRd());
13426   SimVRegister& zn = ReadVRegister(instr->GetRn());
13427   SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
13428   SimVRegister& zm = ReadVRegister(instr->GetRm());
13429 
13430   switch (form_hash_) {
13431     case "tbl_z_zz_1"_h:
13432       tbl(vform, zd, zn, zm);
13433       break;
13434     case "tbl_z_zz_2"_h:
13435       tbl(vform, zd, zn, zn2, zm);
13436       break;
13437     case "tbx_z_zz"_h:
13438       tbx(vform, zd, zn, zm);
13439       break;
13440     default:
13441       VIXL_UNIMPLEMENTED();
13442       break;
13443   }
13444 }
13445 
VisitSVEPredicateCount(const Instruction * instr)13446 void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
13447   VectorFormat vform = instr->GetSVEVectorFormat();
13448   SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13449   SimPRegister& pn = ReadPRegister(instr->GetPn());
13450 
13451   switch (instr->Mask(SVEPredicateCountMask)) {
13452     case CNTP_r_p_p: {
13453       WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
13454       break;
13455     }
13456     default:
13457       VIXL_UNIMPLEMENTED();
13458       break;
13459   }
13460 }
13461 
VisitSVEPredicateLogical(const Instruction * instr)13462 void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
13463   Instr op = instr->Mask(SVEPredicateLogicalMask);
13464   SimPRegister& pd = ReadPRegister(instr->GetPd());
13465   SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13466   SimPRegister& pn = ReadPRegister(instr->GetPn());
13467   SimPRegister& pm = ReadPRegister(instr->GetPm());
13468   SimPRegister result;
13469   switch (op) {
13470     case ANDS_p_p_pp_z:
13471     case AND_p_p_pp_z:
13472     case BICS_p_p_pp_z:
13473     case BIC_p_p_pp_z:
13474     case EORS_p_p_pp_z:
13475     case EOR_p_p_pp_z:
13476     case NANDS_p_p_pp_z:
13477     case NAND_p_p_pp_z:
13478     case NORS_p_p_pp_z:
13479     case NOR_p_p_pp_z:
13480     case ORNS_p_p_pp_z:
13481     case ORN_p_p_pp_z:
13482     case ORRS_p_p_pp_z:
13483     case ORR_p_p_pp_z:
13484       SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
13485                                 result,
13486                                 pn,
13487                                 pm);
13488       break;
13489     case SEL_p_p_pp:
13490       sel(pd, pg, pn, pm);
13491       return;
13492     default:
13493       VIXL_UNIMPLEMENTED();
13494       break;
13495   }
13496 
13497   mov_zeroing(pd, pg, result);
13498   if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
13499     PredTest(kFormatVnB, pg, pd);
13500   }
13501 }
13502 
VisitSVEPredicateFirstActive(const Instruction * instr)13503 void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
13504   LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13505   LogicPRegister pdn = ReadPRegister(instr->GetPd());
13506   switch (instr->Mask(SVEPredicateFirstActiveMask)) {
13507     case PFIRST_p_p_p:
13508       pfirst(pdn, pg, pdn);
13509       // TODO: Is this broken when pg == pdn?
13510       PredTest(kFormatVnB, pg, pdn);
13511       break;
13512     default:
13513       VIXL_UNIMPLEMENTED();
13514       break;
13515   }
13516 }
13517 
VisitSVEPredicateInitialize(const Instruction * instr)13518 void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
13519   // This group only contains PTRUE{S}, and there are no unallocated encodings.
13520   VIXL_STATIC_ASSERT(
13521       SVEPredicateInitializeMask ==
13522       (SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
13523   VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
13524               (instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
13525 
13526   LogicPRegister pdn = ReadPRegister(instr->GetPd());
13527   VectorFormat vform = instr->GetSVEVectorFormat();
13528 
13529   ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
13530   if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
13531 }
13532 
VisitSVEPredicateNextActive(const Instruction * instr)13533 void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
13534   // This group only contains PNEXT, and there are no unallocated encodings.
13535   VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
13536   VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
13537 
13538   LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13539   LogicPRegister pdn = ReadPRegister(instr->GetPd());
13540   VectorFormat vform = instr->GetSVEVectorFormat();
13541 
13542   pnext(vform, pdn, pg, pdn);
13543   // TODO: Is this broken when pg == pdn?
13544   PredTest(vform, pg, pdn);
13545 }
13546 
VisitSVEPredicateReadFromFFR_Predicated(const Instruction * instr)13547 void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
13548     const Instruction* instr) {
13549   LogicPRegister pd(ReadPRegister(instr->GetPd()));
13550   LogicPRegister pg(ReadPRegister(instr->GetPn()));
13551   FlagsUpdate flags = LeaveFlags;
13552   switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
13553     case RDFFR_p_p_f:
13554       // Do nothing.
13555       break;
13556     case RDFFRS_p_p_f:
13557       flags = SetFlags;
13558       break;
13559     default:
13560       VIXL_UNIMPLEMENTED();
13561       break;
13562   }
13563 
13564   LogicPRegister ffr(ReadFFR());
13565   mov_zeroing(pd, pg, ffr);
13566 
13567   if (flags == SetFlags) {
13568     PredTest(kFormatVnB, pg, pd);
13569   }
13570 }
13571 
VisitSVEPredicateReadFromFFR_Unpredicated(const Instruction * instr)13572 void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
13573     const Instruction* instr) {
13574   LogicPRegister pd(ReadPRegister(instr->GetPd()));
13575   LogicPRegister ffr(ReadFFR());
13576   switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
13577     case RDFFR_p_f:
13578       mov(pd, ffr);
13579       break;
13580     default:
13581       VIXL_UNIMPLEMENTED();
13582       break;
13583   }
13584 }
13585 
VisitSVEPredicateTest(const Instruction * instr)13586 void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
13587   switch (instr->Mask(SVEPredicateTestMask)) {
13588     case PTEST_p_p:
13589       PredTest(kFormatVnB,
13590                ReadPRegister(instr->ExtractBits(13, 10)),
13591                ReadPRegister(instr->GetPn()));
13592       break;
13593     default:
13594       VIXL_UNIMPLEMENTED();
13595       break;
13596   }
13597 }
13598 
VisitSVEPredicateZero(const Instruction * instr)13599 void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
13600   switch (instr->Mask(SVEPredicateZeroMask)) {
13601     case PFALSE_p:
13602       pfalse(ReadPRegister(instr->GetPd()));
13603       break;
13604     default:
13605       VIXL_UNIMPLEMENTED();
13606       break;
13607   }
13608 }
13609 
VisitSVEPropagateBreak(const Instruction * instr)13610 void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
13611   SimPRegister& pd = ReadPRegister(instr->GetPd());
13612   SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13613   SimPRegister& pn = ReadPRegister(instr->GetPn());
13614   SimPRegister& pm = ReadPRegister(instr->GetPm());
13615 
13616   bool set_flags = false;
13617   switch (instr->Mask(SVEPropagateBreakMask)) {
13618     case BRKPAS_p_p_pp:
13619       set_flags = true;
13620       VIXL_FALLTHROUGH();
13621     case BRKPA_p_p_pp:
13622       brkpa(pd, pg, pn, pm);
13623       break;
13624     case BRKPBS_p_p_pp:
13625       set_flags = true;
13626       VIXL_FALLTHROUGH();
13627     case BRKPB_p_p_pp:
13628       brkpb(pd, pg, pn, pm);
13629       break;
13630     default:
13631       VIXL_UNIMPLEMENTED();
13632       break;
13633   }
13634 
13635   if (set_flags) {
13636     PredTest(kFormatVnB, pg, pd);
13637   }
13638 }
13639 
VisitSVEStackFrameAdjustment(const Instruction * instr)13640 void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
13641   uint64_t length = 0;
13642   switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
13643     case ADDPL_r_ri:
13644       length = GetPredicateLengthInBytes();
13645       break;
13646     case ADDVL_r_ri:
13647       length = GetVectorLengthInBytes();
13648       break;
13649     default:
13650       VIXL_UNIMPLEMENTED();
13651   }
13652   uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
13653   WriteXRegister(instr->GetRd(),
13654                  base + (length * instr->GetImmSVEVLScale()),
13655                  LogRegWrites,
13656                  Reg31IsStackPointer);
13657 }
13658 
VisitSVEStackFrameSize(const Instruction * instr)13659 void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
13660   int64_t scale = instr->GetImmSVEVLScale();
13661 
13662   switch (instr->Mask(SVEStackFrameSizeMask)) {
13663     case RDVL_r_i:
13664       WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
13665       break;
13666     default:
13667       VIXL_UNIMPLEMENTED();
13668   }
13669 }
13670 
VisitSVEVectorSelect(const Instruction * instr)13671 void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
13672   // The only instruction in this group is `sel`, and there are no unused
13673   // encodings.
13674   VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
13675 
13676   VectorFormat vform = instr->GetSVEVectorFormat();
13677   SimVRegister& zd = ReadVRegister(instr->GetRd());
13678   SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13679   SimVRegister& zn = ReadVRegister(instr->GetRn());
13680   SimVRegister& zm = ReadVRegister(instr->GetRm());
13681 
13682   sel(vform, zd, pg, zn, zm);
13683 }
13684 
VisitSVEFFRInitialise(const Instruction * instr)13685 void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
13686   switch (instr->Mask(SVEFFRInitialiseMask)) {
13687     case SETFFR_f: {
13688       LogicPRegister ffr(ReadFFR());
13689       ffr.SetAllBits();
13690       break;
13691     }
13692     default:
13693       VIXL_UNIMPLEMENTED();
13694       break;
13695   }
13696 }
13697 
VisitSVEFFRWriteFromPredicate(const Instruction * instr)13698 void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
13699   switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
13700     case WRFFR_f_p: {
13701       SimPRegister pn(ReadPRegister(instr->GetPn()));
13702       bool last_active = true;
13703       for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
13704         bool active = pn.GetBit(i);
13705         if (active && !last_active) {
13706           // `pn` is non-monotonic. This is UNPREDICTABLE.
13707           VIXL_ABORT();
13708         }
13709         last_active = active;
13710       }
13711       mov(ReadFFR(), pn);
13712       break;
13713     }
13714     default:
13715       VIXL_UNIMPLEMENTED();
13716       break;
13717   }
13718 }
13719 
VisitSVEContiguousLoad_ScalarPlusImm(const Instruction * instr)13720 void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
13721   bool is_signed;
13722   switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
13723     case LD1B_z_p_bi_u8:
13724     case LD1B_z_p_bi_u16:
13725     case LD1B_z_p_bi_u32:
13726     case LD1B_z_p_bi_u64:
13727     case LD1H_z_p_bi_u16:
13728     case LD1H_z_p_bi_u32:
13729     case LD1H_z_p_bi_u64:
13730     case LD1W_z_p_bi_u32:
13731     case LD1W_z_p_bi_u64:
13732     case LD1D_z_p_bi_u64:
13733       is_signed = false;
13734       break;
13735     case LD1SB_z_p_bi_s16:
13736     case LD1SB_z_p_bi_s32:
13737     case LD1SB_z_p_bi_s64:
13738     case LD1SH_z_p_bi_s32:
13739     case LD1SH_z_p_bi_s64:
13740     case LD1SW_z_p_bi_s64:
13741       is_signed = true;
13742       break;
13743     default:
13744       // This encoding group is complete, so no other values should be possible.
13745       VIXL_UNREACHABLE();
13746       is_signed = false;
13747       break;
13748   }
13749 
13750   int vl = GetVectorLengthInBytes();
13751   int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13752   int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
13753   VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
13754   int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
13755   uint64_t offset =
13756       (instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
13757   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
13758   LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
13759   addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13760   SVEStructuredLoadHelper(vform,
13761                           ReadPRegister(instr->GetPgLow8()),
13762                           instr->GetRt(),
13763                           addr,
13764                           is_signed);
13765 }
13766 
VisitSVEContiguousLoad_ScalarPlusScalar(const Instruction * instr)13767 void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
13768     const Instruction* instr) {
13769   bool is_signed;
13770   switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
13771     case LD1B_z_p_br_u8:
13772     case LD1B_z_p_br_u16:
13773     case LD1B_z_p_br_u32:
13774     case LD1B_z_p_br_u64:
13775     case LD1H_z_p_br_u16:
13776     case LD1H_z_p_br_u32:
13777     case LD1H_z_p_br_u64:
13778     case LD1W_z_p_br_u32:
13779     case LD1W_z_p_br_u64:
13780     case LD1D_z_p_br_u64:
13781       is_signed = false;
13782       break;
13783     case LD1SB_z_p_br_s16:
13784     case LD1SB_z_p_br_s32:
13785     case LD1SB_z_p_br_s64:
13786     case LD1SH_z_p_br_s32:
13787     case LD1SH_z_p_br_s64:
13788     case LD1SW_z_p_br_s64:
13789       is_signed = true;
13790       break;
13791     default:
13792       // This encoding group is complete, so no other values should be possible.
13793       VIXL_UNREACHABLE();
13794       is_signed = false;
13795       break;
13796   }
13797 
13798   int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
13799   int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
13800   VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
13801   VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
13802   uint64_t offset = ReadXRegister(instr->GetRm());
13803   offset <<= msize_in_bytes_log2;
13804   LogicSVEAddressVector addr(ReadXRegister(instr->GetRn()) + offset);
13805   addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13806   SVEStructuredLoadHelper(vform,
13807                           ReadPRegister(instr->GetPgLow8()),
13808                           instr->GetRt(),
13809                           addr,
13810                           is_signed);
13811 }
13812 
DoUnreachable(const Instruction * instr)13813 void Simulator::DoUnreachable(const Instruction* instr) {
13814   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13815               (instr->GetImmException() == kUnreachableOpcode));
13816 
13817   fprintf(stream_,
13818           "Hit UNREACHABLE marker at pc=%p.\n",
13819           reinterpret_cast<const void*>(instr));
13820   abort();
13821 }
13822 
13823 
DoTrace(const Instruction * instr)13824 void Simulator::DoTrace(const Instruction* instr) {
13825   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13826               (instr->GetImmException() == kTraceOpcode));
13827 
13828   // Read the arguments encoded inline in the instruction stream.
13829   uint32_t parameters;
13830   uint32_t command;
13831 
13832   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13833   memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13834   memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
13835 
13836   switch (command) {
13837     case TRACE_ENABLE:
13838       SetTraceParameters(GetTraceParameters() | parameters);
13839       break;
13840     case TRACE_DISABLE:
13841       SetTraceParameters(GetTraceParameters() & ~parameters);
13842       break;
13843     default:
13844       VIXL_UNREACHABLE();
13845   }
13846 
13847   WritePc(instr->GetInstructionAtOffset(kTraceLength));
13848 }
13849 
13850 
DoLog(const Instruction * instr)13851 void Simulator::DoLog(const Instruction* instr) {
13852   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13853               (instr->GetImmException() == kLogOpcode));
13854 
13855   // Read the arguments encoded inline in the instruction stream.
13856   uint32_t parameters;
13857 
13858   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13859   memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
13860 
13861   // We don't support a one-shot LOG_DISASM.
13862   VIXL_ASSERT((parameters & LOG_DISASM) == 0);
13863   // Print the requested information.
13864   if (parameters & LOG_SYSREGS) PrintSystemRegisters();
13865   if (parameters & LOG_REGS) PrintRegisters();
13866   if (parameters & LOG_VREGS) PrintVRegisters();
13867 
13868   WritePc(instr->GetInstructionAtOffset(kLogLength));
13869 }
13870 
13871 
DoPrintf(const Instruction * instr)13872 void Simulator::DoPrintf(const Instruction* instr) {
13873   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
13874               (instr->GetImmException() == kPrintfOpcode));
13875 
13876   // Read the arguments encoded inline in the instruction stream.
13877   uint32_t arg_count;
13878   uint32_t arg_pattern_list;
13879   VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
13880   memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
13881   memcpy(&arg_pattern_list,
13882          instr + kPrintfArgPatternListOffset,
13883          sizeof(arg_pattern_list));
13884 
13885   VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
13886   VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
13887 
13888   // We need to call the host printf function with a set of arguments defined by
13889   // arg_pattern_list. Because we don't know the types and sizes of the
13890   // arguments, this is very difficult to do in a robust and portable way. To
13891   // work around the problem, we pick apart the format string, and print one
13892   // format placeholder at a time.
13893 
13894   // Allocate space for the format string. We take a copy, so we can modify it.
13895   // Leave enough space for one extra character per expected argument (plus the
13896   // '\0' termination).
13897   const char* format_base = ReadRegister<const char*>(0);
13898   VIXL_ASSERT(format_base != NULL);
13899   size_t length = strlen(format_base) + 1;
13900   char* const format = new char[length + arg_count];
13901 
13902   // A list of chunks, each with exactly one format placeholder.
13903   const char* chunks[kPrintfMaxArgCount];
13904 
13905   // Copy the format string and search for format placeholders.
13906   uint32_t placeholder_count = 0;
13907   char* format_scratch = format;
13908   for (size_t i = 0; i < length; i++) {
13909     if (format_base[i] != '%') {
13910       *format_scratch++ = format_base[i];
13911     } else {
13912       if (format_base[i + 1] == '%') {
13913         // Ignore explicit "%%" sequences.
13914         *format_scratch++ = format_base[i];
13915         i++;
13916         // Chunks after the first are passed as format strings to printf, so we
13917         // need to escape '%' characters in those chunks.
13918         if (placeholder_count > 0) *format_scratch++ = format_base[i];
13919       } else {
13920         VIXL_CHECK(placeholder_count < arg_count);
13921         // Insert '\0' before placeholders, and store their locations.
13922         *format_scratch++ = '\0';
13923         chunks[placeholder_count++] = format_scratch;
13924         *format_scratch++ = format_base[i];
13925       }
13926     }
13927   }
13928   VIXL_CHECK(placeholder_count == arg_count);
13929 
13930   // Finally, call printf with each chunk, passing the appropriate register
13931   // argument. Normally, printf returns the number of bytes transmitted, so we
13932   // can emulate a single printf call by adding the result from each chunk. If
13933   // any call returns a negative (error) value, though, just return that value.
13934 
13935   printf("%s", clr_printf);
13936 
13937   // Because '\0' is inserted before each placeholder, the first string in
13938   // 'format' contains no format placeholders and should be printed literally.
13939   int result = printf("%s", format);
13940   int pcs_r = 1;  // Start at x1. x0 holds the format string.
13941   int pcs_f = 0;  // Start at d0.
13942   if (result >= 0) {
13943     for (uint32_t i = 0; i < placeholder_count; i++) {
13944       int part_result = -1;
13945 
13946       uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
13947       arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
13948       switch (arg_pattern) {
13949         case kPrintfArgW:
13950           part_result = printf(chunks[i], ReadWRegister(pcs_r++));
13951           break;
13952         case kPrintfArgX:
13953           part_result = printf(chunks[i], ReadXRegister(pcs_r++));
13954           break;
13955         case kPrintfArgD:
13956           part_result = printf(chunks[i], ReadDRegister(pcs_f++));
13957           break;
13958         default:
13959           VIXL_UNREACHABLE();
13960       }
13961 
13962       if (part_result < 0) {
13963         // Handle error values.
13964         result = part_result;
13965         break;
13966       }
13967 
13968       result += part_result;
13969     }
13970   }
13971 
13972   printf("%s", clr_normal);
13973 
13974   // Printf returns its result in x0 (just like the C library's printf).
13975   WriteXRegister(0, result);
13976 
13977   // The printf parameters are inlined in the code, so skip them.
13978   WritePc(instr->GetInstructionAtOffset(kPrintfLength));
13979 
13980   // Set LR as if we'd just called a native printf function.
13981   WriteLr(ReadPc());
13982 
13983   delete[] format;
13984 }
13985 
13986 
13987 #ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
DoRuntimeCall(const Instruction * instr)13988 void Simulator::DoRuntimeCall(const Instruction* instr) {
13989   VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
13990   // The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
13991   // to call are passed inlined in the assembly.
13992   uintptr_t call_wrapper_address =
13993       MemRead<uintptr_t>(instr + kRuntimeCallWrapperOffset);
13994   uintptr_t function_address =
13995       MemRead<uintptr_t>(instr + kRuntimeCallFunctionOffset);
13996   RuntimeCallType call_type = static_cast<RuntimeCallType>(
13997       MemRead<uint32_t>(instr + kRuntimeCallTypeOffset));
13998   auto runtime_call_wrapper =
13999       reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
14000 
14001   if (call_type == kCallRuntime) {
14002     WriteRegister(kLinkRegCode,
14003                   instr->GetInstructionAtOffset(kRuntimeCallLength));
14004   }
14005   runtime_call_wrapper(this, function_address);
14006   // Read the return address from `lr` and write it into `pc`.
14007   WritePc(ReadRegister<Instruction*>(kLinkRegCode));
14008 }
14009 #else
DoRuntimeCall(const Instruction * instr)14010 void Simulator::DoRuntimeCall(const Instruction* instr) {
14011   USE(instr);
14012   VIXL_UNREACHABLE();
14013 }
14014 #endif
14015 
14016 
DoConfigureCPUFeatures(const Instruction * instr)14017 void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
14018   VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
14019 
14020   typedef ConfigureCPUFeaturesElementType ElementType;
14021   VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
14022               std::numeric_limits<ElementType>::max());
14023 
14024   // k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
14025 
14026   size_t element_size = sizeof(ElementType);
14027   size_t offset = kConfigureCPUFeaturesListOffset;
14028 
14029   // Read the kNone-terminated list of features.
14030   CPUFeatures parameters;
14031   while (true) {
14032     ElementType feature = MemRead<ElementType>(instr + offset);
14033     offset += element_size;
14034     if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
14035     parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
14036   }
14037 
14038   switch (instr->GetImmException()) {
14039     case kSetCPUFeaturesOpcode:
14040       SetCPUFeatures(parameters);
14041       break;
14042     case kEnableCPUFeaturesOpcode:
14043       GetCPUFeatures()->Combine(parameters);
14044       break;
14045     case kDisableCPUFeaturesOpcode:
14046       GetCPUFeatures()->Remove(parameters);
14047       break;
14048     default:
14049       VIXL_UNREACHABLE();
14050       break;
14051   }
14052 
14053   WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
14054 }
14055 
14056 
DoSaveCPUFeatures(const Instruction * instr)14057 void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
14058   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14059               (instr->GetImmException() == kSaveCPUFeaturesOpcode));
14060   USE(instr);
14061 
14062   saved_cpu_features_.push_back(*GetCPUFeatures());
14063 }
14064 
14065 
DoRestoreCPUFeatures(const Instruction * instr)14066 void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
14067   VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14068               (instr->GetImmException() == kRestoreCPUFeaturesOpcode));
14069   USE(instr);
14070 
14071   SetCPUFeatures(saved_cpu_features_.back());
14072   saved_cpu_features_.pop_back();
14073 }
14074 
14075 
14076 }  // namespace aarch64
14077 }  // namespace vixl
14078 
14079 #endif  // VIXL_INCLUDE_SIMULATOR_AARCH64
14080