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 = ®isters_[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(¶meters, 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(¶meters, 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