Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/dep/vixl/src/aarch64/simulator-aarch64.cc
4261 views
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 "simulator-aarch64.h"
30
31
#include <cmath>
32
#include <cstring>
33
#include <errno.h>
34
#include <limits>
35
#include <sys/mman.h>
36
#include <unistd.h>
37
38
namespace vixl {
39
namespace aarch64 {
40
41
using vixl::internal::SimFloat16;
42
43
const Instruction* Simulator::kEndOfSimAddress = NULL;
44
45
MemoryAccessResult TryMemoryAccess(uintptr_t address, uintptr_t access_size) {
46
#ifdef VIXL_ENABLE_IMPLICIT_CHECKS
47
for (uintptr_t i = 0; i < access_size; i++) {
48
if (_vixl_internal_ReadMemory(address, i) == MemoryAccessResult::Failure) {
49
// The memory access failed.
50
return MemoryAccessResult::Failure;
51
}
52
}
53
54
// Either the memory access did not raise a signal or the signal handler did
55
// not correctly return MemoryAccessResult::Failure.
56
return MemoryAccessResult::Success;
57
#else
58
USE(address);
59
USE(access_size);
60
return MemoryAccessResult::Success;
61
#endif // VIXL_ENABLE_IMPLICIT_CHECKS
62
}
63
64
bool MetaDataDepot::MetaDataMTE::is_active = false;
65
66
void SimSystemRegister::SetBits(int msb, int lsb, uint32_t bits) {
67
int width = msb - lsb + 1;
68
VIXL_ASSERT(IsUintN(width, bits) || IsIntN(width, bits));
69
70
bits <<= lsb;
71
uint32_t mask = ((1 << width) - 1) << lsb;
72
VIXL_ASSERT((mask & write_ignore_mask_) == 0);
73
74
value_ = (value_ & ~mask) | (bits & mask);
75
}
76
77
78
SimSystemRegister SimSystemRegister::DefaultValueFor(SystemRegister id) {
79
switch (id) {
80
case NZCV:
81
return SimSystemRegister(0x00000000, NZCVWriteIgnoreMask);
82
case FPCR:
83
return SimSystemRegister(0x00000000, FPCRWriteIgnoreMask);
84
default:
85
VIXL_UNREACHABLE();
86
return SimSystemRegister();
87
}
88
}
89
90
const Simulator::FormToVisitorFnMap* Simulator::GetFormToVisitorFnMap() {
91
static const FormToVisitorFnMap form_to_visitor = {
92
DEFAULT_FORM_TO_VISITOR_MAP(Simulator),
93
SIM_AUD_VISITOR_MAP(Simulator),
94
{"smlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
95
{"smlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
96
{"smull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
97
{"sqdmlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
98
{"sqdmlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
99
{"sqdmull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
100
{"umlal_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
101
{"umlsl_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
102
{"umull_asimdelem_l"_h, &Simulator::SimulateNEONMulByElementLong},
103
{"fcmla_asimdelem_c_h"_h, &Simulator::SimulateNEONComplexMulByElement},
104
{"fcmla_asimdelem_c_s"_h, &Simulator::SimulateNEONComplexMulByElement},
105
{"fmlal2_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},
106
{"fmlal_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},
107
{"fmlsl2_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},
108
{"fmlsl_asimdelem_lh"_h, &Simulator::SimulateNEONFPMulByElementLong},
109
{"fmla_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},
110
{"fmls_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},
111
{"fmulx_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},
112
{"fmul_asimdelem_rh_h"_h, &Simulator::SimulateNEONFPMulByElement},
113
{"fmla_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},
114
{"fmls_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},
115
{"fmulx_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},
116
{"fmul_asimdelem_r_sd"_h, &Simulator::SimulateNEONFPMulByElement},
117
{"sdot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},
118
{"udot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},
119
{"adclb_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},
120
{"adclt_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},
121
{"addhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
122
{"addhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
123
{"addp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
124
{"bcax_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
125
{"bdep_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
126
{"bext_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
127
{"bgrp_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
128
{"bsl1n_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
129
{"bsl2n_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
130
{"bsl_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
131
{"cadd_z_zz"_h, &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},
132
{"cdot_z_zzz"_h, &Simulator::SimulateSVEComplexDotProduct},
133
{"cdot_z_zzzi_d"_h, &Simulator::SimulateSVEComplexDotProduct},
134
{"cdot_z_zzzi_s"_h, &Simulator::SimulateSVEComplexDotProduct},
135
{"cmla_z_zzz"_h, &Simulator::SimulateSVEComplexIntMulAdd},
136
{"cmla_z_zzzi_h"_h, &Simulator::SimulateSVEComplexIntMulAdd},
137
{"cmla_z_zzzi_s"_h, &Simulator::SimulateSVEComplexIntMulAdd},
138
{"eor3_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
139
{"eorbt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
140
{"eortb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
141
{"ext_z_zi_con"_h, &Simulator::Simulate_ZdB_Zn1B_Zn2B_imm},
142
{"faddp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
143
{"fcvtlt_z_p_z_h2s"_h, &Simulator::SimulateSVEFPConvertLong},
144
{"fcvtlt_z_p_z_s2d"_h, &Simulator::SimulateSVEFPConvertLong},
145
{"fcvtnt_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD},
146
{"fcvtnt_z_p_z_s2h"_h, &Simulator::Simulate_ZdH_PgM_ZnS},
147
{"fcvtx_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD},
148
{"fcvtxnt_z_p_z_d2s"_h, &Simulator::Simulate_ZdS_PgM_ZnD},
149
{"flogb_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT},
150
{"fmaxnmp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
151
{"fmaxp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
152
{"fminnmp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
153
{"fminp_z_p_zz"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT},
154
{"fmlalb_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},
155
{"fmlalb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
156
{"fmlalt_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},
157
{"fmlalt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
158
{"fmlslb_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},
159
{"fmlslb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
160
{"fmlslt_z_zzz"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH},
161
{"fmlslt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
162
{"histcnt_z_p_zz"_h, &Simulator::Simulate_ZdT_PgZ_ZnT_ZmT},
163
{"histseg_z_zz"_h, &Simulator::Simulate_ZdB_ZnB_ZmB},
164
{"ldnt1b_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
165
{"ldnt1b_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
166
{"ldnt1d_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
167
{"ldnt1h_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
168
{"ldnt1h_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
169
{"ldnt1sb_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
170
{"ldnt1sb_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
171
{"ldnt1sh_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
172
{"ldnt1sh_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
173
{"ldnt1sw_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
174
{"ldnt1w_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_PgZ_ZnD_Xm},
175
{"ldnt1w_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_PgZ_ZnS_Xm},
176
{"match_p_p_zz"_h, &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},
177
{"mla_z_zzzi_d"_h, &Simulator::SimulateSVEMlaMlsIndex},
178
{"mla_z_zzzi_h"_h, &Simulator::SimulateSVEMlaMlsIndex},
179
{"mla_z_zzzi_s"_h, &Simulator::SimulateSVEMlaMlsIndex},
180
{"mls_z_zzzi_d"_h, &Simulator::SimulateSVEMlaMlsIndex},
181
{"mls_z_zzzi_h"_h, &Simulator::SimulateSVEMlaMlsIndex},
182
{"mls_z_zzzi_s"_h, &Simulator::SimulateSVEMlaMlsIndex},
183
{"mul_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
184
{"mul_z_zzi_d"_h, &Simulator::SimulateSVEMulIndex},
185
{"mul_z_zzi_h"_h, &Simulator::SimulateSVEMulIndex},
186
{"mul_z_zzi_s"_h, &Simulator::SimulateSVEMulIndex},
187
{"nbsl_z_zzz"_h, &Simulator::SimulateSVEBitwiseTernary},
188
{"nmatch_p_p_zz"_h, &Simulator::Simulate_PdT_PgZ_ZnT_ZmT},
189
{"pmul_z_zz"_h, &Simulator::Simulate_ZdB_ZnB_ZmB},
190
{"pmullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
191
{"pmullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
192
{"raddhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
193
{"raddhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
194
{"rshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
195
{"rshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
196
{"rsubhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
197
{"rsubhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
198
{"saba_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnT_ZmT},
199
{"sabalb_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},
200
{"sabalt_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},
201
{"sabdlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
202
{"sabdlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
203
{"sadalp_z_p_z"_h, &Simulator::Simulate_ZdaT_PgM_ZnTb},
204
{"saddlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
205
{"saddlbt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
206
{"saddlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
207
{"saddwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
208
{"saddwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
209
{"sbclb_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},
210
{"sbclt_z_zzz"_h, &Simulator::SimulateSVEAddSubCarry},
211
{"shadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
212
{"shrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
213
{"shrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
214
{"shsub_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
215
{"shsubr_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
216
{"sli_z_zzi"_h, &Simulator::Simulate_ZdT_ZnT_const},
217
{"smaxp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
218
{"sminp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
219
{"smlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
220
{"smlalb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
221
{"smlalb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
222
{"smlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
223
{"smlalt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
224
{"smlalt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
225
{"smlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
226
{"smlslb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
227
{"smlslb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
228
{"smlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
229
{"smlslt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
230
{"smlslt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
231
{"smulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
232
{"smullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
233
{"smullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
234
{"smullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
235
{"smullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
236
{"smullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
237
{"smullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
238
{"splice_z_p_zz_con"_h, &Simulator::VisitSVEVectorSplice},
239
{"sqabs_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT},
240
{"sqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
241
{"sqcadd_z_zz"_h, &Simulator::Simulate_ZdnT_ZdnT_ZmT_const},
242
{"sqdmlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
243
{"sqdmlalb_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
244
{"sqdmlalb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
245
{"sqdmlalbt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
246
{"sqdmlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
247
{"sqdmlalt_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
248
{"sqdmlalt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
249
{"sqdmlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
250
{"sqdmlslb_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
251
{"sqdmlslb_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
252
{"sqdmlslbt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
253
{"sqdmlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
254
{"sqdmlslt_z_zzzi_d"_h, &Simulator::Simulate_ZdaD_ZnS_ZmS_imm},
255
{"sqdmlslt_z_zzzi_s"_h, &Simulator::Simulate_ZdaS_ZnH_ZmH_imm},
256
{"sqdmulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
257
{"sqdmulh_z_zzi_d"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
258
{"sqdmulh_z_zzi_h"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
259
{"sqdmulh_z_zzi_s"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
260
{"sqdmullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
261
{"sqdmullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
262
{"sqdmullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
263
{"sqdmullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
264
{"sqdmullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
265
{"sqdmullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
266
{"sqneg_z_p_z"_h, &Simulator::Simulate_ZdT_PgM_ZnT},
267
{"sqrdcmlah_z_zzz"_h, &Simulator::SimulateSVEComplexIntMulAdd},
268
{"sqrdcmlah_z_zzzi_h"_h, &Simulator::SimulateSVEComplexIntMulAdd},
269
{"sqrdcmlah_z_zzzi_s"_h, &Simulator::SimulateSVEComplexIntMulAdd},
270
{"sqrdmlah_z_zzz"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
271
{"sqrdmlah_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
272
{"sqrdmlah_z_zzzi_h"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
273
{"sqrdmlah_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
274
{"sqrdmlsh_z_zzz"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
275
{"sqrdmlsh_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
276
{"sqrdmlsh_z_zzzi_h"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
277
{"sqrdmlsh_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingMulAddHigh},
278
{"sqrdmulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
279
{"sqrdmulh_z_zzi_d"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
280
{"sqrdmulh_z_zzi_h"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
281
{"sqrdmulh_z_zzi_s"_h, &Simulator::SimulateSVESaturatingMulHighIndex},
282
{"sqrshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
283
{"sqrshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
284
{"sqrshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
285
{"sqrshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
286
{"sqrshrunb_z_zi"_h, &Simulator::SimulateSVENarrow},
287
{"sqrshrunt_z_zi"_h, &Simulator::SimulateSVENarrow},
288
{"sqshl_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
289
{"sqshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
290
{"sqshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
291
{"sqshlu_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
292
{"sqshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
293
{"sqshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
294
{"sqshrunb_z_zi"_h, &Simulator::SimulateSVENarrow},
295
{"sqshrunt_z_zi"_h, &Simulator::SimulateSVENarrow},
296
{"sqsub_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
297
{"sqsubr_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
298
{"sqxtnb_z_zz"_h, &Simulator::SimulateSVENarrow},
299
{"sqxtnt_z_zz"_h, &Simulator::SimulateSVENarrow},
300
{"sqxtunb_z_zz"_h, &Simulator::SimulateSVENarrow},
301
{"sqxtunt_z_zz"_h, &Simulator::SimulateSVENarrow},
302
{"srhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
303
{"sri_z_zzi"_h, &Simulator::Simulate_ZdT_ZnT_const},
304
{"srshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
305
{"srshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
306
{"srshr_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
307
{"srsra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},
308
{"sshllb_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},
309
{"sshllt_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},
310
{"ssra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},
311
{"ssublb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
312
{"ssublbt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
313
{"ssublt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
314
{"ssubltb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
315
{"ssubwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
316
{"ssubwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
317
{"stnt1b_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
318
{"stnt1b_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
319
{"stnt1d_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
320
{"stnt1h_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
321
{"stnt1h_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
322
{"stnt1w_z_p_ar_d_64_unscaled"_h, &Simulator::Simulate_ZtD_Pg_ZnD_Xm},
323
{"stnt1w_z_p_ar_s_x32_unscaled"_h, &Simulator::Simulate_ZtS_Pg_ZnS_Xm},
324
{"subhnb_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
325
{"subhnt_z_zz"_h, &Simulator::SimulateSVEAddSubHigh},
326
{"suqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
327
{"tbl_z_zz_2"_h, &Simulator::VisitSVETableLookup},
328
{"tbx_z_zz"_h, &Simulator::VisitSVETableLookup},
329
{"uaba_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnT_ZmT},
330
{"uabalb_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},
331
{"uabalt_z_zzz"_h, &Simulator::SimulateSVEInterleavedArithLong},
332
{"uabdlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
333
{"uabdlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
334
{"uadalp_z_p_z"_h, &Simulator::Simulate_ZdaT_PgM_ZnTb},
335
{"uaddlb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
336
{"uaddlt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
337
{"uaddwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
338
{"uaddwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
339
{"uhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
340
{"uhsub_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
341
{"uhsubr_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
342
{"umaxp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
343
{"uminp_z_p_zz"_h, &Simulator::SimulateSVEIntArithPair},
344
{"umlalb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
345
{"umlalb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
346
{"umlalb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
347
{"umlalt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
348
{"umlalt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
349
{"umlalt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
350
{"umlslb_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
351
{"umlslb_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
352
{"umlslb_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
353
{"umlslt_z_zzz"_h, &Simulator::Simulate_ZdaT_ZnTb_ZmTb},
354
{"umlslt_z_zzzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
355
{"umlslt_z_zzzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
356
{"umulh_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmT},
357
{"umullb_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
358
{"umullb_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
359
{"umullb_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
360
{"umullt_z_zz"_h, &Simulator::SimulateSVEIntMulLongVec},
361
{"umullt_z_zzi_d"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
362
{"umullt_z_zzi_s"_h, &Simulator::SimulateSVESaturatingIntMulLongIdx},
363
{"uqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
364
{"uqrshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
365
{"uqrshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
366
{"uqrshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
367
{"uqrshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
368
{"uqshl_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
369
{"uqshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
370
{"uqshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
371
{"uqshrnb_z_zi"_h, &Simulator::SimulateSVENarrow},
372
{"uqshrnt_z_zi"_h, &Simulator::SimulateSVENarrow},
373
{"uqsub_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
374
{"uqsubr_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
375
{"uqxtnb_z_zz"_h, &Simulator::SimulateSVENarrow},
376
{"uqxtnt_z_zz"_h, &Simulator::SimulateSVENarrow},
377
{"urecpe_z_p_z"_h, &Simulator::Simulate_ZdS_PgM_ZnS},
378
{"urhadd_z_p_zz"_h, &Simulator::SimulateSVEHalvingAddSub},
379
{"urshl_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
380
{"urshlr_z_p_zz"_h, &Simulator::VisitSVEBitwiseShiftByVector_Predicated},
381
{"urshr_z_p_zi"_h, &Simulator::Simulate_ZdnT_PgM_ZdnT_const},
382
{"ursqrte_z_p_z"_h, &Simulator::Simulate_ZdS_PgM_ZnS},
383
{"ursra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},
384
{"ushllb_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},
385
{"ushllt_z_zi"_h, &Simulator::SimulateSVEShiftLeftImm},
386
{"usqadd_z_p_zz"_h, &Simulator::SimulateSVESaturatingArithmetic},
387
{"usra_z_zi"_h, &Simulator::Simulate_ZdaT_ZnT_const},
388
{"usublb_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
389
{"usublt_z_zz"_h, &Simulator::SimulateSVEInterleavedArithLong},
390
{"usubwb_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
391
{"usubwt_z_zz"_h, &Simulator::Simulate_ZdT_ZnT_ZmTb},
392
{"whilege_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},
393
{"whilegt_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},
394
{"whilehi_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},
395
{"whilehs_p_p_rr"_h, &Simulator::VisitSVEIntCompareScalarCountAndLimit},
396
{"whilerw_p_rr"_h, &Simulator::Simulate_PdT_Xn_Xm},
397
{"whilewr_p_rr"_h, &Simulator::Simulate_PdT_Xn_Xm},
398
{"xar_z_zzi"_h, &Simulator::SimulateSVEExclusiveOrRotate},
399
{"smmla_z_zzz"_h, &Simulator::SimulateMatrixMul},
400
{"ummla_z_zzz"_h, &Simulator::SimulateMatrixMul},
401
{"usmmla_z_zzz"_h, &Simulator::SimulateMatrixMul},
402
{"smmla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul},
403
{"ummla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul},
404
{"usmmla_asimdsame2_g"_h, &Simulator::SimulateMatrixMul},
405
{"fmmla_z_zzz_s"_h, &Simulator::SimulateSVEFPMatrixMul},
406
{"fmmla_z_zzz_d"_h, &Simulator::SimulateSVEFPMatrixMul},
407
{"ld1row_z_p_bi_u32"_h,
408
&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
409
{"ld1row_z_p_br_contiguous"_h,
410
&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
411
{"ld1rod_z_p_bi_u64"_h,
412
&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
413
{"ld1rod_z_p_br_contiguous"_h,
414
&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
415
{"ld1rob_z_p_bi_u8"_h,
416
&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
417
{"ld1rob_z_p_br_contiguous"_h,
418
&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
419
{"ld1roh_z_p_bi_u16"_h,
420
&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm},
421
{"ld1roh_z_p_br_contiguous"_h,
422
&Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar},
423
{"usdot_z_zzz_s"_h, &Simulator::VisitSVEIntMulAddUnpredicated},
424
{"sudot_z_zzzi_s"_h, &Simulator::VisitSVEMulIndex},
425
{"usdot_z_zzzi_s"_h, &Simulator::VisitSVEMulIndex},
426
{"usdot_asimdsame2_d"_h, &Simulator::VisitNEON3SameExtra},
427
{"sudot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},
428
{"usdot_asimdelem_d"_h, &Simulator::SimulateNEONDotProdByElement},
429
{"addg_64_addsub_immtags"_h, &Simulator::SimulateMTEAddSubTag},
430
{"gmi_64g_dp_2src"_h, &Simulator::SimulateMTETagMaskInsert},
431
{"irg_64i_dp_2src"_h, &Simulator::Simulate_XdSP_XnSP_Xm},
432
{"ldg_64loffset_ldsttags"_h, &Simulator::SimulateMTELoadTag},
433
{"st2g_64soffset_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
434
{"st2g_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
435
{"st2g_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
436
{"stgp_64_ldstpair_off"_h, &Simulator::SimulateMTEStoreTagPair},
437
{"stgp_64_ldstpair_post"_h, &Simulator::SimulateMTEStoreTagPair},
438
{"stgp_64_ldstpair_pre"_h, &Simulator::SimulateMTEStoreTagPair},
439
{"stg_64soffset_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
440
{"stg_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
441
{"stg_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
442
{"stz2g_64soffset_ldsttags"_h,
443
&Simulator::Simulator::SimulateMTEStoreTag},
444
{"stz2g_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
445
{"stz2g_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
446
{"stzg_64soffset_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
447
{"stzg_64spost_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
448
{"stzg_64spre_ldsttags"_h, &Simulator::Simulator::SimulateMTEStoreTag},
449
{"subg_64_addsub_immtags"_h, &Simulator::SimulateMTEAddSubTag},
450
{"subps_64s_dp_2src"_h, &Simulator::SimulateMTESubPointer},
451
{"subp_64s_dp_2src"_h, &Simulator::SimulateMTESubPointer},
452
{"cpyen_cpy_memcms"_h, &Simulator::SimulateCpyE},
453
{"cpyern_cpy_memcms"_h, &Simulator::SimulateCpyE},
454
{"cpyewn_cpy_memcms"_h, &Simulator::SimulateCpyE},
455
{"cpye_cpy_memcms"_h, &Simulator::SimulateCpyE},
456
{"cpyfen_cpy_memcms"_h, &Simulator::SimulateCpyE},
457
{"cpyfern_cpy_memcms"_h, &Simulator::SimulateCpyE},
458
{"cpyfewn_cpy_memcms"_h, &Simulator::SimulateCpyE},
459
{"cpyfe_cpy_memcms"_h, &Simulator::SimulateCpyE},
460
{"cpyfmn_cpy_memcms"_h, &Simulator::SimulateCpyM},
461
{"cpyfmrn_cpy_memcms"_h, &Simulator::SimulateCpyM},
462
{"cpyfmwn_cpy_memcms"_h, &Simulator::SimulateCpyM},
463
{"cpyfm_cpy_memcms"_h, &Simulator::SimulateCpyM},
464
{"cpyfpn_cpy_memcms"_h, &Simulator::SimulateCpyFP},
465
{"cpyfprn_cpy_memcms"_h, &Simulator::SimulateCpyFP},
466
{"cpyfpwn_cpy_memcms"_h, &Simulator::SimulateCpyFP},
467
{"cpyfp_cpy_memcms"_h, &Simulator::SimulateCpyFP},
468
{"cpymn_cpy_memcms"_h, &Simulator::SimulateCpyM},
469
{"cpymrn_cpy_memcms"_h, &Simulator::SimulateCpyM},
470
{"cpymwn_cpy_memcms"_h, &Simulator::SimulateCpyM},
471
{"cpym_cpy_memcms"_h, &Simulator::SimulateCpyM},
472
{"cpypn_cpy_memcms"_h, &Simulator::SimulateCpyP},
473
{"cpyprn_cpy_memcms"_h, &Simulator::SimulateCpyP},
474
{"cpypwn_cpy_memcms"_h, &Simulator::SimulateCpyP},
475
{"cpyp_cpy_memcms"_h, &Simulator::SimulateCpyP},
476
{"setp_set_memcms"_h, &Simulator::SimulateSetP},
477
{"setpn_set_memcms"_h, &Simulator::SimulateSetP},
478
{"setgp_set_memcms"_h, &Simulator::SimulateSetGP},
479
{"setgpn_set_memcms"_h, &Simulator::SimulateSetGP},
480
{"setm_set_memcms"_h, &Simulator::SimulateSetM},
481
{"setmn_set_memcms"_h, &Simulator::SimulateSetM},
482
{"setgm_set_memcms"_h, &Simulator::SimulateSetGM},
483
{"setgmn_set_memcms"_h, &Simulator::SimulateSetGM},
484
{"sete_set_memcms"_h, &Simulator::SimulateSetE},
485
{"seten_set_memcms"_h, &Simulator::SimulateSetE},
486
{"setge_set_memcms"_h, &Simulator::SimulateSetE},
487
{"setgen_set_memcms"_h, &Simulator::SimulateSetE},
488
{"abs_32_dp_1src"_h, &Simulator::VisitDataProcessing1Source},
489
{"abs_64_dp_1src"_h, &Simulator::VisitDataProcessing1Source},
490
{"cnt_32_dp_1src"_h, &Simulator::VisitDataProcessing1Source},
491
{"cnt_64_dp_1src"_h, &Simulator::VisitDataProcessing1Source},
492
{"ctz_32_dp_1src"_h, &Simulator::VisitDataProcessing1Source},
493
{"ctz_64_dp_1src"_h, &Simulator::VisitDataProcessing1Source},
494
{"smax_32_dp_2src"_h, &Simulator::SimulateSignedMinMax},
495
{"smax_64_dp_2src"_h, &Simulator::SimulateSignedMinMax},
496
{"smin_32_dp_2src"_h, &Simulator::SimulateSignedMinMax},
497
{"smin_64_dp_2src"_h, &Simulator::SimulateSignedMinMax},
498
{"smax_32_minmax_imm"_h, &Simulator::SimulateSignedMinMax},
499
{"smax_64_minmax_imm"_h, &Simulator::SimulateSignedMinMax},
500
{"smin_32_minmax_imm"_h, &Simulator::SimulateSignedMinMax},
501
{"smin_64_minmax_imm"_h, &Simulator::SimulateSignedMinMax},
502
{"umax_32_dp_2src"_h, &Simulator::SimulateUnsignedMinMax},
503
{"umax_64_dp_2src"_h, &Simulator::SimulateUnsignedMinMax},
504
{"umin_32_dp_2src"_h, &Simulator::SimulateUnsignedMinMax},
505
{"umin_64_dp_2src"_h, &Simulator::SimulateUnsignedMinMax},
506
{"umax_32u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax},
507
{"umax_64u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax},
508
{"umin_32u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax},
509
{"umin_64u_minmax_imm"_h, &Simulator::SimulateUnsignedMinMax},
510
};
511
return &form_to_visitor;
512
}
513
514
// Try to access the piece of memory given by the address passed in RDI and the
515
// offset passed in RSI, using testb. If a signal is raised then the signal
516
// handler should set RIP to _vixl_internal_AccessMemory_continue and RAX to
517
// MemoryAccessResult::Failure. If no signal is raised then zero RAX before
518
// returning.
519
#ifdef VIXL_ENABLE_IMPLICIT_CHECKS
520
#ifdef __x86_64__
521
asm(R"(
522
.globl _vixl_internal_ReadMemory
523
_vixl_internal_ReadMemory:
524
testb (%rdi, %rsi), %al
525
xorq %rax, %rax
526
ret
527
.globl _vixl_internal_AccessMemory_continue
528
_vixl_internal_AccessMemory_continue:
529
ret
530
)");
531
#else
532
asm(R"(
533
.globl _vixl_internal_ReadMemory
534
_vixl_internal_ReadMemory:
535
ret
536
)");
537
#endif // __x86_64__
538
#endif // VIXL_ENABLE_IMPLICIT_CHECKS
539
540
Simulator::Simulator(Decoder* decoder, FILE* stream, SimStack::Allocated stack)
541
: memory_(std::move(stack)),
542
last_instr_(NULL),
543
cpu_features_auditor_(decoder, CPUFeatures::All()) {
544
// Ensure that shift operations act as the simulator expects.
545
VIXL_ASSERT((static_cast<int32_t>(-1) >> 1) == -1);
546
VIXL_ASSERT((static_cast<uint32_t>(-1) >> 1) == 0x7fffffff);
547
548
// Set up a placeholder pipe for CanReadMemory.
549
VIXL_CHECK(pipe(placeholder_pipe_fd_) == 0);
550
551
// Set up the decoder.
552
decoder_ = decoder;
553
decoder_->AppendVisitor(this);
554
555
stream_ = stream;
556
557
print_disasm_ = new PrintDisassembler(stream_);
558
559
memory_.AppendMetaData(&meta_data_);
560
561
// The Simulator and Disassembler share the same available list, held by the
562
// auditor. The Disassembler only annotates instructions with features that
563
// are _not_ available, so registering the auditor should have no effect
564
// unless the simulator is about to abort (due to missing features). In
565
// practice, this means that with trace enabled, the simulator will crash just
566
// after the disassembler prints the instruction, with the missing features
567
// enumerated.
568
print_disasm_->RegisterCPUFeaturesAuditor(&cpu_features_auditor_);
569
570
SetColouredTrace(false);
571
trace_parameters_ = LOG_NONE;
572
573
// We have to configure the SVE vector register length before calling
574
// ResetState().
575
SetVectorLengthInBits(kZRegMinSize);
576
577
ResetState();
578
579
// Print a warning about exclusive-access instructions, but only the first
580
// time they are encountered. This warning can be silenced using
581
// SilenceExclusiveAccessWarning().
582
print_exclusive_access_warning_ = true;
583
584
guard_pages_ = false;
585
586
// Initialize the common state of RNDR and RNDRRS.
587
uint16_t seed[3] = {11, 22, 33};
588
VIXL_STATIC_ASSERT(sizeof(seed) == sizeof(rand_state_));
589
memcpy(rand_state_, seed, sizeof(rand_state_));
590
591
// Initialize all bits of pseudo predicate register to true.
592
LogicPRegister ones(pregister_all_true_);
593
ones.SetAllBits();
594
595
// Initialize the debugger but disable it by default.
596
SetDebuggerEnabled(false);
597
debugger_ = std::make_unique<Debugger>(this);
598
}
599
600
void Simulator::ResetSystemRegisters() {
601
// Reset the system registers.
602
nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
603
fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
604
ResetFFR();
605
}
606
607
void Simulator::ResetRegisters() {
608
for (unsigned i = 0; i < kNumberOfRegisters; i++) {
609
WriteXRegister(i, 0xbadbeef);
610
}
611
// Returning to address 0 exits the Simulator.
612
WriteLr(kEndOfSimAddress);
613
}
614
615
void Simulator::ResetVRegisters() {
616
// Set SVE/FP registers to a value that is a NaN in both 32-bit and 64-bit FP.
617
VIXL_ASSERT((GetVectorLengthInBytes() % kDRegSizeInBytes) == 0);
618
int lane_count = GetVectorLengthInBytes() / kDRegSizeInBytes;
619
for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
620
VIXL_ASSERT(vregisters_[i].GetSizeInBytes() == GetVectorLengthInBytes());
621
vregisters_[i].NotifyAccessAsZ();
622
for (int lane = 0; lane < lane_count; lane++) {
623
// Encode the register number and (D-sized) lane into each NaN, to
624
// make them easier to trace.
625
uint64_t nan_bits = 0x7ff0f0007f80f000 | (0x0000000100000000 * i) |
626
(0x0000000000000001 * lane);
627
VIXL_ASSERT(IsSignallingNaN(RawbitsToDouble(nan_bits & kDRegMask)));
628
VIXL_ASSERT(IsSignallingNaN(RawbitsToFloat(nan_bits & kSRegMask)));
629
vregisters_[i].Insert(lane, nan_bits);
630
}
631
}
632
}
633
634
void Simulator::ResetPRegisters() {
635
VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
636
int lane_count = GetPredicateLengthInBytes() / kHRegSizeInBytes;
637
// Ensure the register configuration fits in this bit encoding.
638
VIXL_STATIC_ASSERT(kNumberOfPRegisters <= UINT8_MAX);
639
VIXL_ASSERT(lane_count <= UINT8_MAX);
640
for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
641
VIXL_ASSERT(pregisters_[i].GetSizeInBytes() == GetPredicateLengthInBytes());
642
for (int lane = 0; lane < lane_count; lane++) {
643
// Encode the register number and (H-sized) lane into each lane slot.
644
uint16_t bits = (0x0100 * lane) | i;
645
pregisters_[i].Insert(lane, bits);
646
}
647
}
648
}
649
650
void Simulator::ResetFFR() {
651
VIXL_ASSERT((GetPredicateLengthInBytes() % kHRegSizeInBytes) == 0);
652
int default_active_lanes = GetPredicateLengthInBytes() / kHRegSizeInBytes;
653
ffr_register_.Write(static_cast<uint16_t>(GetUintMask(default_active_lanes)));
654
}
655
656
void Simulator::ResetState() {
657
ResetSystemRegisters();
658
ResetRegisters();
659
ResetVRegisters();
660
ResetPRegisters();
661
662
WriteSp(memory_.GetStack().GetBase());
663
664
pc_ = NULL;
665
pc_modified_ = false;
666
667
// BTI state.
668
btype_ = DefaultBType;
669
next_btype_ = DefaultBType;
670
671
meta_data_.ResetState();
672
}
673
674
void Simulator::SetVectorLengthInBits(unsigned vector_length) {
675
VIXL_ASSERT((vector_length >= kZRegMinSize) &&
676
(vector_length <= kZRegMaxSize));
677
VIXL_ASSERT((vector_length % kZRegMinSize) == 0);
678
vector_length_ = vector_length;
679
680
for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
681
vregisters_[i].SetSizeInBytes(GetVectorLengthInBytes());
682
}
683
for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
684
pregisters_[i].SetSizeInBytes(GetPredicateLengthInBytes());
685
}
686
687
ffr_register_.SetSizeInBytes(GetPredicateLengthInBytes());
688
689
ResetVRegisters();
690
ResetPRegisters();
691
ResetFFR();
692
}
693
694
Simulator::~Simulator() {
695
// The decoder may outlive the simulator.
696
decoder_->RemoveVisitor(print_disasm_);
697
delete print_disasm_;
698
close(placeholder_pipe_fd_[0]);
699
close(placeholder_pipe_fd_[1]);
700
}
701
702
703
void Simulator::Run() {
704
// Flush any written registers before executing anything, so that
705
// manually-set registers are logged _before_ the first instruction.
706
LogAllWrittenRegisters();
707
708
if (debugger_enabled_) {
709
// Slow path to check for breakpoints only if the debugger is enabled.
710
Debugger* debugger = GetDebugger();
711
while (!IsSimulationFinished()) {
712
if (debugger->IsAtBreakpoint()) {
713
fprintf(stream_, "Debugger hit breakpoint, breaking...\n");
714
debugger->Debug();
715
} else {
716
ExecuteInstruction();
717
}
718
}
719
} else {
720
while (!IsSimulationFinished()) {
721
ExecuteInstruction();
722
}
723
}
724
}
725
726
727
void Simulator::RunFrom(const Instruction* first) {
728
WritePc(first, NoBranchLog);
729
Run();
730
}
731
732
733
// clang-format off
734
const char* Simulator::xreg_names[] = {"x0", "x1", "x2", "x3", "x4", "x5",
735
"x6", "x7", "x8", "x9", "x10", "x11",
736
"x12", "x13", "x14", "x15", "x16", "x17",
737
"x18", "x19", "x20", "x21", "x22", "x23",
738
"x24", "x25", "x26", "x27", "x28", "x29",
739
"lr", "xzr", "sp"};
740
741
const char* Simulator::wreg_names[] = {"w0", "w1", "w2", "w3", "w4", "w5",
742
"w6", "w7", "w8", "w9", "w10", "w11",
743
"w12", "w13", "w14", "w15", "w16", "w17",
744
"w18", "w19", "w20", "w21", "w22", "w23",
745
"w24", "w25", "w26", "w27", "w28", "w29",
746
"w30", "wzr", "wsp"};
747
748
const char* Simulator::breg_names[] = {"b0", "b1", "b2", "b3", "b4", "b5",
749
"b6", "b7", "b8", "b9", "b10", "b11",
750
"b12", "b13", "b14", "b15", "b16", "b17",
751
"b18", "b19", "b20", "b21", "b22", "b23",
752
"b24", "b25", "b26", "b27", "b28", "b29",
753
"b30", "b31"};
754
755
const char* Simulator::hreg_names[] = {"h0", "h1", "h2", "h3", "h4", "h5",
756
"h6", "h7", "h8", "h9", "h10", "h11",
757
"h12", "h13", "h14", "h15", "h16", "h17",
758
"h18", "h19", "h20", "h21", "h22", "h23",
759
"h24", "h25", "h26", "h27", "h28", "h29",
760
"h30", "h31"};
761
762
const char* Simulator::sreg_names[] = {"s0", "s1", "s2", "s3", "s4", "s5",
763
"s6", "s7", "s8", "s9", "s10", "s11",
764
"s12", "s13", "s14", "s15", "s16", "s17",
765
"s18", "s19", "s20", "s21", "s22", "s23",
766
"s24", "s25", "s26", "s27", "s28", "s29",
767
"s30", "s31"};
768
769
const char* Simulator::dreg_names[] = {"d0", "d1", "d2", "d3", "d4", "d5",
770
"d6", "d7", "d8", "d9", "d10", "d11",
771
"d12", "d13", "d14", "d15", "d16", "d17",
772
"d18", "d19", "d20", "d21", "d22", "d23",
773
"d24", "d25", "d26", "d27", "d28", "d29",
774
"d30", "d31"};
775
776
const char* Simulator::vreg_names[] = {"v0", "v1", "v2", "v3", "v4", "v5",
777
"v6", "v7", "v8", "v9", "v10", "v11",
778
"v12", "v13", "v14", "v15", "v16", "v17",
779
"v18", "v19", "v20", "v21", "v22", "v23",
780
"v24", "v25", "v26", "v27", "v28", "v29",
781
"v30", "v31"};
782
783
const char* Simulator::zreg_names[] = {"z0", "z1", "z2", "z3", "z4", "z5",
784
"z6", "z7", "z8", "z9", "z10", "z11",
785
"z12", "z13", "z14", "z15", "z16", "z17",
786
"z18", "z19", "z20", "z21", "z22", "z23",
787
"z24", "z25", "z26", "z27", "z28", "z29",
788
"z30", "z31"};
789
790
const char* Simulator::preg_names[] = {"p0", "p1", "p2", "p3", "p4", "p5",
791
"p6", "p7", "p8", "p9", "p10", "p11",
792
"p12", "p13", "p14", "p15"};
793
// clang-format on
794
795
796
const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
797
// If the code represents the stack pointer, index the name after zr.
798
if ((code == kSPRegInternalCode) ||
799
((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
800
code = kZeroRegCode + 1;
801
}
802
VIXL_ASSERT(code < ArrayLength(wreg_names));
803
return wreg_names[code];
804
}
805
806
807
const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
808
// If the code represents the stack pointer, index the name after zr.
809
if ((code == kSPRegInternalCode) ||
810
((code == kZeroRegCode) && (mode == Reg31IsStackPointer))) {
811
code = kZeroRegCode + 1;
812
}
813
VIXL_ASSERT(code < ArrayLength(xreg_names));
814
return xreg_names[code];
815
}
816
817
818
const char* Simulator::BRegNameForCode(unsigned code) {
819
VIXL_ASSERT(code < kNumberOfVRegisters);
820
return breg_names[code];
821
}
822
823
824
const char* Simulator::HRegNameForCode(unsigned code) {
825
VIXL_ASSERT(code < kNumberOfVRegisters);
826
return hreg_names[code];
827
}
828
829
830
const char* Simulator::SRegNameForCode(unsigned code) {
831
VIXL_ASSERT(code < kNumberOfVRegisters);
832
return sreg_names[code];
833
}
834
835
836
const char* Simulator::DRegNameForCode(unsigned code) {
837
VIXL_ASSERT(code < kNumberOfVRegisters);
838
return dreg_names[code];
839
}
840
841
842
const char* Simulator::VRegNameForCode(unsigned code) {
843
VIXL_ASSERT(code < kNumberOfVRegisters);
844
return vreg_names[code];
845
}
846
847
848
const char* Simulator::ZRegNameForCode(unsigned code) {
849
VIXL_ASSERT(code < kNumberOfZRegisters);
850
return zreg_names[code];
851
}
852
853
854
const char* Simulator::PRegNameForCode(unsigned code) {
855
VIXL_ASSERT(code < kNumberOfPRegisters);
856
return preg_names[code];
857
}
858
859
SimVRegister Simulator::ExpandToSimVRegister(const SimPRegister& pg) {
860
SimVRegister ones, result;
861
dup_immediate(kFormatVnB, ones, 0xff);
862
mov_zeroing(kFormatVnB, result, pg, ones);
863
return result;
864
}
865
866
void Simulator::ExtractFromSimVRegister(VectorFormat vform,
867
SimPRegister& pd,
868
SimVRegister vreg) {
869
SimVRegister zero;
870
dup_immediate(kFormatVnB, zero, 0);
871
SVEIntCompareVectorsHelper(ne,
872
vform,
873
pd,
874
GetPTrue(),
875
vreg,
876
zero,
877
false,
878
LeaveFlags);
879
}
880
881
#define COLOUR(colour_code) "\033[0;" colour_code "m"
882
#define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
883
#define COLOUR_HIGHLIGHT "\033[43m"
884
#define NORMAL ""
885
#define GREY "30"
886
#define RED "31"
887
#define GREEN "32"
888
#define YELLOW "33"
889
#define BLUE "34"
890
#define MAGENTA "35"
891
#define CYAN "36"
892
#define WHITE "37"
893
void Simulator::SetColouredTrace(bool value) {
894
coloured_trace_ = value;
895
896
clr_normal = value ? COLOUR(NORMAL) : "";
897
clr_flag_name = value ? COLOUR_BOLD(WHITE) : "";
898
clr_flag_value = value ? COLOUR(NORMAL) : "";
899
clr_reg_name = value ? COLOUR_BOLD(CYAN) : "";
900
clr_reg_value = value ? COLOUR(CYAN) : "";
901
clr_vreg_name = value ? COLOUR_BOLD(MAGENTA) : "";
902
clr_vreg_value = value ? COLOUR(MAGENTA) : "";
903
clr_preg_name = value ? COLOUR_BOLD(GREEN) : "";
904
clr_preg_value = value ? COLOUR(GREEN) : "";
905
clr_memory_address = value ? COLOUR_BOLD(BLUE) : "";
906
clr_warning = value ? COLOUR_BOLD(YELLOW) : "";
907
clr_warning_message = value ? COLOUR(YELLOW) : "";
908
clr_printf = value ? COLOUR(GREEN) : "";
909
clr_branch_marker = value ? COLOUR(GREY) COLOUR_HIGHLIGHT : "";
910
911
if (value) {
912
print_disasm_->SetCPUFeaturesPrefix("// Needs: " COLOUR_BOLD(RED));
913
print_disasm_->SetCPUFeaturesSuffix(COLOUR(NORMAL));
914
} else {
915
print_disasm_->SetCPUFeaturesPrefix("// Needs: ");
916
print_disasm_->SetCPUFeaturesSuffix("");
917
}
918
}
919
920
921
void Simulator::SetTraceParameters(int parameters) {
922
bool disasm_before = trace_parameters_ & LOG_DISASM;
923
trace_parameters_ = parameters;
924
bool disasm_after = trace_parameters_ & LOG_DISASM;
925
926
if (disasm_before != disasm_after) {
927
if (disasm_after) {
928
decoder_->InsertVisitorBefore(print_disasm_, this);
929
} else {
930
decoder_->RemoveVisitor(print_disasm_);
931
}
932
}
933
}
934
935
// Helpers ---------------------------------------------------------------------
936
uint64_t Simulator::AddWithCarry(unsigned reg_size,
937
bool set_flags,
938
uint64_t left,
939
uint64_t right,
940
int carry_in) {
941
std::pair<uint64_t, uint8_t> result_and_flags =
942
AddWithCarry(reg_size, left, right, carry_in);
943
if (set_flags) {
944
uint8_t flags = result_and_flags.second;
945
ReadNzcv().SetN((flags >> 3) & 1);
946
ReadNzcv().SetZ((flags >> 2) & 1);
947
ReadNzcv().SetC((flags >> 1) & 1);
948
ReadNzcv().SetV((flags >> 0) & 1);
949
LogSystemRegister(NZCV);
950
}
951
return result_and_flags.first;
952
}
953
954
std::pair<uint64_t, uint8_t> Simulator::AddWithCarry(unsigned reg_size,
955
uint64_t left,
956
uint64_t right,
957
int carry_in) {
958
VIXL_ASSERT((carry_in == 0) || (carry_in == 1));
959
VIXL_ASSERT((reg_size == kXRegSize) || (reg_size == kWRegSize));
960
961
uint64_t max_uint = (reg_size == kWRegSize) ? kWMaxUInt : kXMaxUInt;
962
uint64_t reg_mask = (reg_size == kWRegSize) ? kWRegMask : kXRegMask;
963
uint64_t sign_mask = (reg_size == kWRegSize) ? kWSignMask : kXSignMask;
964
965
left &= reg_mask;
966
right &= reg_mask;
967
uint64_t result = (left + right + carry_in) & reg_mask;
968
969
// NZCV bits, ordered N in bit 3 to V in bit 0.
970
uint8_t nzcv = CalcNFlag(result, reg_size) ? 8 : 0;
971
nzcv |= CalcZFlag(result) ? 4 : 0;
972
973
// Compute the C flag by comparing the result to the max unsigned integer.
974
uint64_t max_uint_2op = max_uint - carry_in;
975
bool C = (left > max_uint_2op) || ((max_uint_2op - left) < right);
976
nzcv |= C ? 2 : 0;
977
978
// Overflow iff the sign bit is the same for the two inputs and different
979
// for the result.
980
uint64_t left_sign = left & sign_mask;
981
uint64_t right_sign = right & sign_mask;
982
uint64_t result_sign = result & sign_mask;
983
bool V = (left_sign == right_sign) && (left_sign != result_sign);
984
nzcv |= V ? 1 : 0;
985
986
return std::make_pair(result, nzcv);
987
}
988
989
using vixl_uint128_t = std::pair<uint64_t, uint64_t>;
990
991
vixl_uint128_t Simulator::Add128(vixl_uint128_t x, vixl_uint128_t y) {
992
std::pair<uint64_t, uint8_t> sum_lo =
993
AddWithCarry(kXRegSize, x.second, y.second, 0);
994
int carry_in = (sum_lo.second & 0x2) >> 1; // C flag in NZCV result.
995
std::pair<uint64_t, uint8_t> sum_hi =
996
AddWithCarry(kXRegSize, x.first, y.first, carry_in);
997
return std::make_pair(sum_hi.first, sum_lo.first);
998
}
999
1000
vixl_uint128_t Simulator::Lsl128(vixl_uint128_t x, unsigned shift) const {
1001
VIXL_ASSERT(shift <= 64);
1002
if (shift == 0) return x;
1003
if (shift == 64) return std::make_pair(x.second, 0);
1004
uint64_t lo = x.second << shift;
1005
uint64_t hi = (x.first << shift) | (x.second >> (64 - shift));
1006
return std::make_pair(hi, lo);
1007
}
1008
1009
vixl_uint128_t Simulator::Eor128(vixl_uint128_t x, vixl_uint128_t y) const {
1010
return std::make_pair(x.first ^ y.first, x.second ^ y.second);
1011
}
1012
1013
vixl_uint128_t Simulator::Neg128(vixl_uint128_t x) {
1014
// Negate the integer value. Throw an assertion when the input is INT128_MIN.
1015
VIXL_ASSERT((x.first != GetSignMask(64)) || (x.second != 0));
1016
x.first = ~x.first;
1017
x.second = ~x.second;
1018
return Add128(x, {0, 1});
1019
}
1020
1021
vixl_uint128_t Simulator::Mul64(uint64_t x, uint64_t y) {
1022
bool neg_result = false;
1023
if ((x >> 63) == 1) {
1024
x = -x;
1025
neg_result = !neg_result;
1026
}
1027
if ((y >> 63) == 1) {
1028
y = -y;
1029
neg_result = !neg_result;
1030
}
1031
1032
uint64_t x_lo = x & 0xffffffff;
1033
uint64_t x_hi = x >> 32;
1034
uint64_t y_lo = y & 0xffffffff;
1035
uint64_t y_hi = y >> 32;
1036
1037
uint64_t t1 = x_lo * y_hi;
1038
uint64_t t2 = x_hi * y_lo;
1039
vixl_uint128_t a = std::make_pair(0, x_lo * y_lo);
1040
vixl_uint128_t b = std::make_pair(t1 >> 32, t1 << 32);
1041
vixl_uint128_t c = std::make_pair(t2 >> 32, t2 << 32);
1042
vixl_uint128_t d = std::make_pair(x_hi * y_hi, 0);
1043
1044
vixl_uint128_t result = Add128(a, b);
1045
result = Add128(result, c);
1046
result = Add128(result, d);
1047
return neg_result ? std::make_pair(-result.first - 1, -result.second)
1048
: result;
1049
}
1050
1051
vixl_uint128_t Simulator::PolynomialMult128(uint64_t op1,
1052
uint64_t op2,
1053
int lane_size_in_bits) const {
1054
VIXL_ASSERT(static_cast<unsigned>(lane_size_in_bits) <= kDRegSize);
1055
vixl_uint128_t result = std::make_pair(0, 0);
1056
vixl_uint128_t op2q = std::make_pair(0, op2);
1057
for (int i = 0; i < lane_size_in_bits; i++) {
1058
if ((op1 >> i) & 1) {
1059
result = Eor128(result, Lsl128(op2q, i));
1060
}
1061
}
1062
return result;
1063
}
1064
1065
int64_t Simulator::ShiftOperand(unsigned reg_size,
1066
uint64_t uvalue,
1067
Shift shift_type,
1068
unsigned amount) const {
1069
VIXL_ASSERT((reg_size == kBRegSize) || (reg_size == kHRegSize) ||
1070
(reg_size == kSRegSize) || (reg_size == kDRegSize));
1071
if (amount > 0) {
1072
uint64_t mask = GetUintMask(reg_size);
1073
bool is_negative = (uvalue & GetSignMask(reg_size)) != 0;
1074
// The behavior is undefined in c++ if the shift amount greater than or
1075
// equal to the register lane size. Work out the shifted result based on
1076
// architectural behavior before performing the c++ type shift operations.
1077
switch (shift_type) {
1078
case LSL:
1079
if (amount >= reg_size) {
1080
return UINT64_C(0);
1081
}
1082
uvalue <<= amount;
1083
break;
1084
case LSR:
1085
if (amount >= reg_size) {
1086
return UINT64_C(0);
1087
}
1088
uvalue >>= amount;
1089
break;
1090
case ASR:
1091
if (amount >= reg_size) {
1092
return is_negative ? ~UINT64_C(0) : UINT64_C(0);
1093
}
1094
uvalue >>= amount;
1095
if (is_negative) {
1096
// Simulate sign-extension to 64 bits.
1097
uvalue |= ~UINT64_C(0) << (reg_size - amount);
1098
}
1099
break;
1100
case ROR: {
1101
uvalue = RotateRight(uvalue, amount, reg_size);
1102
break;
1103
}
1104
default:
1105
VIXL_UNIMPLEMENTED();
1106
return 0;
1107
}
1108
uvalue &= mask;
1109
}
1110
1111
int64_t result;
1112
memcpy(&result, &uvalue, sizeof(result));
1113
return result;
1114
}
1115
1116
1117
int64_t Simulator::ExtendValue(unsigned reg_size,
1118
int64_t value,
1119
Extend extend_type,
1120
unsigned left_shift) const {
1121
switch (extend_type) {
1122
case UXTB:
1123
value &= kByteMask;
1124
break;
1125
case UXTH:
1126
value &= kHalfWordMask;
1127
break;
1128
case UXTW:
1129
value &= kWordMask;
1130
break;
1131
case SXTB:
1132
value &= kByteMask;
1133
if ((value & 0x80) != 0) {
1134
value |= ~UINT64_C(0) << 8;
1135
}
1136
break;
1137
case SXTH:
1138
value &= kHalfWordMask;
1139
if ((value & 0x8000) != 0) {
1140
value |= ~UINT64_C(0) << 16;
1141
}
1142
break;
1143
case SXTW:
1144
value &= kWordMask;
1145
if ((value & 0x80000000) != 0) {
1146
value |= ~UINT64_C(0) << 32;
1147
}
1148
break;
1149
case UXTX:
1150
case SXTX:
1151
break;
1152
default:
1153
VIXL_UNREACHABLE();
1154
}
1155
return ShiftOperand(reg_size, value, LSL, left_shift);
1156
}
1157
1158
1159
void Simulator::FPCompare(double val0, double val1, FPTrapFlags trap) {
1160
AssertSupportedFPCR();
1161
1162
// TODO: This assumes that the C++ implementation handles comparisons in the
1163
// way that we expect (as per AssertSupportedFPCR()).
1164
bool process_exception = false;
1165
if ((IsNaN(val0) != 0) || (IsNaN(val1) != 0)) {
1166
ReadNzcv().SetRawValue(FPUnorderedFlag);
1167
if (IsSignallingNaN(val0) || IsSignallingNaN(val1) ||
1168
(trap == EnableTrap)) {
1169
process_exception = true;
1170
}
1171
} else if (val0 < val1) {
1172
ReadNzcv().SetRawValue(FPLessThanFlag);
1173
} else if (val0 > val1) {
1174
ReadNzcv().SetRawValue(FPGreaterThanFlag);
1175
} else if (val0 == val1) {
1176
ReadNzcv().SetRawValue(FPEqualFlag);
1177
} else {
1178
VIXL_UNREACHABLE();
1179
}
1180
LogSystemRegister(NZCV);
1181
if (process_exception) FPProcessException();
1182
}
1183
1184
1185
uint64_t Simulator::ComputeMemOperandAddress(const MemOperand& mem_op) const {
1186
VIXL_ASSERT(mem_op.IsValid());
1187
int64_t base = ReadRegister<int64_t>(mem_op.GetBaseRegister());
1188
if (mem_op.IsImmediateOffset()) {
1189
return base + mem_op.GetOffset();
1190
} else {
1191
VIXL_ASSERT(mem_op.GetRegisterOffset().IsValid());
1192
int64_t offset = ReadRegister<int64_t>(mem_op.GetRegisterOffset());
1193
unsigned shift_amount = mem_op.GetShiftAmount();
1194
if (mem_op.GetShift() != NO_SHIFT) {
1195
offset = ShiftOperand(kXRegSize, offset, mem_op.GetShift(), shift_amount);
1196
}
1197
if (mem_op.GetExtend() != NO_EXTEND) {
1198
offset = ExtendValue(kXRegSize, offset, mem_op.GetExtend(), shift_amount);
1199
}
1200
return static_cast<uint64_t>(base + offset);
1201
}
1202
}
1203
1204
1205
Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
1206
unsigned reg_size, unsigned lane_size) {
1207
VIXL_ASSERT(reg_size >= lane_size);
1208
1209
uint32_t format = 0;
1210
if (reg_size != lane_size) {
1211
switch (reg_size) {
1212
default:
1213
VIXL_UNREACHABLE();
1214
break;
1215
case kQRegSizeInBytes:
1216
format = kPrintRegAsQVector;
1217
break;
1218
case kDRegSizeInBytes:
1219
format = kPrintRegAsDVector;
1220
break;
1221
}
1222
}
1223
1224
switch (lane_size) {
1225
default:
1226
VIXL_UNREACHABLE();
1227
break;
1228
case kQRegSizeInBytes:
1229
format |= kPrintReg1Q;
1230
break;
1231
case kDRegSizeInBytes:
1232
format |= kPrintReg1D;
1233
break;
1234
case kSRegSizeInBytes:
1235
format |= kPrintReg1S;
1236
break;
1237
case kHRegSizeInBytes:
1238
format |= kPrintReg1H;
1239
break;
1240
case kBRegSizeInBytes:
1241
format |= kPrintReg1B;
1242
break;
1243
}
1244
// These sizes would be duplicate case labels.
1245
VIXL_STATIC_ASSERT(kXRegSizeInBytes == kDRegSizeInBytes);
1246
VIXL_STATIC_ASSERT(kWRegSizeInBytes == kSRegSizeInBytes);
1247
VIXL_STATIC_ASSERT(kPrintXReg == kPrintReg1D);
1248
VIXL_STATIC_ASSERT(kPrintWReg == kPrintReg1S);
1249
1250
return static_cast<PrintRegisterFormat>(format);
1251
}
1252
1253
1254
Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
1255
VectorFormat vform) {
1256
switch (vform) {
1257
default:
1258
VIXL_UNREACHABLE();
1259
return kPrintReg16B;
1260
case kFormat16B:
1261
return kPrintReg16B;
1262
case kFormat8B:
1263
return kPrintReg8B;
1264
case kFormat8H:
1265
return kPrintReg8H;
1266
case kFormat4H:
1267
return kPrintReg4H;
1268
case kFormat4S:
1269
return kPrintReg4S;
1270
case kFormat2S:
1271
return kPrintReg2S;
1272
case kFormat2D:
1273
return kPrintReg2D;
1274
case kFormat1D:
1275
return kPrintReg1D;
1276
1277
case kFormatB:
1278
return kPrintReg1B;
1279
case kFormatH:
1280
return kPrintReg1H;
1281
case kFormatS:
1282
return kPrintReg1S;
1283
case kFormatD:
1284
return kPrintReg1D;
1285
1286
case kFormatVnB:
1287
return kPrintRegVnB;
1288
case kFormatVnH:
1289
return kPrintRegVnH;
1290
case kFormatVnS:
1291
return kPrintRegVnS;
1292
case kFormatVnD:
1293
return kPrintRegVnD;
1294
}
1295
}
1296
1297
1298
Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
1299
VectorFormat vform) {
1300
switch (vform) {
1301
default:
1302
VIXL_UNREACHABLE();
1303
return kPrintReg16B;
1304
case kFormat8H:
1305
return kPrintReg8HFP;
1306
case kFormat4H:
1307
return kPrintReg4HFP;
1308
case kFormat4S:
1309
return kPrintReg4SFP;
1310
case kFormat2S:
1311
return kPrintReg2SFP;
1312
case kFormat2D:
1313
return kPrintReg2DFP;
1314
case kFormat1D:
1315
return kPrintReg1DFP;
1316
case kFormatH:
1317
return kPrintReg1HFP;
1318
case kFormatS:
1319
return kPrintReg1SFP;
1320
case kFormatD:
1321
return kPrintReg1DFP;
1322
}
1323
}
1324
1325
void Simulator::PrintRegisters() {
1326
for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1327
if (i == kSpRegCode) i = kSPRegInternalCode;
1328
PrintRegister(i);
1329
}
1330
}
1331
1332
void Simulator::PrintVRegisters() {
1333
for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1334
PrintVRegister(i);
1335
}
1336
}
1337
1338
void Simulator::PrintZRegisters() {
1339
for (unsigned i = 0; i < kNumberOfZRegisters; i++) {
1340
PrintZRegister(i);
1341
}
1342
}
1343
1344
void Simulator::PrintWrittenRegisters() {
1345
for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1346
if (registers_[i].WrittenSinceLastLog()) {
1347
if (i == kSpRegCode) i = kSPRegInternalCode;
1348
PrintRegister(i);
1349
}
1350
}
1351
}
1352
1353
void Simulator::PrintWrittenVRegisters() {
1354
bool has_sve = GetCPUFeatures()->Has(CPUFeatures::kSVE);
1355
for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1356
if (vregisters_[i].WrittenSinceLastLog()) {
1357
// Z registers are initialised in the constructor before the user can
1358
// configure the CPU features, so we must also check for SVE here.
1359
if (vregisters_[i].AccessedAsZSinceLastLog() && has_sve) {
1360
PrintZRegister(i);
1361
} else {
1362
PrintVRegister(i);
1363
}
1364
}
1365
}
1366
}
1367
1368
void Simulator::PrintWrittenPRegisters() {
1369
// P registers are initialised in the constructor before the user can
1370
// configure the CPU features, so we must check for SVE here.
1371
if (!GetCPUFeatures()->Has(CPUFeatures::kSVE)) return;
1372
for (unsigned i = 0; i < kNumberOfPRegisters; i++) {
1373
if (pregisters_[i].WrittenSinceLastLog()) {
1374
PrintPRegister(i);
1375
}
1376
}
1377
if (ReadFFR().WrittenSinceLastLog()) PrintFFR();
1378
}
1379
1380
void Simulator::PrintSystemRegisters() {
1381
PrintSystemRegister(NZCV);
1382
PrintSystemRegister(FPCR);
1383
}
1384
1385
void Simulator::PrintRegisterValue(const uint8_t* value,
1386
int value_size,
1387
PrintRegisterFormat format) {
1388
int print_width = GetPrintRegSizeInBytes(format);
1389
VIXL_ASSERT(print_width <= value_size);
1390
for (int i = value_size - 1; i >= print_width; i--) {
1391
// Pad with spaces so that values align vertically.
1392
fprintf(stream_, " ");
1393
// If we aren't explicitly printing a partial value, ensure that the
1394
// unprinted bits are zero.
1395
VIXL_ASSERT(((format & kPrintRegPartial) != 0) || (value[i] == 0));
1396
}
1397
fprintf(stream_, "0x");
1398
for (int i = print_width - 1; i >= 0; i--) {
1399
fprintf(stream_, "%02x", value[i]);
1400
}
1401
}
1402
1403
void Simulator::PrintRegisterValueFPAnnotations(const uint8_t* value,
1404
uint16_t lane_mask,
1405
PrintRegisterFormat format) {
1406
VIXL_ASSERT((format & kPrintRegAsFP) != 0);
1407
int lane_size = GetPrintRegLaneSizeInBytes(format);
1408
fprintf(stream_, " (");
1409
bool last_inactive = false;
1410
const char* sep = "";
1411
for (int i = GetPrintRegLaneCount(format) - 1; i >= 0; i--, sep = ", ") {
1412
bool access = (lane_mask & (1 << (i * lane_size))) != 0;
1413
if (access) {
1414
// Read the lane as a double, so we can format all FP types in the same
1415
// way. We squash NaNs, and a double can exactly represent any other value
1416
// that the smaller types can represent, so this is lossless.
1417
double element;
1418
switch (lane_size) {
1419
case kHRegSizeInBytes: {
1420
Float16 element_fp16;
1421
VIXL_STATIC_ASSERT(sizeof(element_fp16) == kHRegSizeInBytes);
1422
memcpy(&element_fp16, &value[i * lane_size], sizeof(element_fp16));
1423
element = FPToDouble(element_fp16, kUseDefaultNaN);
1424
break;
1425
}
1426
case kSRegSizeInBytes: {
1427
float element_fp32;
1428
memcpy(&element_fp32, &value[i * lane_size], sizeof(element_fp32));
1429
element = static_cast<double>(element_fp32);
1430
break;
1431
}
1432
case kDRegSizeInBytes: {
1433
memcpy(&element, &value[i * lane_size], sizeof(element));
1434
break;
1435
}
1436
default:
1437
VIXL_UNREACHABLE();
1438
fprintf(stream_, "{UnknownFPValue}");
1439
continue;
1440
}
1441
if (IsNaN(element)) {
1442
// The fprintf behaviour for NaNs is implementation-defined. Always
1443
// print "nan", so that traces are consistent.
1444
fprintf(stream_, "%s%snan%s", sep, clr_vreg_value, clr_normal);
1445
} else {
1446
fprintf(stream_,
1447
"%s%s%#.4g%s",
1448
sep,
1449
clr_vreg_value,
1450
element,
1451
clr_normal);
1452
}
1453
last_inactive = false;
1454
} else if (!last_inactive) {
1455
// Replace each contiguous sequence of inactive lanes with "...".
1456
fprintf(stream_, "%s...", sep);
1457
last_inactive = true;
1458
}
1459
}
1460
fprintf(stream_, ")");
1461
}
1462
1463
void Simulator::PrintRegister(int code,
1464
PrintRegisterFormat format,
1465
const char* suffix) {
1466
VIXL_ASSERT((static_cast<unsigned>(code) < kNumberOfRegisters) ||
1467
(static_cast<unsigned>(code) == kSPRegInternalCode));
1468
VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsScalar);
1469
VIXL_ASSERT((format & kPrintRegAsFP) == 0);
1470
1471
SimRegister* reg;
1472
SimRegister zero;
1473
if (code == kZeroRegCode) {
1474
reg = &zero;
1475
} else {
1476
// registers_[31] holds the SP.
1477
VIXL_STATIC_ASSERT((kSPRegInternalCode % kNumberOfRegisters) == 31);
1478
reg = &registers_[code % kNumberOfRegisters];
1479
}
1480
1481
// We trace register writes as whole register values, implying that any
1482
// unprinted bits are all zero:
1483
// "# x{code}: 0x{-----value----}"
1484
// "# w{code}: 0x{-value}"
1485
// Stores trace partial register values, implying nothing about the unprinted
1486
// bits:
1487
// "# x{code}<63:0>: 0x{-----value----}"
1488
// "# x{code}<31:0>: 0x{-value}"
1489
// "# x{code}<15:0>: 0x{--}"
1490
// "# x{code}<7:0>: 0x{}"
1491
1492
bool is_partial = (format & kPrintRegPartial) != 0;
1493
unsigned print_reg_size = GetPrintRegSizeInBits(format);
1494
std::stringstream name;
1495
if (is_partial) {
1496
name << XRegNameForCode(code) << GetPartialRegSuffix(format);
1497
} else {
1498
// Notify the register that it has been logged, but only if we're printing
1499
// all of it.
1500
reg->NotifyRegisterLogged();
1501
switch (print_reg_size) {
1502
case kWRegSize:
1503
name << WRegNameForCode(code);
1504
break;
1505
case kXRegSize:
1506
name << XRegNameForCode(code);
1507
break;
1508
default:
1509
VIXL_UNREACHABLE();
1510
return;
1511
}
1512
}
1513
1514
fprintf(stream_,
1515
"# %s%*s: %s",
1516
clr_reg_name,
1517
kPrintRegisterNameFieldWidth,
1518
name.str().c_str(),
1519
clr_reg_value);
1520
PrintRegisterValue(*reg, format);
1521
fprintf(stream_, "%s%s", clr_normal, suffix);
1522
}
1523
1524
void Simulator::PrintVRegister(int code,
1525
PrintRegisterFormat format,
1526
const char* suffix) {
1527
VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfVRegisters);
1528
VIXL_ASSERT(((format & kPrintRegAsVectorMask) == kPrintRegAsScalar) ||
1529
((format & kPrintRegAsVectorMask) == kPrintRegAsDVector) ||
1530
((format & kPrintRegAsVectorMask) == kPrintRegAsQVector));
1531
1532
// We trace register writes as whole register values, implying that any
1533
// unprinted bits are all zero:
1534
// "# v{code}: 0x{-------------value------------}"
1535
// "# d{code}: 0x{-----value----}"
1536
// "# s{code}: 0x{-value}"
1537
// "# h{code}: 0x{--}"
1538
// "# b{code}: 0x{}"
1539
// Stores trace partial register values, implying nothing about the unprinted
1540
// bits:
1541
// "# v{code}<127:0>: 0x{-------------value------------}"
1542
// "# v{code}<63:0>: 0x{-----value----}"
1543
// "# v{code}<31:0>: 0x{-value}"
1544
// "# v{code}<15:0>: 0x{--}"
1545
// "# v{code}<7:0>: 0x{}"
1546
1547
bool is_partial = ((format & kPrintRegPartial) != 0);
1548
std::stringstream name;
1549
unsigned print_reg_size = GetPrintRegSizeInBits(format);
1550
if (is_partial) {
1551
name << VRegNameForCode(code) << GetPartialRegSuffix(format);
1552
} else {
1553
// Notify the register that it has been logged, but only if we're printing
1554
// all of it.
1555
vregisters_[code].NotifyRegisterLogged();
1556
switch (print_reg_size) {
1557
case kBRegSize:
1558
name << BRegNameForCode(code);
1559
break;
1560
case kHRegSize:
1561
name << HRegNameForCode(code);
1562
break;
1563
case kSRegSize:
1564
name << SRegNameForCode(code);
1565
break;
1566
case kDRegSize:
1567
name << DRegNameForCode(code);
1568
break;
1569
case kQRegSize:
1570
name << VRegNameForCode(code);
1571
break;
1572
default:
1573
VIXL_UNREACHABLE();
1574
return;
1575
}
1576
}
1577
1578
fprintf(stream_,
1579
"# %s%*s: %s",
1580
clr_vreg_name,
1581
kPrintRegisterNameFieldWidth,
1582
name.str().c_str(),
1583
clr_vreg_value);
1584
PrintRegisterValue(vregisters_[code], format);
1585
fprintf(stream_, "%s", clr_normal);
1586
if ((format & kPrintRegAsFP) != 0) {
1587
PrintRegisterValueFPAnnotations(vregisters_[code], format);
1588
}
1589
fprintf(stream_, "%s", suffix);
1590
}
1591
1592
void Simulator::PrintVRegistersForStructuredAccess(int rt_code,
1593
int reg_count,
1594
uint16_t focus_mask,
1595
PrintRegisterFormat format) {
1596
bool print_fp = (format & kPrintRegAsFP) != 0;
1597
// Suppress FP formatting, so we can specify the lanes we're interested in.
1598
PrintRegisterFormat format_no_fp =
1599
static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1600
1601
for (int r = 0; r < reg_count; r++) {
1602
int code = (rt_code + r) % kNumberOfVRegisters;
1603
PrintVRegister(code, format_no_fp, "");
1604
if (print_fp) {
1605
PrintRegisterValueFPAnnotations(vregisters_[code], focus_mask, format);
1606
}
1607
fprintf(stream_, "\n");
1608
}
1609
}
1610
1611
void Simulator::PrintZRegistersForStructuredAccess(int rt_code,
1612
int q_index,
1613
int reg_count,
1614
uint16_t focus_mask,
1615
PrintRegisterFormat format) {
1616
bool print_fp = (format & kPrintRegAsFP) != 0;
1617
// Suppress FP formatting, so we can specify the lanes we're interested in.
1618
PrintRegisterFormat format_no_fp =
1619
static_cast<PrintRegisterFormat>(format & ~kPrintRegAsFP);
1620
1621
PrintRegisterFormat format_q = GetPrintRegAsQChunkOfSVE(format);
1622
1623
const unsigned size = kQRegSizeInBytes;
1624
unsigned byte_index = q_index * size;
1625
const uint8_t* value = vregisters_[rt_code].GetBytes() + byte_index;
1626
VIXL_ASSERT((byte_index + size) <= vregisters_[rt_code].GetSizeInBytes());
1627
1628
for (int r = 0; r < reg_count; r++) {
1629
int code = (rt_code + r) % kNumberOfZRegisters;
1630
PrintPartialZRegister(code, q_index, format_no_fp, "");
1631
if (print_fp) {
1632
PrintRegisterValueFPAnnotations(value, focus_mask, format_q);
1633
}
1634
fprintf(stream_, "\n");
1635
}
1636
}
1637
1638
void Simulator::PrintZRegister(int code, PrintRegisterFormat format) {
1639
// We're going to print the register in parts, so force a partial format.
1640
format = GetPrintRegPartial(format);
1641
VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1642
int vl = GetVectorLengthInBits();
1643
VIXL_ASSERT((vl % kQRegSize) == 0);
1644
for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1645
PrintPartialZRegister(code, i, format);
1646
}
1647
vregisters_[code].NotifyRegisterLogged();
1648
}
1649
1650
void Simulator::PrintPRegister(int code, PrintRegisterFormat format) {
1651
// We're going to print the register in parts, so force a partial format.
1652
format = GetPrintRegPartial(format);
1653
VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1654
int vl = GetVectorLengthInBits();
1655
VIXL_ASSERT((vl % kQRegSize) == 0);
1656
for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1657
PrintPartialPRegister(code, i, format);
1658
}
1659
pregisters_[code].NotifyRegisterLogged();
1660
}
1661
1662
void Simulator::PrintFFR(PrintRegisterFormat format) {
1663
// We're going to print the register in parts, so force a partial format.
1664
format = GetPrintRegPartial(format);
1665
VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1666
int vl = GetVectorLengthInBits();
1667
VIXL_ASSERT((vl % kQRegSize) == 0);
1668
SimPRegister& ffr = ReadFFR();
1669
for (unsigned i = 0; i < (vl / kQRegSize); i++) {
1670
PrintPartialPRegister("FFR", ffr, i, format);
1671
}
1672
ffr.NotifyRegisterLogged();
1673
}
1674
1675
void Simulator::PrintPartialZRegister(int code,
1676
int q_index,
1677
PrintRegisterFormat format,
1678
const char* suffix) {
1679
VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfZRegisters);
1680
VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1681
VIXL_ASSERT((format & kPrintRegPartial) != 0);
1682
VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1683
1684
// We _only_ trace partial Z register values in Q-sized chunks, because
1685
// they're often too large to reasonably fit on a single line. Each line
1686
// implies nothing about the unprinted bits.
1687
// "# z{code}<127:0>: 0x{-------------value------------}"
1688
1689
format = GetPrintRegAsQChunkOfSVE(format);
1690
1691
const unsigned size = kQRegSizeInBytes;
1692
unsigned byte_index = q_index * size;
1693
const uint8_t* value = vregisters_[code].GetBytes() + byte_index;
1694
VIXL_ASSERT((byte_index + size) <= vregisters_[code].GetSizeInBytes());
1695
1696
int lsb = q_index * kQRegSize;
1697
int msb = lsb + kQRegSize - 1;
1698
std::stringstream name;
1699
name << ZRegNameForCode(code) << '<' << msb << ':' << lsb << '>';
1700
1701
fprintf(stream_,
1702
"# %s%*s: %s",
1703
clr_vreg_name,
1704
kPrintRegisterNameFieldWidth,
1705
name.str().c_str(),
1706
clr_vreg_value);
1707
PrintRegisterValue(value, size, format);
1708
fprintf(stream_, "%s", clr_normal);
1709
if ((format & kPrintRegAsFP) != 0) {
1710
PrintRegisterValueFPAnnotations(value, GetPrintRegLaneMask(format), format);
1711
}
1712
fprintf(stream_, "%s", suffix);
1713
}
1714
1715
void Simulator::PrintPartialPRegister(const char* name,
1716
const SimPRegister& reg,
1717
int q_index,
1718
PrintRegisterFormat format,
1719
const char* suffix) {
1720
VIXL_ASSERT((format & kPrintRegAsVectorMask) == kPrintRegAsSVEVector);
1721
VIXL_ASSERT((format & kPrintRegPartial) != 0);
1722
VIXL_ASSERT((q_index * kQRegSize) < GetVectorLengthInBits());
1723
1724
// We don't currently use the format for anything here.
1725
USE(format);
1726
1727
// We _only_ trace partial P register values, because they're often too large
1728
// to reasonably fit on a single line. Each line implies nothing about the
1729
// unprinted bits.
1730
//
1731
// We print values in binary, with spaces between each bit, in order for the
1732
// bits to align with the Z register bytes that they predicate.
1733
// "# {name}<15:0>: 0b{-------------value------------}"
1734
1735
int print_size_in_bits = kQRegSize / kZRegBitsPerPRegBit;
1736
int lsb = q_index * print_size_in_bits;
1737
int msb = lsb + print_size_in_bits - 1;
1738
std::stringstream prefix;
1739
prefix << name << '<' << msb << ':' << lsb << '>';
1740
1741
fprintf(stream_,
1742
"# %s%*s: %s0b",
1743
clr_preg_name,
1744
kPrintRegisterNameFieldWidth,
1745
prefix.str().c_str(),
1746
clr_preg_value);
1747
for (int i = msb; i >= lsb; i--) {
1748
fprintf(stream_, " %c", reg.GetBit(i) ? '1' : '0');
1749
}
1750
fprintf(stream_, "%s%s", clr_normal, suffix);
1751
}
1752
1753
void Simulator::PrintPartialPRegister(int code,
1754
int q_index,
1755
PrintRegisterFormat format,
1756
const char* suffix) {
1757
VIXL_ASSERT(static_cast<unsigned>(code) < kNumberOfPRegisters);
1758
PrintPartialPRegister(PRegNameForCode(code),
1759
pregisters_[code],
1760
q_index,
1761
format,
1762
suffix);
1763
}
1764
1765
void Simulator::PrintSystemRegister(SystemRegister id) {
1766
switch (id) {
1767
case NZCV:
1768
fprintf(stream_,
1769
"# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1770
clr_flag_name,
1771
clr_flag_value,
1772
ReadNzcv().GetN(),
1773
ReadNzcv().GetZ(),
1774
ReadNzcv().GetC(),
1775
ReadNzcv().GetV(),
1776
clr_normal);
1777
break;
1778
case FPCR: {
1779
static const char* rmode[] = {"0b00 (Round to Nearest)",
1780
"0b01 (Round towards Plus Infinity)",
1781
"0b10 (Round towards Minus Infinity)",
1782
"0b11 (Round towards Zero)"};
1783
VIXL_ASSERT(ReadFpcr().GetRMode() < ArrayLength(rmode));
1784
fprintf(stream_,
1785
"# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1786
clr_flag_name,
1787
clr_flag_value,
1788
ReadFpcr().GetAHP(),
1789
ReadFpcr().GetDN(),
1790
ReadFpcr().GetFZ(),
1791
rmode[ReadFpcr().GetRMode()],
1792
clr_normal);
1793
break;
1794
}
1795
default:
1796
VIXL_UNREACHABLE();
1797
}
1798
}
1799
1800
uint16_t Simulator::PrintPartialAccess(uint16_t access_mask,
1801
uint16_t future_access_mask,
1802
int struct_element_count,
1803
int lane_size_in_bytes,
1804
const char* op,
1805
uintptr_t address,
1806
int reg_size_in_bytes) {
1807
// We want to assume that we'll access at least one lane.
1808
VIXL_ASSERT(access_mask != 0);
1809
VIXL_ASSERT((reg_size_in_bytes == kXRegSizeInBytes) ||
1810
(reg_size_in_bytes == kQRegSizeInBytes));
1811
bool started_annotation = false;
1812
// Indent to match the register field, the fixed formatting, and the value
1813
// prefix ("0x"): "# {name}: 0x"
1814
fprintf(stream_, "# %*s ", kPrintRegisterNameFieldWidth, "");
1815
// First, annotate the lanes (byte by byte).
1816
for (int lane = reg_size_in_bytes - 1; lane >= 0; lane--) {
1817
bool access = (access_mask & (1 << lane)) != 0;
1818
bool future = (future_access_mask & (1 << lane)) != 0;
1819
if (started_annotation) {
1820
// If we've started an annotation, draw a horizontal line in addition to
1821
// any other symbols.
1822
if (access) {
1823
fprintf(stream_, "─╨");
1824
} else if (future) {
1825
fprintf(stream_, "─║");
1826
} else {
1827
fprintf(stream_, "──");
1828
}
1829
} else {
1830
if (access) {
1831
started_annotation = true;
1832
fprintf(stream_, " â•™");
1833
} else if (future) {
1834
fprintf(stream_, " â•‘");
1835
} else {
1836
fprintf(stream_, " ");
1837
}
1838
}
1839
}
1840
VIXL_ASSERT(started_annotation);
1841
fprintf(stream_, "─ 0x");
1842
int lane_size_in_nibbles = lane_size_in_bytes * 2;
1843
// Print the most-significant struct element first.
1844
const char* sep = "";
1845
for (int i = struct_element_count - 1; i >= 0; i--) {
1846
int offset = lane_size_in_bytes * i;
1847
auto nibble = MemReadUint(lane_size_in_bytes, address + offset);
1848
VIXL_ASSERT(nibble);
1849
fprintf(stream_, "%s%0*" PRIx64, sep, lane_size_in_nibbles, *nibble);
1850
sep = "'";
1851
}
1852
fprintf(stream_,
1853
" %s %s0x%016" PRIxPTR "%s\n",
1854
op,
1855
clr_memory_address,
1856
address,
1857
clr_normal);
1858
return future_access_mask & ~access_mask;
1859
}
1860
1861
void Simulator::PrintAccess(int code,
1862
PrintRegisterFormat format,
1863
const char* op,
1864
uintptr_t address) {
1865
VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
1866
VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1867
if ((format & kPrintRegPartial) == 0) {
1868
if (code != kZeroRegCode) {
1869
registers_[code].NotifyRegisterLogged();
1870
}
1871
}
1872
// Scalar-format accesses use a simple format:
1873
// "# {reg}: 0x{value} -> {address}"
1874
1875
// Suppress the newline, so the access annotation goes on the same line.
1876
PrintRegister(code, format, "");
1877
fprintf(stream_,
1878
" %s %s0x%016" PRIxPTR "%s\n",
1879
op,
1880
clr_memory_address,
1881
address,
1882
clr_normal);
1883
}
1884
1885
void Simulator::PrintVAccess(int code,
1886
PrintRegisterFormat format,
1887
const char* op,
1888
uintptr_t address) {
1889
VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1890
1891
// Scalar-format accesses use a simple format:
1892
// "# v{code}: 0x{value} -> {address}"
1893
1894
// Suppress the newline, so the access annotation goes on the same line.
1895
PrintVRegister(code, format, "");
1896
fprintf(stream_,
1897
" %s %s0x%016" PRIxPTR "%s\n",
1898
op,
1899
clr_memory_address,
1900
address,
1901
clr_normal);
1902
}
1903
1904
void Simulator::PrintVStructAccess(int rt_code,
1905
int reg_count,
1906
PrintRegisterFormat format,
1907
const char* op,
1908
uintptr_t address) {
1909
VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1910
1911
// For example:
1912
// "# v{code}: 0x{value}"
1913
// "# ...: 0x{value}"
1914
// "# ║ ╙─ {struct_value} -> {lowest_address}"
1915
// "# ╙───── {struct_value} -> {highest_address}"
1916
1917
uint16_t lane_mask = GetPrintRegLaneMask(format);
1918
PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1919
1920
int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
1921
int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1922
for (int i = 0; i < reg_size_in_bytes; i += lane_size_in_bytes) {
1923
uint16_t access_mask = 1 << i;
1924
VIXL_ASSERT((lane_mask & access_mask) != 0);
1925
lane_mask = PrintPartialAccess(access_mask,
1926
lane_mask,
1927
reg_count,
1928
lane_size_in_bytes,
1929
op,
1930
address + (i * reg_count));
1931
}
1932
}
1933
1934
void Simulator::PrintVSingleStructAccess(int rt_code,
1935
int reg_count,
1936
int lane,
1937
PrintRegisterFormat format,
1938
const char* op,
1939
uintptr_t address) {
1940
VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1941
1942
// For example:
1943
// "# v{code}: 0x{value}"
1944
// "# ...: 0x{value}"
1945
// "# ╙───── {struct_value} -> {address}"
1946
1947
int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1948
uint16_t lane_mask = 1 << (lane * lane_size_in_bytes);
1949
PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1950
PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1951
}
1952
1953
void Simulator::PrintVReplicatingStructAccess(int rt_code,
1954
int reg_count,
1955
PrintRegisterFormat format,
1956
const char* op,
1957
uintptr_t address) {
1958
VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1959
1960
// For example:
1961
// "# v{code}: 0x{value}"
1962
// "# ...: 0x{value}"
1963
// "# ╙─╨─╨─╨─ {struct_value} -> {address}"
1964
1965
int lane_size_in_bytes = GetPrintRegLaneSizeInBytes(format);
1966
uint16_t lane_mask = GetPrintRegLaneMask(format);
1967
PrintVRegistersForStructuredAccess(rt_code, reg_count, lane_mask, format);
1968
PrintPartialAccess(lane_mask, 0, reg_count, lane_size_in_bytes, op, address);
1969
}
1970
1971
void Simulator::PrintZAccess(int rt_code, const char* op, uintptr_t address) {
1972
VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
1973
1974
// Scalar-format accesses are split into separate chunks, each of which uses a
1975
// simple format:
1976
// "# z{code}<127:0>: 0x{value} -> {address}"
1977
// "# z{code}<255:128>: 0x{value} -> {address + 16}"
1978
// "# z{code}<383:256>: 0x{value} -> {address + 32}"
1979
// etc
1980
1981
int vl = GetVectorLengthInBits();
1982
VIXL_ASSERT((vl % kQRegSize) == 0);
1983
for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
1984
// Suppress the newline, so the access annotation goes on the same line.
1985
PrintPartialZRegister(rt_code, q_index, kPrintRegVnQPartial, "");
1986
fprintf(stream_,
1987
" %s %s0x%016" PRIxPTR "%s\n",
1988
op,
1989
clr_memory_address,
1990
address,
1991
clr_normal);
1992
address += kQRegSizeInBytes;
1993
}
1994
}
1995
1996
void Simulator::PrintZStructAccess(int rt_code,
1997
int reg_count,
1998
const LogicPRegister& pg,
1999
PrintRegisterFormat format,
2000
int msize_in_bytes,
2001
const char* op,
2002
const LogicSVEAddressVector& addr) {
2003
VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
2004
2005
// For example:
2006
// "# z{code}<255:128>: 0x{value}"
2007
// "# ...<255:128>: 0x{value}"
2008
// "# ║ ╙─ {struct_value} -> {first_address}"
2009
// "# ╙───── {struct_value} -> {last_address}"
2010
2011
// We're going to print the register in parts, so force a partial format.
2012
bool skip_inactive_chunks = (format & kPrintRegPartial) != 0;
2013
format = GetPrintRegPartial(format);
2014
2015
int esize_in_bytes = GetPrintRegLaneSizeInBytes(format);
2016
int vl = GetVectorLengthInBits();
2017
VIXL_ASSERT((vl % kQRegSize) == 0);
2018
int lanes_per_q = kQRegSizeInBytes / esize_in_bytes;
2019
for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
2020
uint16_t pred =
2021
pg.GetActiveMask<uint16_t>(q_index) & GetPrintRegLaneMask(format);
2022
if ((pred == 0) && skip_inactive_chunks) continue;
2023
2024
PrintZRegistersForStructuredAccess(rt_code,
2025
q_index,
2026
reg_count,
2027
pred,
2028
format);
2029
if (pred == 0) {
2030
// This register chunk has no active lanes. The loop below would print
2031
// nothing, so leave a blank line to keep structures grouped together.
2032
fprintf(stream_, "#\n");
2033
continue;
2034
}
2035
for (int i = 0; i < lanes_per_q; i++) {
2036
uint16_t access = 1 << (i * esize_in_bytes);
2037
int lane = (q_index * lanes_per_q) + i;
2038
// Skip inactive lanes.
2039
if ((pred & access) == 0) continue;
2040
pred = PrintPartialAccess(access,
2041
pred,
2042
reg_count,
2043
msize_in_bytes,
2044
op,
2045
addr.GetStructAddress(lane));
2046
}
2047
}
2048
2049
// We print the whole register, even for stores.
2050
for (int i = 0; i < reg_count; i++) {
2051
vregisters_[(rt_code + i) % kNumberOfZRegisters].NotifyRegisterLogged();
2052
}
2053
}
2054
2055
void Simulator::PrintPAccess(int code, const char* op, uintptr_t address) {
2056
VIXL_ASSERT((strcmp(op, "->") == 0) || (strcmp(op, "<-") == 0));
2057
2058
// Scalar-format accesses are split into separate chunks, each of which uses a
2059
// simple format:
2060
// "# p{code}<15:0>: 0b{value} -> {address}"
2061
// "# p{code}<31:16>: 0b{value} -> {address + 2}"
2062
// "# p{code}<47:32>: 0b{value} -> {address + 4}"
2063
// etc
2064
2065
int vl = GetVectorLengthInBits();
2066
VIXL_ASSERT((vl % kQRegSize) == 0);
2067
for (unsigned q_index = 0; q_index < (vl / kQRegSize); q_index++) {
2068
// Suppress the newline, so the access annotation goes on the same line.
2069
PrintPartialPRegister(code, q_index, kPrintRegVnQPartial, "");
2070
fprintf(stream_,
2071
" %s %s0x%016" PRIxPTR "%s\n",
2072
op,
2073
clr_memory_address,
2074
address,
2075
clr_normal);
2076
address += kQRegSizeInBytes;
2077
}
2078
}
2079
2080
void Simulator::PrintMemTransfer(uintptr_t dst, uintptr_t src, uint8_t value) {
2081
fprintf(stream_,
2082
"# %s: %s0x%016" PRIxPTR " %s<- %s0x%02x%s",
2083
clr_reg_name,
2084
clr_memory_address,
2085
dst,
2086
clr_normal,
2087
clr_reg_value,
2088
value,
2089
clr_normal);
2090
2091
fprintf(stream_,
2092
" <- %s0x%016" PRIxPTR "%s\n",
2093
clr_memory_address,
2094
src,
2095
clr_normal);
2096
}
2097
2098
void Simulator::PrintRead(int rt_code,
2099
PrintRegisterFormat format,
2100
uintptr_t address) {
2101
VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
2102
if (rt_code != kZeroRegCode) {
2103
registers_[rt_code].NotifyRegisterLogged();
2104
}
2105
PrintAccess(rt_code, format, "<-", address);
2106
}
2107
2108
void Simulator::PrintExtendingRead(int rt_code,
2109
PrintRegisterFormat format,
2110
int access_size_in_bytes,
2111
uintptr_t address) {
2112
int reg_size_in_bytes = GetPrintRegSizeInBytes(format);
2113
if (access_size_in_bytes == reg_size_in_bytes) {
2114
// There is no extension here, so print a simple load.
2115
PrintRead(rt_code, format, address);
2116
return;
2117
}
2118
VIXL_ASSERT(access_size_in_bytes < reg_size_in_bytes);
2119
2120
// For sign- and zero-extension, make it clear that the resulting register
2121
// value is different from what is loaded from memory.
2122
VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
2123
if (rt_code != kZeroRegCode) {
2124
registers_[rt_code].NotifyRegisterLogged();
2125
}
2126
PrintRegister(rt_code, format);
2127
PrintPartialAccess(1,
2128
0,
2129
1,
2130
access_size_in_bytes,
2131
"<-",
2132
address,
2133
kXRegSizeInBytes);
2134
}
2135
2136
void Simulator::PrintVRead(int rt_code,
2137
PrintRegisterFormat format,
2138
uintptr_t address) {
2139
VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
2140
vregisters_[rt_code].NotifyRegisterLogged();
2141
PrintVAccess(rt_code, format, "<-", address);
2142
}
2143
2144
void Simulator::PrintWrite(int rt_code,
2145
PrintRegisterFormat format,
2146
uintptr_t address) {
2147
// Because this trace doesn't represent a change to the source register's
2148
// value, only print the relevant part of the value.
2149
format = GetPrintRegPartial(format);
2150
VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
2151
if (rt_code != kZeroRegCode) {
2152
registers_[rt_code].NotifyRegisterLogged();
2153
}
2154
PrintAccess(rt_code, format, "->", address);
2155
}
2156
2157
void Simulator::PrintVWrite(int rt_code,
2158
PrintRegisterFormat format,
2159
uintptr_t address) {
2160
// Because this trace doesn't represent a change to the source register's
2161
// value, only print the relevant part of the value.
2162
format = GetPrintRegPartial(format);
2163
// It only makes sense to write scalar values here. Vectors are handled by
2164
// PrintVStructAccess.
2165
VIXL_ASSERT(GetPrintRegLaneCount(format) == 1);
2166
PrintVAccess(rt_code, format, "->", address);
2167
}
2168
2169
void Simulator::PrintTakenBranch(const Instruction* target) {
2170
fprintf(stream_,
2171
"# %sBranch%s to 0x%016" PRIx64 ".\n",
2172
clr_branch_marker,
2173
clr_normal,
2174
reinterpret_cast<uint64_t>(target));
2175
}
2176
2177
// Visitors---------------------------------------------------------------------
2178
2179
2180
void Simulator::Visit(Metadata* metadata, const Instruction* instr) {
2181
VIXL_ASSERT(metadata->count("form") > 0);
2182
std::string form = (*metadata)["form"];
2183
form_hash_ = Hash(form.c_str());
2184
const FormToVisitorFnMap* fv = Simulator::GetFormToVisitorFnMap();
2185
FormToVisitorFnMap::const_iterator it = fv->find(form_hash_);
2186
if (it == fv->end()) {
2187
VisitUnimplemented(instr);
2188
} else {
2189
(it->second)(this, instr);
2190
}
2191
}
2192
2193
void Simulator::Simulate_PdT_PgZ_ZnT_ZmT(const Instruction* instr) {
2194
VectorFormat vform = instr->GetSVEVectorFormat();
2195
SimPRegister& pd = ReadPRegister(instr->GetPd());
2196
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2197
SimVRegister& zm = ReadVRegister(instr->GetRm());
2198
SimVRegister& zn = ReadVRegister(instr->GetRn());
2199
2200
switch (form_hash_) {
2201
case "match_p_p_zz"_h:
2202
match(vform, pd, zn, zm, /* negate_match = */ false);
2203
break;
2204
case "nmatch_p_p_zz"_h:
2205
match(vform, pd, zn, zm, /* negate_match = */ true);
2206
break;
2207
default:
2208
VIXL_UNIMPLEMENTED();
2209
}
2210
mov_zeroing(pd, pg, pd);
2211
PredTest(vform, pg, pd);
2212
}
2213
2214
void Simulator::Simulate_PdT_Xn_Xm(const Instruction* instr) {
2215
VectorFormat vform = instr->GetSVEVectorFormat();
2216
SimPRegister& pd = ReadPRegister(instr->GetPd());
2217
uint64_t src1 = ReadXRegister(instr->GetRn());
2218
uint64_t src2 = ReadXRegister(instr->GetRm());
2219
2220
uint64_t absdiff = (src1 > src2) ? (src1 - src2) : (src2 - src1);
2221
absdiff >>= LaneSizeInBytesLog2FromFormat(vform);
2222
2223
bool no_conflict = false;
2224
switch (form_hash_) {
2225
case "whilerw_p_rr"_h:
2226
no_conflict = (absdiff == 0);
2227
break;
2228
case "whilewr_p_rr"_h:
2229
no_conflict = (absdiff == 0) || (src2 <= src1);
2230
break;
2231
default:
2232
VIXL_UNIMPLEMENTED();
2233
}
2234
2235
LogicPRegister dst(pd);
2236
for (int i = 0; i < LaneCountFromFormat(vform); i++) {
2237
dst.SetActive(vform,
2238
i,
2239
no_conflict || (static_cast<uint64_t>(i) < absdiff));
2240
}
2241
2242
PredTest(vform, GetPTrue(), pd);
2243
}
2244
2245
void Simulator::Simulate_ZdB_Zn1B_Zn2B_imm(const Instruction* instr) {
2246
VIXL_ASSERT(form_hash_ == "ext_z_zi_con"_h);
2247
2248
SimVRegister& zd = ReadVRegister(instr->GetRd());
2249
SimVRegister& zn = ReadVRegister(instr->GetRn());
2250
SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
2251
2252
int index = instr->GetSVEExtractImmediate();
2253
int vl = GetVectorLengthInBytes();
2254
index = (index >= vl) ? 0 : index;
2255
2256
ext(kFormatVnB, zd, zn, zn2, index);
2257
}
2258
2259
void Simulator::Simulate_ZdB_ZnB_ZmB(const Instruction* instr) {
2260
SimVRegister& zd = ReadVRegister(instr->GetRd());
2261
SimVRegister& zm = ReadVRegister(instr->GetRm());
2262
SimVRegister& zn = ReadVRegister(instr->GetRn());
2263
2264
switch (form_hash_) {
2265
case "histseg_z_zz"_h:
2266
if (instr->GetSVEVectorFormat() == kFormatVnB) {
2267
histogram(kFormatVnB,
2268
zd,
2269
GetPTrue(),
2270
zn,
2271
zm,
2272
/* do_segmented = */ true);
2273
} else {
2274
VIXL_UNIMPLEMENTED();
2275
}
2276
break;
2277
case "pmul_z_zz"_h:
2278
pmul(kFormatVnB, zd, zn, zm);
2279
break;
2280
default:
2281
VIXL_UNIMPLEMENTED();
2282
}
2283
}
2284
2285
void Simulator::SimulateSVEMulIndex(const Instruction* instr) {
2286
VectorFormat vform = instr->GetSVEVectorFormat();
2287
SimVRegister& zd = ReadVRegister(instr->GetRd());
2288
SimVRegister& zn = ReadVRegister(instr->GetRn());
2289
2290
// The encoding for B and H-sized lanes are redefined to encode the most
2291
// significant bit of index for H-sized lanes. B-sized lanes are not
2292
// supported.
2293
if (vform == kFormatVnB) vform = kFormatVnH;
2294
2295
VIXL_ASSERT((form_hash_ == "mul_z_zzi_d"_h) ||
2296
(form_hash_ == "mul_z_zzi_h"_h) ||
2297
(form_hash_ == "mul_z_zzi_s"_h));
2298
2299
SimVRegister temp;
2300
dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2301
mul(vform, zd, zn, temp);
2302
}
2303
2304
void Simulator::SimulateSVEMlaMlsIndex(const Instruction* instr) {
2305
VectorFormat vform = instr->GetSVEVectorFormat();
2306
SimVRegister& zda = ReadVRegister(instr->GetRd());
2307
SimVRegister& zn = ReadVRegister(instr->GetRn());
2308
2309
// The encoding for B and H-sized lanes are redefined to encode the most
2310
// significant bit of index for H-sized lanes. B-sized lanes are not
2311
// supported.
2312
if (vform == kFormatVnB) vform = kFormatVnH;
2313
2314
VIXL_ASSERT(
2315
(form_hash_ == "mla_z_zzzi_d"_h) || (form_hash_ == "mla_z_zzzi_h"_h) ||
2316
(form_hash_ == "mla_z_zzzi_s"_h) || (form_hash_ == "mls_z_zzzi_d"_h) ||
2317
(form_hash_ == "mls_z_zzzi_h"_h) || (form_hash_ == "mls_z_zzzi_s"_h));
2318
2319
SimVRegister temp;
2320
dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2321
if (instr->ExtractBit(10) == 0) {
2322
mla(vform, zda, zda, zn, temp);
2323
} else {
2324
mls(vform, zda, zda, zn, temp);
2325
}
2326
}
2327
2328
void Simulator::SimulateSVESaturatingMulHighIndex(const Instruction* instr) {
2329
VectorFormat vform = instr->GetSVEVectorFormat();
2330
SimVRegister& zd = ReadVRegister(instr->GetRd());
2331
SimVRegister& zn = ReadVRegister(instr->GetRn());
2332
2333
// The encoding for B and H-sized lanes are redefined to encode the most
2334
// significant bit of index for H-sized lanes. B-sized lanes are not
2335
// supported.
2336
if (vform == kFormatVnB) {
2337
vform = kFormatVnH;
2338
}
2339
2340
SimVRegister temp;
2341
dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
2342
switch (form_hash_) {
2343
case "sqdmulh_z_zzi_h"_h:
2344
case "sqdmulh_z_zzi_s"_h:
2345
case "sqdmulh_z_zzi_d"_h:
2346
sqdmulh(vform, zd, zn, temp);
2347
break;
2348
case "sqrdmulh_z_zzi_h"_h:
2349
case "sqrdmulh_z_zzi_s"_h:
2350
case "sqrdmulh_z_zzi_d"_h:
2351
sqrdmulh(vform, zd, zn, temp);
2352
break;
2353
default:
2354
VIXL_UNIMPLEMENTED();
2355
}
2356
}
2357
2358
void Simulator::SimulateSVESaturatingIntMulLongIdx(const Instruction* instr) {
2359
VectorFormat vform = instr->GetSVEVectorFormat();
2360
SimVRegister& zd = ReadVRegister(instr->GetRd());
2361
SimVRegister& zn = ReadVRegister(instr->GetRn());
2362
2363
SimVRegister temp, zm_idx, zn_b, zn_t;
2364
// Instead of calling the indexed form of the instruction logic, we call the
2365
// vector form, which can reuse existing function logic without modification.
2366
// Select the specified elements based on the index input and than pack them
2367
// to the corresponding position.
2368
VectorFormat vform_half = VectorFormatHalfWidth(vform);
2369
dup_elements_to_segments(vform_half, temp, instr->GetSVEMulLongZmAndIndex());
2370
pack_even_elements(vform_half, zm_idx, temp);
2371
2372
pack_even_elements(vform_half, zn_b, zn);
2373
pack_odd_elements(vform_half, zn_t, zn);
2374
2375
switch (form_hash_) {
2376
case "smullb_z_zzi_s"_h:
2377
case "smullb_z_zzi_d"_h:
2378
smull(vform, zd, zn_b, zm_idx);
2379
break;
2380
case "smullt_z_zzi_s"_h:
2381
case "smullt_z_zzi_d"_h:
2382
smull(vform, zd, zn_t, zm_idx);
2383
break;
2384
case "sqdmullb_z_zzi_d"_h:
2385
sqdmull(vform, zd, zn_b, zm_idx);
2386
break;
2387
case "sqdmullt_z_zzi_d"_h:
2388
sqdmull(vform, zd, zn_t, zm_idx);
2389
break;
2390
case "umullb_z_zzi_s"_h:
2391
case "umullb_z_zzi_d"_h:
2392
umull(vform, zd, zn_b, zm_idx);
2393
break;
2394
case "umullt_z_zzi_s"_h:
2395
case "umullt_z_zzi_d"_h:
2396
umull(vform, zd, zn_t, zm_idx);
2397
break;
2398
case "sqdmullb_z_zzi_s"_h:
2399
sqdmull(vform, zd, zn_b, zm_idx);
2400
break;
2401
case "sqdmullt_z_zzi_s"_h:
2402
sqdmull(vform, zd, zn_t, zm_idx);
2403
break;
2404
case "smlalb_z_zzzi_s"_h:
2405
case "smlalb_z_zzzi_d"_h:
2406
smlal(vform, zd, zn_b, zm_idx);
2407
break;
2408
case "smlalt_z_zzzi_s"_h:
2409
case "smlalt_z_zzzi_d"_h:
2410
smlal(vform, zd, zn_t, zm_idx);
2411
break;
2412
case "smlslb_z_zzzi_s"_h:
2413
case "smlslb_z_zzzi_d"_h:
2414
smlsl(vform, zd, zn_b, zm_idx);
2415
break;
2416
case "smlslt_z_zzzi_s"_h:
2417
case "smlslt_z_zzzi_d"_h:
2418
smlsl(vform, zd, zn_t, zm_idx);
2419
break;
2420
case "umlalb_z_zzzi_s"_h:
2421
case "umlalb_z_zzzi_d"_h:
2422
umlal(vform, zd, zn_b, zm_idx);
2423
break;
2424
case "umlalt_z_zzzi_s"_h:
2425
case "umlalt_z_zzzi_d"_h:
2426
umlal(vform, zd, zn_t, zm_idx);
2427
break;
2428
case "umlslb_z_zzzi_s"_h:
2429
case "umlslb_z_zzzi_d"_h:
2430
umlsl(vform, zd, zn_b, zm_idx);
2431
break;
2432
case "umlslt_z_zzzi_s"_h:
2433
case "umlslt_z_zzzi_d"_h:
2434
umlsl(vform, zd, zn_t, zm_idx);
2435
break;
2436
default:
2437
VIXL_UNIMPLEMENTED();
2438
}
2439
}
2440
2441
void Simulator::Simulate_ZdH_PgM_ZnS(const Instruction* instr) {
2442
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2443
SimVRegister& zd = ReadVRegister(instr->GetRd());
2444
SimVRegister& zn = ReadVRegister(instr->GetRn());
2445
SimVRegister result, zd_b;
2446
2447
pack_even_elements(kFormatVnH, zd_b, zd);
2448
2449
switch (form_hash_) {
2450
case "fcvtnt_z_p_z_s2h"_h:
2451
fcvt(kFormatVnH, kFormatVnS, result, pg, zn);
2452
pack_even_elements(kFormatVnH, result, result);
2453
zip1(kFormatVnH, result, zd_b, result);
2454
break;
2455
default:
2456
VIXL_UNIMPLEMENTED();
2457
}
2458
mov_merging(kFormatVnS, zd, pg, result);
2459
}
2460
2461
void Simulator::Simulate_ZdS_PgM_ZnD(const Instruction* instr) {
2462
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2463
SimVRegister& zd = ReadVRegister(instr->GetRd());
2464
SimVRegister& zn = ReadVRegister(instr->GetRn());
2465
SimVRegister result, zero, zd_b;
2466
2467
zero.Clear();
2468
pack_even_elements(kFormatVnS, zd_b, zd);
2469
2470
switch (form_hash_) {
2471
case "fcvtnt_z_p_z_d2s"_h:
2472
fcvt(kFormatVnS, kFormatVnD, result, pg, zn);
2473
pack_even_elements(kFormatVnS, result, result);
2474
zip1(kFormatVnS, result, zd_b, result);
2475
break;
2476
case "fcvtx_z_p_z_d2s"_h:
2477
fcvtxn(kFormatVnS, result, zn);
2478
zip1(kFormatVnS, result, result, zero);
2479
break;
2480
case "fcvtxnt_z_p_z_d2s"_h:
2481
fcvtxn(kFormatVnS, result, zn);
2482
zip1(kFormatVnS, result, zd_b, result);
2483
break;
2484
default:
2485
VIXL_UNIMPLEMENTED();
2486
}
2487
mov_merging(kFormatVnD, zd, pg, result);
2488
}
2489
2490
void Simulator::SimulateSVEFPConvertLong(const Instruction* instr) {
2491
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2492
SimVRegister& zd = ReadVRegister(instr->GetRd());
2493
SimVRegister& zn = ReadVRegister(instr->GetRn());
2494
SimVRegister result;
2495
2496
switch (form_hash_) {
2497
case "fcvtlt_z_p_z_h2s"_h:
2498
ext(kFormatVnB, result, zn, zn, kHRegSizeInBytes);
2499
fcvt(kFormatVnS, kFormatVnH, zd, pg, result);
2500
break;
2501
case "fcvtlt_z_p_z_s2d"_h:
2502
ext(kFormatVnB, result, zn, zn, kSRegSizeInBytes);
2503
fcvt(kFormatVnD, kFormatVnS, zd, pg, result);
2504
break;
2505
default:
2506
VIXL_UNIMPLEMENTED();
2507
}
2508
}
2509
2510
void Simulator::Simulate_ZdS_PgM_ZnS(const Instruction* instr) {
2511
VectorFormat vform = instr->GetSVEVectorFormat();
2512
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2513
SimVRegister& zd = ReadVRegister(instr->GetRd());
2514
SimVRegister& zn = ReadVRegister(instr->GetRn());
2515
SimVRegister result;
2516
2517
if (vform != kFormatVnS) {
2518
VIXL_UNIMPLEMENTED();
2519
}
2520
2521
switch (form_hash_) {
2522
case "urecpe_z_p_z"_h:
2523
urecpe(vform, result, zn);
2524
break;
2525
case "ursqrte_z_p_z"_h:
2526
ursqrte(vform, result, zn);
2527
break;
2528
default:
2529
VIXL_UNIMPLEMENTED();
2530
}
2531
mov_merging(vform, zd, pg, result);
2532
}
2533
2534
void Simulator::Simulate_ZdT_PgM_ZnT(const Instruction* instr) {
2535
VectorFormat vform = instr->GetSVEVectorFormat();
2536
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2537
SimVRegister& zd = ReadVRegister(instr->GetRd());
2538
SimVRegister& zn = ReadVRegister(instr->GetRn());
2539
SimVRegister result;
2540
2541
switch (form_hash_) {
2542
case "flogb_z_p_z"_h:
2543
vform = instr->GetSVEVectorFormat(17);
2544
flogb(vform, result, zn);
2545
break;
2546
case "sqabs_z_p_z"_h:
2547
abs(vform, result, zn).SignedSaturate(vform);
2548
break;
2549
case "sqneg_z_p_z"_h:
2550
neg(vform, result, zn).SignedSaturate(vform);
2551
break;
2552
default:
2553
VIXL_UNIMPLEMENTED();
2554
}
2555
mov_merging(vform, zd, pg, result);
2556
}
2557
2558
void Simulator::Simulate_ZdT_PgZ_ZnT_ZmT(const Instruction* instr) {
2559
VectorFormat vform = instr->GetSVEVectorFormat();
2560
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
2561
SimVRegister& zd = ReadVRegister(instr->GetRd());
2562
SimVRegister& zm = ReadVRegister(instr->GetRm());
2563
SimVRegister& zn = ReadVRegister(instr->GetRn());
2564
SimVRegister result;
2565
2566
VIXL_ASSERT(form_hash_ == "histcnt_z_p_zz"_h);
2567
if ((vform == kFormatVnS) || (vform == kFormatVnD)) {
2568
histogram(vform, result, pg, zn, zm);
2569
mov_zeroing(vform, zd, pg, result);
2570
} else {
2571
VIXL_UNIMPLEMENTED();
2572
}
2573
}
2574
2575
void Simulator::Simulate_ZdT_ZnT_ZmT(const Instruction* instr) {
2576
VectorFormat vform = instr->GetSVEVectorFormat();
2577
SimVRegister& zd = ReadVRegister(instr->GetRd());
2578
SimVRegister& zm = ReadVRegister(instr->GetRm());
2579
SimVRegister& zn = ReadVRegister(instr->GetRn());
2580
SimVRegister result;
2581
bool do_bext = false;
2582
2583
switch (form_hash_) {
2584
case "bdep_z_zz"_h:
2585
bdep(vform, zd, zn, zm);
2586
break;
2587
case "bext_z_zz"_h:
2588
do_bext = true;
2589
VIXL_FALLTHROUGH();
2590
case "bgrp_z_zz"_h:
2591
bgrp(vform, zd, zn, zm, do_bext);
2592
break;
2593
case "eorbt_z_zz"_h:
2594
rotate_elements_right(vform, result, zm, 1);
2595
SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2596
mov_alternating(vform, zd, result, 0);
2597
break;
2598
case "eortb_z_zz"_h:
2599
rotate_elements_right(vform, result, zm, -1);
2600
SVEBitwiseLogicalUnpredicatedHelper(EOR, kFormatVnD, result, zn, result);
2601
mov_alternating(vform, zd, result, 1);
2602
break;
2603
case "mul_z_zz"_h:
2604
mul(vform, zd, zn, zm);
2605
break;
2606
case "smulh_z_zz"_h:
2607
smulh(vform, zd, zn, zm);
2608
break;
2609
case "sqdmulh_z_zz"_h:
2610
sqdmulh(vform, zd, zn, zm);
2611
break;
2612
case "sqrdmulh_z_zz"_h:
2613
sqrdmulh(vform, zd, zn, zm);
2614
break;
2615
case "umulh_z_zz"_h:
2616
umulh(vform, zd, zn, zm);
2617
break;
2618
default:
2619
VIXL_UNIMPLEMENTED();
2620
}
2621
}
2622
2623
void Simulator::Simulate_ZdT_ZnT_ZmTb(const Instruction* instr) {
2624
VectorFormat vform = instr->GetSVEVectorFormat();
2625
SimVRegister& zd = ReadVRegister(instr->GetRd());
2626
SimVRegister& zm = ReadVRegister(instr->GetRm());
2627
SimVRegister& zn = ReadVRegister(instr->GetRn());
2628
2629
SimVRegister zm_b, zm_t;
2630
VectorFormat vform_half = VectorFormatHalfWidth(vform);
2631
pack_even_elements(vform_half, zm_b, zm);
2632
pack_odd_elements(vform_half, zm_t, zm);
2633
2634
switch (form_hash_) {
2635
case "saddwb_z_zz"_h:
2636
saddw(vform, zd, zn, zm_b);
2637
break;
2638
case "saddwt_z_zz"_h:
2639
saddw(vform, zd, zn, zm_t);
2640
break;
2641
case "ssubwb_z_zz"_h:
2642
ssubw(vform, zd, zn, zm_b);
2643
break;
2644
case "ssubwt_z_zz"_h:
2645
ssubw(vform, zd, zn, zm_t);
2646
break;
2647
case "uaddwb_z_zz"_h:
2648
uaddw(vform, zd, zn, zm_b);
2649
break;
2650
case "uaddwt_z_zz"_h:
2651
uaddw(vform, zd, zn, zm_t);
2652
break;
2653
case "usubwb_z_zz"_h:
2654
usubw(vform, zd, zn, zm_b);
2655
break;
2656
case "usubwt_z_zz"_h:
2657
usubw(vform, zd, zn, zm_t);
2658
break;
2659
default:
2660
VIXL_UNIMPLEMENTED();
2661
}
2662
}
2663
2664
void Simulator::Simulate_ZdT_ZnT_const(const Instruction* instr) {
2665
SimVRegister& zd = ReadVRegister(instr->GetRd());
2666
SimVRegister& zn = ReadVRegister(instr->GetRn());
2667
2668
std::pair<int, int> shift_and_lane_size =
2669
instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2670
int lane_size = shift_and_lane_size.second;
2671
VIXL_ASSERT((lane_size >= 0) &&
2672
(static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2673
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
2674
int shift_dist = shift_and_lane_size.first;
2675
2676
switch (form_hash_) {
2677
case "sli_z_zzi"_h:
2678
// Shift distance is computed differently for left shifts. Convert the
2679
// result.
2680
shift_dist = (8 << lane_size) - shift_dist;
2681
sli(vform, zd, zn, shift_dist);
2682
break;
2683
case "sri_z_zzi"_h:
2684
sri(vform, zd, zn, shift_dist);
2685
break;
2686
default:
2687
VIXL_UNIMPLEMENTED();
2688
}
2689
}
2690
2691
void Simulator::SimulateSVENarrow(const Instruction* instr) {
2692
SimVRegister& zd = ReadVRegister(instr->GetRd());
2693
SimVRegister& zn = ReadVRegister(instr->GetRn());
2694
SimVRegister result;
2695
2696
std::pair<int, int> shift_and_lane_size =
2697
instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2698
int lane_size = shift_and_lane_size.second;
2699
VIXL_ASSERT((lane_size >= static_cast<int>(kBRegSizeInBytesLog2)) &&
2700
(lane_size <= static_cast<int>(kSRegSizeInBytesLog2)));
2701
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
2702
int right_shift_dist = shift_and_lane_size.first;
2703
bool top = false;
2704
2705
switch (form_hash_) {
2706
case "sqxtnt_z_zz"_h:
2707
top = true;
2708
VIXL_FALLTHROUGH();
2709
case "sqxtnb_z_zz"_h:
2710
sqxtn(vform, result, zn);
2711
break;
2712
case "sqxtunt_z_zz"_h:
2713
top = true;
2714
VIXL_FALLTHROUGH();
2715
case "sqxtunb_z_zz"_h:
2716
sqxtun(vform, result, zn);
2717
break;
2718
case "uqxtnt_z_zz"_h:
2719
top = true;
2720
VIXL_FALLTHROUGH();
2721
case "uqxtnb_z_zz"_h:
2722
uqxtn(vform, result, zn);
2723
break;
2724
case "rshrnt_z_zi"_h:
2725
top = true;
2726
VIXL_FALLTHROUGH();
2727
case "rshrnb_z_zi"_h:
2728
rshrn(vform, result, zn, right_shift_dist);
2729
break;
2730
case "shrnt_z_zi"_h:
2731
top = true;
2732
VIXL_FALLTHROUGH();
2733
case "shrnb_z_zi"_h:
2734
shrn(vform, result, zn, right_shift_dist);
2735
break;
2736
case "sqrshrnt_z_zi"_h:
2737
top = true;
2738
VIXL_FALLTHROUGH();
2739
case "sqrshrnb_z_zi"_h:
2740
sqrshrn(vform, result, zn, right_shift_dist);
2741
break;
2742
case "sqrshrunt_z_zi"_h:
2743
top = true;
2744
VIXL_FALLTHROUGH();
2745
case "sqrshrunb_z_zi"_h:
2746
sqrshrun(vform, result, zn, right_shift_dist);
2747
break;
2748
case "sqshrnt_z_zi"_h:
2749
top = true;
2750
VIXL_FALLTHROUGH();
2751
case "sqshrnb_z_zi"_h:
2752
sqshrn(vform, result, zn, right_shift_dist);
2753
break;
2754
case "sqshrunt_z_zi"_h:
2755
top = true;
2756
VIXL_FALLTHROUGH();
2757
case "sqshrunb_z_zi"_h:
2758
sqshrun(vform, result, zn, right_shift_dist);
2759
break;
2760
case "uqrshrnt_z_zi"_h:
2761
top = true;
2762
VIXL_FALLTHROUGH();
2763
case "uqrshrnb_z_zi"_h:
2764
uqrshrn(vform, result, zn, right_shift_dist);
2765
break;
2766
case "uqshrnt_z_zi"_h:
2767
top = true;
2768
VIXL_FALLTHROUGH();
2769
case "uqshrnb_z_zi"_h:
2770
uqshrn(vform, result, zn, right_shift_dist);
2771
break;
2772
default:
2773
VIXL_UNIMPLEMENTED();
2774
}
2775
2776
if (top) {
2777
// Keep even elements, replace odd elements with the results.
2778
xtn(vform, zd, zd);
2779
zip1(vform, zd, zd, result);
2780
} else {
2781
// Zero odd elements, replace even elements with the results.
2782
SimVRegister zero;
2783
zero.Clear();
2784
zip1(vform, zd, result, zero);
2785
}
2786
}
2787
2788
void Simulator::SimulateSVEInterleavedArithLong(const Instruction* instr) {
2789
VectorFormat vform = instr->GetSVEVectorFormat();
2790
SimVRegister& zd = ReadVRegister(instr->GetRd());
2791
SimVRegister& zm = ReadVRegister(instr->GetRm());
2792
SimVRegister& zn = ReadVRegister(instr->GetRn());
2793
SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2794
2795
// Construct temporary registers containing the even (bottom) and odd (top)
2796
// elements.
2797
VectorFormat vform_half = VectorFormatHalfWidth(vform);
2798
pack_even_elements(vform_half, zn_b, zn);
2799
pack_even_elements(vform_half, zm_b, zm);
2800
pack_odd_elements(vform_half, zn_t, zn);
2801
pack_odd_elements(vform_half, zm_t, zm);
2802
2803
switch (form_hash_) {
2804
case "sabdlb_z_zz"_h:
2805
sabdl(vform, zd, zn_b, zm_b);
2806
break;
2807
case "sabdlt_z_zz"_h:
2808
sabdl(vform, zd, zn_t, zm_t);
2809
break;
2810
case "saddlb_z_zz"_h:
2811
saddl(vform, zd, zn_b, zm_b);
2812
break;
2813
case "saddlbt_z_zz"_h:
2814
saddl(vform, zd, zn_b, zm_t);
2815
break;
2816
case "saddlt_z_zz"_h:
2817
saddl(vform, zd, zn_t, zm_t);
2818
break;
2819
case "ssublb_z_zz"_h:
2820
ssubl(vform, zd, zn_b, zm_b);
2821
break;
2822
case "ssublbt_z_zz"_h:
2823
ssubl(vform, zd, zn_b, zm_t);
2824
break;
2825
case "ssublt_z_zz"_h:
2826
ssubl(vform, zd, zn_t, zm_t);
2827
break;
2828
case "ssubltb_z_zz"_h:
2829
ssubl(vform, zd, zn_t, zm_b);
2830
break;
2831
case "uabdlb_z_zz"_h:
2832
uabdl(vform, zd, zn_b, zm_b);
2833
break;
2834
case "uabdlt_z_zz"_h:
2835
uabdl(vform, zd, zn_t, zm_t);
2836
break;
2837
case "uaddlb_z_zz"_h:
2838
uaddl(vform, zd, zn_b, zm_b);
2839
break;
2840
case "uaddlt_z_zz"_h:
2841
uaddl(vform, zd, zn_t, zm_t);
2842
break;
2843
case "usublb_z_zz"_h:
2844
usubl(vform, zd, zn_b, zm_b);
2845
break;
2846
case "usublt_z_zz"_h:
2847
usubl(vform, zd, zn_t, zm_t);
2848
break;
2849
case "sabalb_z_zzz"_h:
2850
sabal(vform, zd, zn_b, zm_b);
2851
break;
2852
case "sabalt_z_zzz"_h:
2853
sabal(vform, zd, zn_t, zm_t);
2854
break;
2855
case "uabalb_z_zzz"_h:
2856
uabal(vform, zd, zn_b, zm_b);
2857
break;
2858
case "uabalt_z_zzz"_h:
2859
uabal(vform, zd, zn_t, zm_t);
2860
break;
2861
default:
2862
VIXL_UNIMPLEMENTED();
2863
}
2864
}
2865
2866
void Simulator::SimulateSVEIntMulLongVec(const Instruction* instr) {
2867
VectorFormat vform = instr->GetSVEVectorFormat();
2868
SimVRegister& zd = ReadVRegister(instr->GetRd());
2869
SimVRegister& zm = ReadVRegister(instr->GetRm());
2870
SimVRegister& zn = ReadVRegister(instr->GetRn());
2871
SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
2872
VectorFormat vform_half = VectorFormatHalfWidth(vform);
2873
pack_even_elements(vform_half, zn_b, zn);
2874
pack_even_elements(vform_half, zm_b, zm);
2875
pack_odd_elements(vform_half, zn_t, zn);
2876
pack_odd_elements(vform_half, zm_t, zm);
2877
2878
switch (form_hash_) {
2879
case "pmullb_z_zz"_h:
2880
// '00' is reserved for Q-sized lane.
2881
if (vform == kFormatVnB) {
2882
VIXL_UNIMPLEMENTED();
2883
}
2884
pmull(vform, zd, zn_b, zm_b);
2885
break;
2886
case "pmullt_z_zz"_h:
2887
// '00' is reserved for Q-sized lane.
2888
if (vform == kFormatVnB) {
2889
VIXL_UNIMPLEMENTED();
2890
}
2891
pmull(vform, zd, zn_t, zm_t);
2892
break;
2893
case "smullb_z_zz"_h:
2894
smull(vform, zd, zn_b, zm_b);
2895
break;
2896
case "smullt_z_zz"_h:
2897
smull(vform, zd, zn_t, zm_t);
2898
break;
2899
case "sqdmullb_z_zz"_h:
2900
sqdmull(vform, zd, zn_b, zm_b);
2901
break;
2902
case "sqdmullt_z_zz"_h:
2903
sqdmull(vform, zd, zn_t, zm_t);
2904
break;
2905
case "umullb_z_zz"_h:
2906
umull(vform, zd, zn_b, zm_b);
2907
break;
2908
case "umullt_z_zz"_h:
2909
umull(vform, zd, zn_t, zm_t);
2910
break;
2911
default:
2912
VIXL_UNIMPLEMENTED();
2913
}
2914
}
2915
2916
void Simulator::SimulateSVEAddSubHigh(const Instruction* instr) {
2917
SimVRegister& zd = ReadVRegister(instr->GetRd());
2918
SimVRegister& zm = ReadVRegister(instr->GetRm());
2919
SimVRegister& zn = ReadVRegister(instr->GetRn());
2920
SimVRegister result;
2921
bool top = false;
2922
2923
VectorFormat vform_src = instr->GetSVEVectorFormat();
2924
if (vform_src == kFormatVnB) {
2925
VIXL_UNIMPLEMENTED();
2926
}
2927
VectorFormat vform = VectorFormatHalfWidth(vform_src);
2928
2929
switch (form_hash_) {
2930
case "addhnt_z_zz"_h:
2931
top = true;
2932
VIXL_FALLTHROUGH();
2933
case "addhnb_z_zz"_h:
2934
addhn(vform, result, zn, zm);
2935
break;
2936
case "raddhnt_z_zz"_h:
2937
top = true;
2938
VIXL_FALLTHROUGH();
2939
case "raddhnb_z_zz"_h:
2940
raddhn(vform, result, zn, zm);
2941
break;
2942
case "rsubhnt_z_zz"_h:
2943
top = true;
2944
VIXL_FALLTHROUGH();
2945
case "rsubhnb_z_zz"_h:
2946
rsubhn(vform, result, zn, zm);
2947
break;
2948
case "subhnt_z_zz"_h:
2949
top = true;
2950
VIXL_FALLTHROUGH();
2951
case "subhnb_z_zz"_h:
2952
subhn(vform, result, zn, zm);
2953
break;
2954
default:
2955
VIXL_UNIMPLEMENTED();
2956
}
2957
2958
if (top) {
2959
// Keep even elements, replace odd elements with the results.
2960
xtn(vform, zd, zd);
2961
zip1(vform, zd, zd, result);
2962
} else {
2963
// Zero odd elements, replace even elements with the results.
2964
SimVRegister zero;
2965
zero.Clear();
2966
zip1(vform, zd, result, zero);
2967
}
2968
}
2969
2970
void Simulator::SimulateSVEShiftLeftImm(const Instruction* instr) {
2971
SimVRegister& zd = ReadVRegister(instr->GetRd());
2972
SimVRegister& zn = ReadVRegister(instr->GetRn());
2973
SimVRegister zn_b, zn_t;
2974
2975
std::pair<int, int> shift_and_lane_size =
2976
instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
2977
int lane_size = shift_and_lane_size.second;
2978
VIXL_ASSERT((lane_size >= 0) &&
2979
(static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
2980
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size + 1);
2981
int right_shift_dist = shift_and_lane_size.first;
2982
int left_shift_dist = (8 << lane_size) - right_shift_dist;
2983
2984
// Construct temporary registers containing the even (bottom) and odd (top)
2985
// elements.
2986
VectorFormat vform_half = VectorFormatHalfWidth(vform);
2987
pack_even_elements(vform_half, zn_b, zn);
2988
pack_odd_elements(vform_half, zn_t, zn);
2989
2990
switch (form_hash_) {
2991
case "sshllb_z_zi"_h:
2992
sshll(vform, zd, zn_b, left_shift_dist);
2993
break;
2994
case "sshllt_z_zi"_h:
2995
sshll(vform, zd, zn_t, left_shift_dist);
2996
break;
2997
case "ushllb_z_zi"_h:
2998
ushll(vform, zd, zn_b, left_shift_dist);
2999
break;
3000
case "ushllt_z_zi"_h:
3001
ushll(vform, zd, zn_t, left_shift_dist);
3002
break;
3003
default:
3004
VIXL_UNIMPLEMENTED();
3005
}
3006
}
3007
3008
void Simulator::SimulateSVESaturatingMulAddHigh(const Instruction* instr) {
3009
VectorFormat vform = instr->GetSVEVectorFormat();
3010
SimVRegister& zda = ReadVRegister(instr->GetRd());
3011
SimVRegister& zn = ReadVRegister(instr->GetRn());
3012
unsigned zm_code = instr->GetRm();
3013
int index = -1;
3014
bool is_mla = false;
3015
3016
switch (form_hash_) {
3017
case "sqrdmlah_z_zzz"_h:
3018
is_mla = true;
3019
VIXL_FALLTHROUGH();
3020
case "sqrdmlsh_z_zzz"_h:
3021
// Nothing to do.
3022
break;
3023
case "sqrdmlah_z_zzzi_h"_h:
3024
is_mla = true;
3025
VIXL_FALLTHROUGH();
3026
case "sqrdmlsh_z_zzzi_h"_h:
3027
vform = kFormatVnH;
3028
index = (instr->ExtractBit(22) << 2) | instr->ExtractBits(20, 19);
3029
zm_code = instr->ExtractBits(18, 16);
3030
break;
3031
case "sqrdmlah_z_zzzi_s"_h:
3032
is_mla = true;
3033
VIXL_FALLTHROUGH();
3034
case "sqrdmlsh_z_zzzi_s"_h:
3035
vform = kFormatVnS;
3036
index = instr->ExtractBits(20, 19);
3037
zm_code = instr->ExtractBits(18, 16);
3038
break;
3039
case "sqrdmlah_z_zzzi_d"_h:
3040
is_mla = true;
3041
VIXL_FALLTHROUGH();
3042
case "sqrdmlsh_z_zzzi_d"_h:
3043
vform = kFormatVnD;
3044
index = instr->ExtractBit(20);
3045
zm_code = instr->ExtractBits(19, 16);
3046
break;
3047
default:
3048
VIXL_UNIMPLEMENTED();
3049
}
3050
3051
SimVRegister& zm = ReadVRegister(zm_code);
3052
SimVRegister zm_idx;
3053
if (index >= 0) {
3054
dup_elements_to_segments(vform, zm_idx, zm, index);
3055
}
3056
3057
if (is_mla) {
3058
sqrdmlah(vform, zda, zn, (index >= 0) ? zm_idx : zm);
3059
} else {
3060
sqrdmlsh(vform, zda, zn, (index >= 0) ? zm_idx : zm);
3061
}
3062
}
3063
3064
void Simulator::Simulate_ZdaD_ZnS_ZmS_imm(const Instruction* instr) {
3065
SimVRegister& zda = ReadVRegister(instr->GetRd());
3066
SimVRegister& zn = ReadVRegister(instr->GetRn());
3067
SimVRegister& zm = ReadVRegister(instr->ExtractBits(19, 16));
3068
3069
SimVRegister temp, zm_idx, zn_b, zn_t;
3070
Instr index = (instr->ExtractBit(20) << 1) | instr->ExtractBit(11);
3071
dup_elements_to_segments(kFormatVnS, temp, zm, index);
3072
pack_even_elements(kFormatVnS, zm_idx, temp);
3073
pack_even_elements(kFormatVnS, zn_b, zn);
3074
pack_odd_elements(kFormatVnS, zn_t, zn);
3075
3076
switch (form_hash_) {
3077
case "sqdmlalb_z_zzzi_d"_h:
3078
sqdmlal(kFormatVnD, zda, zn_b, zm_idx);
3079
break;
3080
case "sqdmlalt_z_zzzi_d"_h:
3081
sqdmlal(kFormatVnD, zda, zn_t, zm_idx);
3082
break;
3083
case "sqdmlslb_z_zzzi_d"_h:
3084
sqdmlsl(kFormatVnD, zda, zn_b, zm_idx);
3085
break;
3086
case "sqdmlslt_z_zzzi_d"_h:
3087
sqdmlsl(kFormatVnD, zda, zn_t, zm_idx);
3088
break;
3089
default:
3090
VIXL_UNIMPLEMENTED();
3091
}
3092
}
3093
3094
void Simulator::Simulate_ZdaS_ZnH_ZmH(const Instruction* instr) {
3095
SimVRegister& zda = ReadVRegister(instr->GetRd());
3096
SimVRegister& zm = ReadVRegister(instr->GetRm());
3097
SimVRegister& zn = ReadVRegister(instr->GetRn());
3098
3099
SimVRegister temp, zn_b, zm_b, zn_t, zm_t;
3100
pack_even_elements(kFormatVnH, zn_b, zn);
3101
pack_even_elements(kFormatVnH, zm_b, zm);
3102
pack_odd_elements(kFormatVnH, zn_t, zn);
3103
pack_odd_elements(kFormatVnH, zm_t, zm);
3104
3105
switch (form_hash_) {
3106
case "fmlalb_z_zzz"_h:
3107
fmlal(kFormatVnS, zda, zn_b, zm_b);
3108
break;
3109
case "fmlalt_z_zzz"_h:
3110
fmlal(kFormatVnS, zda, zn_t, zm_t);
3111
break;
3112
case "fmlslb_z_zzz"_h:
3113
fmlsl(kFormatVnS, zda, zn_b, zm_b);
3114
break;
3115
case "fmlslt_z_zzz"_h:
3116
fmlsl(kFormatVnS, zda, zn_t, zm_t);
3117
break;
3118
default:
3119
VIXL_UNIMPLEMENTED();
3120
}
3121
}
3122
3123
void Simulator::Simulate_ZdaS_ZnH_ZmH_imm(const Instruction* instr) {
3124
SimVRegister& zda = ReadVRegister(instr->GetRd());
3125
SimVRegister& zn = ReadVRegister(instr->GetRn());
3126
SimVRegister& zm = ReadVRegister(instr->ExtractBits(18, 16));
3127
3128
SimVRegister temp, zm_idx, zn_b, zn_t;
3129
Instr index = (instr->ExtractBits(20, 19) << 1) | instr->ExtractBit(11);
3130
dup_elements_to_segments(kFormatVnH, temp, zm, index);
3131
pack_even_elements(kFormatVnH, zm_idx, temp);
3132
pack_even_elements(kFormatVnH, zn_b, zn);
3133
pack_odd_elements(kFormatVnH, zn_t, zn);
3134
3135
switch (form_hash_) {
3136
case "fmlalb_z_zzzi_s"_h:
3137
fmlal(kFormatVnS, zda, zn_b, zm_idx);
3138
break;
3139
case "fmlalt_z_zzzi_s"_h:
3140
fmlal(kFormatVnS, zda, zn_t, zm_idx);
3141
break;
3142
case "fmlslb_z_zzzi_s"_h:
3143
fmlsl(kFormatVnS, zda, zn_b, zm_idx);
3144
break;
3145
case "fmlslt_z_zzzi_s"_h:
3146
fmlsl(kFormatVnS, zda, zn_t, zm_idx);
3147
break;
3148
case "sqdmlalb_z_zzzi_s"_h:
3149
sqdmlal(kFormatVnS, zda, zn_b, zm_idx);
3150
break;
3151
case "sqdmlalt_z_zzzi_s"_h:
3152
sqdmlal(kFormatVnS, zda, zn_t, zm_idx);
3153
break;
3154
case "sqdmlslb_z_zzzi_s"_h:
3155
sqdmlsl(kFormatVnS, zda, zn_b, zm_idx);
3156
break;
3157
case "sqdmlslt_z_zzzi_s"_h:
3158
sqdmlsl(kFormatVnS, zda, zn_t, zm_idx);
3159
break;
3160
default:
3161
VIXL_UNIMPLEMENTED();
3162
}
3163
}
3164
3165
void Simulator::Simulate_ZdaT_PgM_ZnTb(const Instruction* instr) {
3166
VectorFormat vform = instr->GetSVEVectorFormat();
3167
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3168
SimVRegister& zda = ReadVRegister(instr->GetRd());
3169
SimVRegister& zn = ReadVRegister(instr->GetRn());
3170
SimVRegister result;
3171
3172
switch (form_hash_) {
3173
case "sadalp_z_p_z"_h:
3174
sadalp(vform, result, zn);
3175
break;
3176
case "uadalp_z_p_z"_h:
3177
uadalp(vform, result, zn);
3178
break;
3179
default:
3180
VIXL_UNIMPLEMENTED();
3181
}
3182
mov_merging(vform, zda, pg, result);
3183
}
3184
3185
void Simulator::SimulateSVEAddSubCarry(const Instruction* instr) {
3186
VectorFormat vform = (instr->ExtractBit(22) == 0) ? kFormatVnS : kFormatVnD;
3187
SimVRegister& zda = ReadVRegister(instr->GetRd());
3188
SimVRegister& zm = ReadVRegister(instr->GetRm());
3189
SimVRegister& zn = ReadVRegister(instr->GetRn());
3190
3191
SimVRegister not_zn;
3192
not_(vform, not_zn, zn);
3193
3194
switch (form_hash_) {
3195
case "adclb_z_zzz"_h:
3196
adcl(vform, zda, zn, zm, /* top = */ false);
3197
break;
3198
case "adclt_z_zzz"_h:
3199
adcl(vform, zda, zn, zm, /* top = */ true);
3200
break;
3201
case "sbclb_z_zzz"_h:
3202
adcl(vform, zda, not_zn, zm, /* top = */ false);
3203
break;
3204
case "sbclt_z_zzz"_h:
3205
adcl(vform, zda, not_zn, zm, /* top = */ true);
3206
break;
3207
default:
3208
VIXL_UNIMPLEMENTED();
3209
}
3210
}
3211
3212
void Simulator::Simulate_ZdaT_ZnT_ZmT(const Instruction* instr) {
3213
VectorFormat vform = instr->GetSVEVectorFormat();
3214
SimVRegister& zda = ReadVRegister(instr->GetRd());
3215
SimVRegister& zm = ReadVRegister(instr->GetRm());
3216
SimVRegister& zn = ReadVRegister(instr->GetRn());
3217
3218
switch (form_hash_) {
3219
case "saba_z_zzz"_h:
3220
saba(vform, zda, zn, zm);
3221
break;
3222
case "uaba_z_zzz"_h:
3223
uaba(vform, zda, zn, zm);
3224
break;
3225
default:
3226
VIXL_UNIMPLEMENTED();
3227
}
3228
}
3229
3230
void Simulator::SimulateSVEComplexIntMulAdd(const Instruction* instr) {
3231
SimVRegister& zda = ReadVRegister(instr->GetRd());
3232
SimVRegister& zn = ReadVRegister(instr->GetRn());
3233
int rot = instr->ExtractBits(11, 10) * 90;
3234
// vform and zm are only valid for the vector form of instruction.
3235
VectorFormat vform = instr->GetSVEVectorFormat();
3236
SimVRegister& zm = ReadVRegister(instr->GetRm());
3237
3238
// Inputs for indexed form of instruction.
3239
SimVRegister& zm_h = ReadVRegister(instr->ExtractBits(18, 16));
3240
SimVRegister& zm_s = ReadVRegister(instr->ExtractBits(19, 16));
3241
int idx_h = instr->ExtractBits(20, 19);
3242
int idx_s = instr->ExtractBit(20);
3243
3244
switch (form_hash_) {
3245
case "cmla_z_zzz"_h:
3246
cmla(vform, zda, zda, zn, zm, rot);
3247
break;
3248
case "cmla_z_zzzi_h"_h:
3249
cmla(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot);
3250
break;
3251
case "cmla_z_zzzi_s"_h:
3252
cmla(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot);
3253
break;
3254
case "sqrdcmlah_z_zzz"_h:
3255
sqrdcmlah(vform, zda, zda, zn, zm, rot);
3256
break;
3257
case "sqrdcmlah_z_zzzi_h"_h:
3258
sqrdcmlah(kFormatVnH, zda, zda, zn, zm_h, idx_h, rot);
3259
break;
3260
case "sqrdcmlah_z_zzzi_s"_h:
3261
sqrdcmlah(kFormatVnS, zda, zda, zn, zm_s, idx_s, rot);
3262
break;
3263
default:
3264
VIXL_UNIMPLEMENTED();
3265
}
3266
}
3267
3268
void Simulator::Simulate_ZdaT_ZnT_const(const Instruction* instr) {
3269
SimVRegister& zd = ReadVRegister(instr->GetRd());
3270
SimVRegister& zn = ReadVRegister(instr->GetRn());
3271
3272
std::pair<int, int> shift_and_lane_size =
3273
instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3274
int lane_size = shift_and_lane_size.second;
3275
VIXL_ASSERT((lane_size >= 0) &&
3276
(static_cast<unsigned>(lane_size) <= kDRegSizeInBytesLog2));
3277
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3278
int shift_dist = shift_and_lane_size.first;
3279
3280
switch (form_hash_) {
3281
case "srsra_z_zi"_h:
3282
srsra(vform, zd, zn, shift_dist);
3283
break;
3284
case "ssra_z_zi"_h:
3285
ssra(vform, zd, zn, shift_dist);
3286
break;
3287
case "ursra_z_zi"_h:
3288
ursra(vform, zd, zn, shift_dist);
3289
break;
3290
case "usra_z_zi"_h:
3291
usra(vform, zd, zn, shift_dist);
3292
break;
3293
default:
3294
VIXL_UNIMPLEMENTED();
3295
}
3296
}
3297
3298
void Simulator::Simulate_ZdaT_ZnTb_ZmTb(const Instruction* instr) {
3299
VectorFormat vform = instr->GetSVEVectorFormat();
3300
SimVRegister& zda = ReadVRegister(instr->GetRd());
3301
SimVRegister& zm = ReadVRegister(instr->GetRm());
3302
SimVRegister& zn = ReadVRegister(instr->GetRn());
3303
3304
SimVRegister zero, zn_b, zm_b, zn_t, zm_t;
3305
zero.Clear();
3306
3307
VectorFormat vform_half = VectorFormatHalfWidth(vform);
3308
uzp1(vform_half, zn_b, zn, zero);
3309
uzp1(vform_half, zm_b, zm, zero);
3310
uzp2(vform_half, zn_t, zn, zero);
3311
uzp2(vform_half, zm_t, zm, zero);
3312
3313
switch (form_hash_) {
3314
case "smlalb_z_zzz"_h:
3315
smlal(vform, zda, zn_b, zm_b);
3316
break;
3317
case "smlalt_z_zzz"_h:
3318
smlal(vform, zda, zn_t, zm_t);
3319
break;
3320
case "smlslb_z_zzz"_h:
3321
smlsl(vform, zda, zn_b, zm_b);
3322
break;
3323
case "smlslt_z_zzz"_h:
3324
smlsl(vform, zda, zn_t, zm_t);
3325
break;
3326
case "sqdmlalb_z_zzz"_h:
3327
sqdmlal(vform, zda, zn_b, zm_b);
3328
break;
3329
case "sqdmlalbt_z_zzz"_h:
3330
sqdmlal(vform, zda, zn_b, zm_t);
3331
break;
3332
case "sqdmlalt_z_zzz"_h:
3333
sqdmlal(vform, zda, zn_t, zm_t);
3334
break;
3335
case "sqdmlslb_z_zzz"_h:
3336
sqdmlsl(vform, zda, zn_b, zm_b);
3337
break;
3338
case "sqdmlslbt_z_zzz"_h:
3339
sqdmlsl(vform, zda, zn_b, zm_t);
3340
break;
3341
case "sqdmlslt_z_zzz"_h:
3342
sqdmlsl(vform, zda, zn_t, zm_t);
3343
break;
3344
case "umlalb_z_zzz"_h:
3345
umlal(vform, zda, zn_b, zm_b);
3346
break;
3347
case "umlalt_z_zzz"_h:
3348
umlal(vform, zda, zn_t, zm_t);
3349
break;
3350
case "umlslb_z_zzz"_h:
3351
umlsl(vform, zda, zn_b, zm_b);
3352
break;
3353
case "umlslt_z_zzz"_h:
3354
umlsl(vform, zda, zn_t, zm_t);
3355
break;
3356
default:
3357
VIXL_UNIMPLEMENTED();
3358
}
3359
}
3360
3361
void Simulator::SimulateSVEComplexDotProduct(const Instruction* instr) {
3362
VectorFormat vform = instr->GetSVEVectorFormat();
3363
SimVRegister& zda = ReadVRegister(instr->GetRd());
3364
SimVRegister& zn = ReadVRegister(instr->GetRn());
3365
int rot = instr->ExtractBits(11, 10) * 90;
3366
unsigned zm_code = instr->GetRm();
3367
int index = -1;
3368
3369
switch (form_hash_) {
3370
case "cdot_z_zzz"_h:
3371
// Nothing to do.
3372
break;
3373
case "cdot_z_zzzi_s"_h:
3374
index = zm_code >> 3;
3375
zm_code &= 0x7;
3376
break;
3377
case "cdot_z_zzzi_d"_h:
3378
index = zm_code >> 4;
3379
zm_code &= 0xf;
3380
break;
3381
default:
3382
VIXL_UNIMPLEMENTED();
3383
}
3384
3385
SimVRegister temp;
3386
SimVRegister& zm = ReadVRegister(zm_code);
3387
if (index >= 0) dup_elements_to_segments(vform, temp, zm, index);
3388
cdot(vform, zda, zda, zn, (index >= 0) ? temp : zm, rot);
3389
}
3390
3391
void Simulator::SimulateSVEBitwiseTernary(const Instruction* instr) {
3392
VectorFormat vform = kFormatVnD;
3393
SimVRegister& zdn = ReadVRegister(instr->GetRd());
3394
SimVRegister& zm = ReadVRegister(instr->GetRm());
3395
SimVRegister& zk = ReadVRegister(instr->GetRn());
3396
SimVRegister temp;
3397
3398
switch (form_hash_) {
3399
case "bcax_z_zzz"_h:
3400
bic(vform, temp, zm, zk);
3401
eor(vform, zdn, temp, zdn);
3402
break;
3403
case "bsl1n_z_zzz"_h:
3404
not_(vform, temp, zdn);
3405
bsl(vform, zdn, zk, temp, zm);
3406
break;
3407
case "bsl2n_z_zzz"_h:
3408
not_(vform, temp, zm);
3409
bsl(vform, zdn, zk, zdn, temp);
3410
break;
3411
case "bsl_z_zzz"_h:
3412
bsl(vform, zdn, zk, zdn, zm);
3413
break;
3414
case "eor3_z_zzz"_h:
3415
eor(vform, temp, zdn, zm);
3416
eor(vform, zdn, temp, zk);
3417
break;
3418
case "nbsl_z_zzz"_h:
3419
bsl(vform, zdn, zk, zdn, zm);
3420
not_(vform, zdn, zdn);
3421
break;
3422
default:
3423
VIXL_UNIMPLEMENTED();
3424
}
3425
}
3426
3427
void Simulator::SimulateSVEHalvingAddSub(const Instruction* instr) {
3428
VectorFormat vform = instr->GetSVEVectorFormat();
3429
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3430
SimVRegister& zdn = ReadVRegister(instr->GetRd());
3431
SimVRegister& zm = ReadVRegister(instr->GetRn());
3432
SimVRegister result;
3433
3434
switch (form_hash_) {
3435
case "shadd_z_p_zz"_h:
3436
add(vform, result, zdn, zm).Halve(vform);
3437
break;
3438
case "shsub_z_p_zz"_h:
3439
sub(vform, result, zdn, zm).Halve(vform);
3440
break;
3441
case "shsubr_z_p_zz"_h:
3442
sub(vform, result, zm, zdn).Halve(vform);
3443
break;
3444
case "srhadd_z_p_zz"_h:
3445
add(vform, result, zdn, zm).Halve(vform).Round(vform);
3446
break;
3447
case "uhadd_z_p_zz"_h:
3448
add(vform, result, zdn, zm).Uhalve(vform);
3449
break;
3450
case "uhsub_z_p_zz"_h:
3451
sub(vform, result, zdn, zm).Uhalve(vform);
3452
break;
3453
case "uhsubr_z_p_zz"_h:
3454
sub(vform, result, zm, zdn).Uhalve(vform);
3455
break;
3456
case "urhadd_z_p_zz"_h:
3457
add(vform, result, zdn, zm).Uhalve(vform).Round(vform);
3458
break;
3459
default:
3460
VIXL_UNIMPLEMENTED();
3461
break;
3462
}
3463
mov_merging(vform, zdn, pg, result);
3464
}
3465
3466
void Simulator::SimulateSVESaturatingArithmetic(const Instruction* instr) {
3467
VectorFormat vform = instr->GetSVEVectorFormat();
3468
SimVRegister& zdn = ReadVRegister(instr->GetRd());
3469
SimVRegister& zm = ReadVRegister(instr->GetRn());
3470
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3471
SimVRegister result;
3472
3473
switch (form_hash_) {
3474
case "sqadd_z_p_zz"_h:
3475
add(vform, result, zdn, zm).SignedSaturate(vform);
3476
break;
3477
case "sqsub_z_p_zz"_h:
3478
sub(vform, result, zdn, zm).SignedSaturate(vform);
3479
break;
3480
case "sqsubr_z_p_zz"_h:
3481
sub(vform, result, zm, zdn).SignedSaturate(vform);
3482
break;
3483
case "suqadd_z_p_zz"_h:
3484
suqadd(vform, result, zdn, zm);
3485
break;
3486
case "uqadd_z_p_zz"_h:
3487
add(vform, result, zdn, zm).UnsignedSaturate(vform);
3488
break;
3489
case "uqsub_z_p_zz"_h:
3490
sub(vform, result, zdn, zm).UnsignedSaturate(vform);
3491
break;
3492
case "uqsubr_z_p_zz"_h:
3493
sub(vform, result, zm, zdn).UnsignedSaturate(vform);
3494
break;
3495
case "usqadd_z_p_zz"_h:
3496
usqadd(vform, result, zdn, zm);
3497
break;
3498
default:
3499
VIXL_UNIMPLEMENTED();
3500
break;
3501
}
3502
mov_merging(vform, zdn, pg, result);
3503
}
3504
3505
void Simulator::SimulateSVEIntArithPair(const Instruction* instr) {
3506
VectorFormat vform = instr->GetSVEVectorFormat();
3507
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3508
SimVRegister& zdn = ReadVRegister(instr->GetRd());
3509
SimVRegister& zm = ReadVRegister(instr->GetRn());
3510
SimVRegister result;
3511
3512
switch (form_hash_) {
3513
case "addp_z_p_zz"_h:
3514
addp(vform, result, zdn, zm);
3515
break;
3516
case "smaxp_z_p_zz"_h:
3517
smaxp(vform, result, zdn, zm);
3518
break;
3519
case "sminp_z_p_zz"_h:
3520
sminp(vform, result, zdn, zm);
3521
break;
3522
case "umaxp_z_p_zz"_h:
3523
umaxp(vform, result, zdn, zm);
3524
break;
3525
case "uminp_z_p_zz"_h:
3526
uminp(vform, result, zdn, zm);
3527
break;
3528
default:
3529
VIXL_UNIMPLEMENTED();
3530
break;
3531
}
3532
mov_merging(vform, zdn, pg, result);
3533
}
3534
3535
void Simulator::Simulate_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr) {
3536
VectorFormat vform = instr->GetSVEVectorFormat();
3537
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3538
SimVRegister& zdn = ReadVRegister(instr->GetRd());
3539
SimVRegister& zm = ReadVRegister(instr->GetRn());
3540
SimVRegister result;
3541
3542
switch (form_hash_) {
3543
case "faddp_z_p_zz"_h:
3544
faddp(vform, result, zdn, zm);
3545
break;
3546
case "fmaxnmp_z_p_zz"_h:
3547
fmaxnmp(vform, result, zdn, zm);
3548
break;
3549
case "fmaxp_z_p_zz"_h:
3550
fmaxp(vform, result, zdn, zm);
3551
break;
3552
case "fminnmp_z_p_zz"_h:
3553
fminnmp(vform, result, zdn, zm);
3554
break;
3555
case "fminp_z_p_zz"_h:
3556
fminp(vform, result, zdn, zm);
3557
break;
3558
default:
3559
VIXL_UNIMPLEMENTED();
3560
}
3561
mov_merging(vform, zdn, pg, result);
3562
}
3563
3564
void Simulator::Simulate_ZdnT_PgM_ZdnT_const(const Instruction* instr) {
3565
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3566
SimVRegister& zdn = ReadVRegister(instr->GetRd());
3567
3568
std::pair<int, int> shift_and_lane_size =
3569
instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
3570
unsigned lane_size = shift_and_lane_size.second;
3571
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3572
int right_shift_dist = shift_and_lane_size.first;
3573
int left_shift_dist = (8 << lane_size) - right_shift_dist;
3574
SimVRegister result;
3575
3576
switch (form_hash_) {
3577
case "sqshl_z_p_zi"_h:
3578
sqshl(vform, result, zdn, left_shift_dist);
3579
break;
3580
case "sqshlu_z_p_zi"_h:
3581
sqshlu(vform, result, zdn, left_shift_dist);
3582
break;
3583
case "srshr_z_p_zi"_h:
3584
sshr(vform, result, zdn, right_shift_dist).Round(vform);
3585
break;
3586
case "uqshl_z_p_zi"_h:
3587
uqshl(vform, result, zdn, left_shift_dist);
3588
break;
3589
case "urshr_z_p_zi"_h:
3590
ushr(vform, result, zdn, right_shift_dist).Round(vform);
3591
break;
3592
default:
3593
VIXL_UNIMPLEMENTED();
3594
}
3595
mov_merging(vform, zdn, pg, result);
3596
}
3597
3598
void Simulator::SimulateSVEExclusiveOrRotate(const Instruction* instr) {
3599
VIXL_ASSERT(form_hash_ == "xar_z_zzi"_h);
3600
3601
SimVRegister& zdn = ReadVRegister(instr->GetRd());
3602
SimVRegister& zm = ReadVRegister(instr->GetRn());
3603
3604
std::pair<int, int> shift_and_lane_size =
3605
instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
3606
unsigned lane_size = shift_and_lane_size.second;
3607
VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
3608
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
3609
int shift_dist = shift_and_lane_size.first;
3610
eor(vform, zdn, zdn, zm);
3611
ror(vform, zdn, zdn, shift_dist);
3612
}
3613
3614
void Simulator::Simulate_ZdnT_ZdnT_ZmT_const(const Instruction* instr) {
3615
VectorFormat vform = instr->GetSVEVectorFormat();
3616
SimVRegister& zdn = ReadVRegister(instr->GetRd());
3617
SimVRegister& zm = ReadVRegister(instr->GetRn());
3618
int rot = (instr->ExtractBit(10) == 0) ? 90 : 270;
3619
3620
switch (form_hash_) {
3621
case "cadd_z_zz"_h:
3622
cadd(vform, zdn, zdn, zm, rot);
3623
break;
3624
case "sqcadd_z_zz"_h:
3625
cadd(vform, zdn, zdn, zm, rot, /* saturate = */ true);
3626
break;
3627
default:
3628
VIXL_UNIMPLEMENTED();
3629
}
3630
}
3631
3632
void Simulator::Simulate_ZtD_PgZ_ZnD_Xm(const Instruction* instr) {
3633
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3634
SimVRegister& zn = ReadVRegister(instr->GetRn());
3635
uint64_t xm = ReadXRegister(instr->GetRm());
3636
3637
LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3638
int msize = -1;
3639
bool is_signed = false;
3640
3641
switch (form_hash_) {
3642
case "ldnt1b_z_p_ar_d_64_unscaled"_h:
3643
msize = 0;
3644
break;
3645
case "ldnt1d_z_p_ar_d_64_unscaled"_h:
3646
msize = 3;
3647
break;
3648
case "ldnt1h_z_p_ar_d_64_unscaled"_h:
3649
msize = 1;
3650
break;
3651
case "ldnt1sb_z_p_ar_d_64_unscaled"_h:
3652
msize = 0;
3653
is_signed = true;
3654
break;
3655
case "ldnt1sh_z_p_ar_d_64_unscaled"_h:
3656
msize = 1;
3657
is_signed = true;
3658
break;
3659
case "ldnt1sw_z_p_ar_d_64_unscaled"_h:
3660
msize = 2;
3661
is_signed = true;
3662
break;
3663
case "ldnt1w_z_p_ar_d_64_unscaled"_h:
3664
msize = 2;
3665
break;
3666
default:
3667
VIXL_UNIMPLEMENTED();
3668
}
3669
addr.SetMsizeInBytesLog2(msize);
3670
SVEStructuredLoadHelper(kFormatVnD, pg, instr->GetRt(), addr, is_signed);
3671
}
3672
3673
void Simulator::Simulate_ZtD_Pg_ZnD_Xm(const Instruction* instr) {
3674
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3675
SimVRegister& zn = ReadVRegister(instr->GetRn());
3676
uint64_t xm = ReadXRegister(instr->GetRm());
3677
3678
LogicSVEAddressVector addr(xm, &zn, kFormatVnD);
3679
VIXL_ASSERT((form_hash_ == "stnt1b_z_p_ar_d_64_unscaled"_h) ||
3680
(form_hash_ == "stnt1d_z_p_ar_d_64_unscaled"_h) ||
3681
(form_hash_ == "stnt1h_z_p_ar_d_64_unscaled"_h) ||
3682
(form_hash_ == "stnt1w_z_p_ar_d_64_unscaled"_h));
3683
3684
addr.SetMsizeInBytesLog2(
3685
instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3686
SVEStructuredStoreHelper(kFormatVnD, pg, instr->GetRt(), addr);
3687
}
3688
3689
void Simulator::Simulate_ZtS_PgZ_ZnS_Xm(const Instruction* instr) {
3690
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3691
SimVRegister& zn = ReadVRegister(instr->GetRn());
3692
uint64_t xm = ReadXRegister(instr->GetRm());
3693
3694
LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3695
int msize = -1;
3696
bool is_signed = false;
3697
3698
switch (form_hash_) {
3699
case "ldnt1b_z_p_ar_s_x32_unscaled"_h:
3700
msize = 0;
3701
break;
3702
case "ldnt1h_z_p_ar_s_x32_unscaled"_h:
3703
msize = 1;
3704
break;
3705
case "ldnt1sb_z_p_ar_s_x32_unscaled"_h:
3706
msize = 0;
3707
is_signed = true;
3708
break;
3709
case "ldnt1sh_z_p_ar_s_x32_unscaled"_h:
3710
msize = 1;
3711
is_signed = true;
3712
break;
3713
case "ldnt1w_z_p_ar_s_x32_unscaled"_h:
3714
msize = 2;
3715
break;
3716
default:
3717
VIXL_UNIMPLEMENTED();
3718
}
3719
addr.SetMsizeInBytesLog2(msize);
3720
SVEStructuredLoadHelper(kFormatVnS, pg, instr->GetRt(), addr, is_signed);
3721
}
3722
3723
void Simulator::Simulate_ZtS_Pg_ZnS_Xm(const Instruction* instr) {
3724
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
3725
SimVRegister& zn = ReadVRegister(instr->GetRn());
3726
uint64_t xm = ReadXRegister(instr->GetRm());
3727
3728
LogicSVEAddressVector addr(xm, &zn, kFormatVnS);
3729
VIXL_ASSERT((form_hash_ == "stnt1b_z_p_ar_s_x32_unscaled"_h) ||
3730
(form_hash_ == "stnt1h_z_p_ar_s_x32_unscaled"_h) ||
3731
(form_hash_ == "stnt1w_z_p_ar_s_x32_unscaled"_h));
3732
3733
addr.SetMsizeInBytesLog2(
3734
instr->GetSVEMsizeFromDtype(/* is_signed = */ false));
3735
SVEStructuredStoreHelper(kFormatVnS, pg, instr->GetRt(), addr);
3736
}
3737
3738
void Simulator::VisitReserved(const Instruction* instr) {
3739
// UDF is the only instruction in this group, and the Decoder is precise here.
3740
VIXL_ASSERT(instr->Mask(ReservedMask) == UDF);
3741
3742
printf("UDF (permanently undefined) instruction at %p: 0x%08" PRIx32 "\n",
3743
reinterpret_cast<const void*>(instr),
3744
instr->GetInstructionBits());
3745
VIXL_ABORT_WITH_MSG("UNDEFINED (UDF)\n");
3746
}
3747
3748
3749
void Simulator::VisitUnimplemented(const Instruction* instr) {
3750
printf("Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
3751
reinterpret_cast<const void*>(instr),
3752
instr->GetInstructionBits());
3753
VIXL_UNIMPLEMENTED();
3754
}
3755
3756
3757
void Simulator::VisitUnallocated(const Instruction* instr) {
3758
printf("Unallocated instruction at %p: 0x%08" PRIx32 "\n",
3759
reinterpret_cast<const void*>(instr),
3760
instr->GetInstructionBits());
3761
VIXL_UNIMPLEMENTED();
3762
}
3763
3764
3765
void Simulator::VisitPCRelAddressing(const Instruction* instr) {
3766
VIXL_ASSERT((instr->Mask(PCRelAddressingMask) == ADR) ||
3767
(instr->Mask(PCRelAddressingMask) == ADRP));
3768
3769
WriteRegister(instr->GetRd(), instr->GetImmPCOffsetTarget());
3770
}
3771
3772
3773
void Simulator::VisitUnconditionalBranch(const Instruction* instr) {
3774
switch (instr->Mask(UnconditionalBranchMask)) {
3775
case BL:
3776
WriteLr(instr->GetNextInstruction());
3777
VIXL_FALLTHROUGH();
3778
case B:
3779
WritePc(instr->GetImmPCOffsetTarget());
3780
break;
3781
default:
3782
VIXL_UNREACHABLE();
3783
}
3784
}
3785
3786
3787
void Simulator::VisitConditionalBranch(const Instruction* instr) {
3788
VIXL_ASSERT(instr->Mask(ConditionalBranchMask) == B_cond);
3789
if (ConditionPassed(instr->GetConditionBranch())) {
3790
WritePc(instr->GetImmPCOffsetTarget());
3791
}
3792
}
3793
3794
BType Simulator::GetBTypeFromInstruction(const Instruction* instr) const {
3795
switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3796
case BLR:
3797
case BLRAA:
3798
case BLRAB:
3799
case BLRAAZ:
3800
case BLRABZ:
3801
return BranchAndLink;
3802
case BR:
3803
case BRAA:
3804
case BRAB:
3805
case BRAAZ:
3806
case BRABZ:
3807
if ((instr->GetRn() == 16) || (instr->GetRn() == 17) ||
3808
!PcIsInGuardedPage()) {
3809
return BranchFromUnguardedOrToIP;
3810
}
3811
return BranchFromGuardedNotToIP;
3812
}
3813
return DefaultBType;
3814
}
3815
3816
void Simulator::VisitUnconditionalBranchToRegister(const Instruction* instr) {
3817
bool authenticate = false;
3818
bool link = false;
3819
bool ret = false;
3820
uint64_t addr = ReadXRegister(instr->GetRn());
3821
uint64_t context = 0;
3822
3823
switch (instr->Mask(UnconditionalBranchToRegisterMask)) {
3824
case BLR:
3825
link = true;
3826
VIXL_FALLTHROUGH();
3827
case BR:
3828
break;
3829
3830
case BLRAAZ:
3831
case BLRABZ:
3832
link = true;
3833
VIXL_FALLTHROUGH();
3834
case BRAAZ:
3835
case BRABZ:
3836
authenticate = true;
3837
break;
3838
3839
case BLRAA:
3840
case BLRAB:
3841
link = true;
3842
VIXL_FALLTHROUGH();
3843
case BRAA:
3844
case BRAB:
3845
authenticate = true;
3846
context = ReadXRegister(instr->GetRd());
3847
break;
3848
3849
case RETAA:
3850
case RETAB:
3851
authenticate = true;
3852
addr = ReadXRegister(kLinkRegCode);
3853
context = ReadXRegister(31, Reg31IsStackPointer);
3854
VIXL_FALLTHROUGH();
3855
case RET:
3856
ret = true;
3857
break;
3858
default:
3859
VIXL_UNREACHABLE();
3860
}
3861
3862
if (link) {
3863
WriteLr(instr->GetNextInstruction());
3864
}
3865
3866
if (authenticate) {
3867
PACKey key = (instr->ExtractBit(10) == 0) ? kPACKeyIA : kPACKeyIB;
3868
addr = AuthPAC(addr, context, key, kInstructionPointer);
3869
3870
int error_lsb = GetTopPACBit(addr, kInstructionPointer) - 2;
3871
if (((addr >> error_lsb) & 0x3) != 0x0) {
3872
VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
3873
}
3874
}
3875
3876
if (!ret) {
3877
// Check for interceptions to the target address, if one is found, call it.
3878
MetaDataDepot::BranchInterceptionAbstract* interception =
3879
meta_data_.FindBranchInterception(addr);
3880
3881
if (interception != nullptr) {
3882
// Instead of writing the address of the function to the PC, call the
3883
// function's interception directly. We change the address that will be
3884
// branched to so that afterwards we continue execution from
3885
// the address in the LR. Note: the interception may modify the LR so
3886
// store it before calling the interception.
3887
addr = ReadRegister<uint64_t>(kLinkRegCode);
3888
(*interception)(this);
3889
}
3890
}
3891
3892
WriteNextBType(GetBTypeFromInstruction(instr));
3893
WritePc(Instruction::Cast(addr));
3894
}
3895
3896
3897
void Simulator::VisitTestBranch(const Instruction* instr) {
3898
unsigned bit_pos =
3899
(instr->GetImmTestBranchBit5() << 5) | instr->GetImmTestBranchBit40();
3900
bool bit_zero = ((ReadXRegister(instr->GetRt()) >> bit_pos) & 1) == 0;
3901
bool take_branch = false;
3902
switch (instr->Mask(TestBranchMask)) {
3903
case TBZ:
3904
take_branch = bit_zero;
3905
break;
3906
case TBNZ:
3907
take_branch = !bit_zero;
3908
break;
3909
default:
3910
VIXL_UNIMPLEMENTED();
3911
}
3912
if (take_branch) {
3913
WritePc(instr->GetImmPCOffsetTarget());
3914
}
3915
}
3916
3917
3918
void Simulator::VisitCompareBranch(const Instruction* instr) {
3919
unsigned rt = instr->GetRt();
3920
bool take_branch = false;
3921
switch (instr->Mask(CompareBranchMask)) {
3922
case CBZ_w:
3923
take_branch = (ReadWRegister(rt) == 0);
3924
break;
3925
case CBZ_x:
3926
take_branch = (ReadXRegister(rt) == 0);
3927
break;
3928
case CBNZ_w:
3929
take_branch = (ReadWRegister(rt) != 0);
3930
break;
3931
case CBNZ_x:
3932
take_branch = (ReadXRegister(rt) != 0);
3933
break;
3934
default:
3935
VIXL_UNIMPLEMENTED();
3936
}
3937
if (take_branch) {
3938
WritePc(instr->GetImmPCOffsetTarget());
3939
}
3940
}
3941
3942
3943
void Simulator::AddSubHelper(const Instruction* instr, int64_t op2) {
3944
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3945
bool set_flags = instr->GetFlagsUpdate();
3946
int64_t new_val = 0;
3947
Instr operation = instr->Mask(AddSubOpMask);
3948
3949
switch (operation) {
3950
case ADD:
3951
case ADDS: {
3952
new_val = AddWithCarry(reg_size,
3953
set_flags,
3954
ReadRegister(reg_size,
3955
instr->GetRn(),
3956
instr->GetRnMode()),
3957
op2);
3958
break;
3959
}
3960
case SUB:
3961
case SUBS: {
3962
new_val = AddWithCarry(reg_size,
3963
set_flags,
3964
ReadRegister(reg_size,
3965
instr->GetRn(),
3966
instr->GetRnMode()),
3967
~op2,
3968
1);
3969
break;
3970
}
3971
default:
3972
VIXL_UNREACHABLE();
3973
}
3974
3975
WriteRegister(reg_size,
3976
instr->GetRd(),
3977
new_val,
3978
LogRegWrites,
3979
instr->GetRdMode());
3980
}
3981
3982
3983
void Simulator::VisitAddSubShifted(const Instruction* instr) {
3984
// Add/sub/adds/subs don't allow ROR as a shift mode.
3985
VIXL_ASSERT(instr->GetShiftDP() != ROR);
3986
3987
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
3988
int64_t op2 = ShiftOperand(reg_size,
3989
ReadRegister(reg_size, instr->GetRm()),
3990
static_cast<Shift>(instr->GetShiftDP()),
3991
instr->GetImmDPShift());
3992
AddSubHelper(instr, op2);
3993
}
3994
3995
3996
void Simulator::VisitAddSubImmediate(const Instruction* instr) {
3997
int64_t op2 = instr->GetImmAddSub()
3998
<< ((instr->GetImmAddSubShift() == 1) ? 12 : 0);
3999
AddSubHelper(instr, op2);
4000
}
4001
4002
4003
void Simulator::VisitAddSubExtended(const Instruction* instr) {
4004
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
4005
int64_t op2 = ExtendValue(reg_size,
4006
ReadRegister(reg_size, instr->GetRm()),
4007
static_cast<Extend>(instr->GetExtendMode()),
4008
instr->GetImmExtendShift());
4009
AddSubHelper(instr, op2);
4010
}
4011
4012
4013
void Simulator::VisitAddSubWithCarry(const Instruction* instr) {
4014
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
4015
int64_t op2 = ReadRegister(reg_size, instr->GetRm());
4016
int64_t new_val;
4017
4018
if ((instr->Mask(AddSubOpMask) == SUB) ||
4019
(instr->Mask(AddSubOpMask) == SUBS)) {
4020
op2 = ~op2;
4021
}
4022
4023
new_val = AddWithCarry(reg_size,
4024
instr->GetFlagsUpdate(),
4025
ReadRegister(reg_size, instr->GetRn()),
4026
op2,
4027
ReadC());
4028
4029
WriteRegister(reg_size, instr->GetRd(), new_val);
4030
}
4031
4032
4033
void Simulator::VisitRotateRightIntoFlags(const Instruction* instr) {
4034
switch (instr->Mask(RotateRightIntoFlagsMask)) {
4035
case RMIF: {
4036
uint64_t value = ReadRegister<uint64_t>(instr->GetRn());
4037
unsigned shift = instr->GetImmRMIFRotation();
4038
unsigned mask = instr->GetNzcv();
4039
uint64_t rotated = RotateRight(value, shift, kXRegSize);
4040
4041
ReadNzcv().SetFlags((rotated & mask) | (ReadNzcv().GetFlags() & ~mask));
4042
break;
4043
}
4044
}
4045
}
4046
4047
4048
void Simulator::VisitEvaluateIntoFlags(const Instruction* instr) {
4049
uint32_t value = ReadRegister<uint32_t>(instr->GetRn());
4050
unsigned msb = (instr->Mask(EvaluateIntoFlagsMask) == SETF16) ? 15 : 7;
4051
4052
unsigned sign_bit = (value >> msb) & 1;
4053
unsigned overflow_bit = (value >> (msb + 1)) & 1;
4054
ReadNzcv().SetN(sign_bit);
4055
ReadNzcv().SetZ((value << (31 - msb)) == 0);
4056
ReadNzcv().SetV(sign_bit ^ overflow_bit);
4057
}
4058
4059
4060
void Simulator::VisitLogicalShifted(const Instruction* instr) {
4061
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
4062
Shift shift_type = static_cast<Shift>(instr->GetShiftDP());
4063
unsigned shift_amount = instr->GetImmDPShift();
4064
int64_t op2 = ShiftOperand(reg_size,
4065
ReadRegister(reg_size, instr->GetRm()),
4066
shift_type,
4067
shift_amount);
4068
if (instr->Mask(NOT) == NOT) {
4069
op2 = ~op2;
4070
}
4071
LogicalHelper(instr, op2);
4072
}
4073
4074
4075
void Simulator::VisitLogicalImmediate(const Instruction* instr) {
4076
if (instr->GetImmLogical() == 0) {
4077
VIXL_UNIMPLEMENTED();
4078
} else {
4079
LogicalHelper(instr, instr->GetImmLogical());
4080
}
4081
}
4082
4083
4084
void Simulator::LogicalHelper(const Instruction* instr, int64_t op2) {
4085
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
4086
int64_t op1 = ReadRegister(reg_size, instr->GetRn());
4087
int64_t result = 0;
4088
bool update_flags = false;
4089
4090
// Switch on the logical operation, stripping out the NOT bit, as it has a
4091
// different meaning for logical immediate instructions.
4092
switch (instr->Mask(LogicalOpMask & ~NOT)) {
4093
case ANDS:
4094
update_flags = true;
4095
VIXL_FALLTHROUGH();
4096
case AND:
4097
result = op1 & op2;
4098
break;
4099
case ORR:
4100
result = op1 | op2;
4101
break;
4102
case EOR:
4103
result = op1 ^ op2;
4104
break;
4105
default:
4106
VIXL_UNIMPLEMENTED();
4107
}
4108
4109
if (update_flags) {
4110
ReadNzcv().SetN(CalcNFlag(result, reg_size));
4111
ReadNzcv().SetZ(CalcZFlag(result));
4112
ReadNzcv().SetC(0);
4113
ReadNzcv().SetV(0);
4114
LogSystemRegister(NZCV);
4115
}
4116
4117
WriteRegister(reg_size,
4118
instr->GetRd(),
4119
result,
4120
LogRegWrites,
4121
instr->GetRdMode());
4122
}
4123
4124
4125
void Simulator::VisitConditionalCompareRegister(const Instruction* instr) {
4126
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
4127
ConditionalCompareHelper(instr, ReadRegister(reg_size, instr->GetRm()));
4128
}
4129
4130
4131
void Simulator::VisitConditionalCompareImmediate(const Instruction* instr) {
4132
ConditionalCompareHelper(instr, instr->GetImmCondCmp());
4133
}
4134
4135
4136
void Simulator::ConditionalCompareHelper(const Instruction* instr,
4137
int64_t op2) {
4138
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
4139
int64_t op1 = ReadRegister(reg_size, instr->GetRn());
4140
4141
if (ConditionPassed(instr->GetCondition())) {
4142
// If the condition passes, set the status flags to the result of comparing
4143
// the operands.
4144
if (instr->Mask(ConditionalCompareMask) == CCMP) {
4145
AddWithCarry(reg_size, true, op1, ~op2, 1);
4146
} else {
4147
VIXL_ASSERT(instr->Mask(ConditionalCompareMask) == CCMN);
4148
AddWithCarry(reg_size, true, op1, op2, 0);
4149
}
4150
} else {
4151
// If the condition fails, set the status flags to the nzcv immediate.
4152
ReadNzcv().SetFlags(instr->GetNzcv());
4153
LogSystemRegister(NZCV);
4154
}
4155
}
4156
4157
4158
void Simulator::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
4159
int offset = instr->GetImmLSUnsigned() << instr->GetSizeLS();
4160
LoadStoreHelper(instr, offset, Offset);
4161
}
4162
4163
4164
void Simulator::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
4165
LoadStoreHelper(instr, instr->GetImmLS(), Offset);
4166
}
4167
4168
4169
void Simulator::VisitLoadStorePreIndex(const Instruction* instr) {
4170
LoadStoreHelper(instr, instr->GetImmLS(), PreIndex);
4171
}
4172
4173
4174
void Simulator::VisitLoadStorePostIndex(const Instruction* instr) {
4175
LoadStoreHelper(instr, instr->GetImmLS(), PostIndex);
4176
}
4177
4178
4179
template <typename T1, typename T2>
4180
void Simulator::LoadAcquireRCpcUnscaledOffsetHelper(const Instruction* instr) {
4181
unsigned rt = instr->GetRt();
4182
unsigned rn = instr->GetRn();
4183
4184
unsigned element_size = sizeof(T2);
4185
uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4186
int offset = instr->GetImmLS();
4187
address += offset;
4188
4189
// Verify that the address is available to the host.
4190
VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4191
4192
// Check the alignment of `address`.
4193
if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
4194
VIXL_ALIGNMENT_EXCEPTION();
4195
}
4196
4197
VIXL_DEFINE_OR_RETURN(value, MemRead<T2>(address));
4198
4199
WriteRegister<T1>(rt, static_cast<T1>(value));
4200
4201
// Approximate load-acquire by issuing a full barrier after the load.
4202
__sync_synchronize();
4203
4204
LogRead(rt, GetPrintRegisterFormat(element_size), address);
4205
}
4206
4207
4208
template <typename T>
4209
void Simulator::StoreReleaseUnscaledOffsetHelper(const Instruction* instr) {
4210
unsigned rt = instr->GetRt();
4211
unsigned rn = instr->GetRn();
4212
4213
unsigned element_size = sizeof(T);
4214
uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4215
int offset = instr->GetImmLS();
4216
address += offset;
4217
4218
// Verify that the address is available to the host.
4219
VIXL_ASSERT(address == static_cast<uintptr_t>(address));
4220
4221
// Check the alignment of `address`.
4222
if (AlignDown(address, 16) != AlignDown(address + element_size - 1, 16)) {
4223
VIXL_ALIGNMENT_EXCEPTION();
4224
}
4225
4226
// Approximate store-release by issuing a full barrier after the load.
4227
__sync_synchronize();
4228
4229
if (!MemWrite<T>(address, ReadRegister<T>(rt))) return;
4230
4231
LogWrite(rt, GetPrintRegisterFormat(element_size), address);
4232
}
4233
4234
4235
void Simulator::VisitLoadStoreRCpcUnscaledOffset(const Instruction* instr) {
4236
switch (instr->Mask(LoadStoreRCpcUnscaledOffsetMask)) {
4237
case LDAPURB:
4238
LoadAcquireRCpcUnscaledOffsetHelper<uint8_t, uint8_t>(instr);
4239
break;
4240
case LDAPURH:
4241
LoadAcquireRCpcUnscaledOffsetHelper<uint16_t, uint16_t>(instr);
4242
break;
4243
case LDAPUR_w:
4244
LoadAcquireRCpcUnscaledOffsetHelper<uint32_t, uint32_t>(instr);
4245
break;
4246
case LDAPUR_x:
4247
LoadAcquireRCpcUnscaledOffsetHelper<uint64_t, uint64_t>(instr);
4248
break;
4249
case LDAPURSB_w:
4250
LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int8_t>(instr);
4251
break;
4252
case LDAPURSB_x:
4253
LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int8_t>(instr);
4254
break;
4255
case LDAPURSH_w:
4256
LoadAcquireRCpcUnscaledOffsetHelper<int32_t, int16_t>(instr);
4257
break;
4258
case LDAPURSH_x:
4259
LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int16_t>(instr);
4260
break;
4261
case LDAPURSW:
4262
LoadAcquireRCpcUnscaledOffsetHelper<int64_t, int32_t>(instr);
4263
break;
4264
case STLURB:
4265
StoreReleaseUnscaledOffsetHelper<uint8_t>(instr);
4266
break;
4267
case STLURH:
4268
StoreReleaseUnscaledOffsetHelper<uint16_t>(instr);
4269
break;
4270
case STLUR_w:
4271
StoreReleaseUnscaledOffsetHelper<uint32_t>(instr);
4272
break;
4273
case STLUR_x:
4274
StoreReleaseUnscaledOffsetHelper<uint64_t>(instr);
4275
break;
4276
}
4277
}
4278
4279
4280
void Simulator::VisitLoadStorePAC(const Instruction* instr) {
4281
unsigned dst = instr->GetRt();
4282
unsigned addr_reg = instr->GetRn();
4283
4284
uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
4285
4286
PACKey key = (instr->ExtractBit(23) == 0) ? kPACKeyDA : kPACKeyDB;
4287
address = AuthPAC(address, 0, key, kDataPointer);
4288
4289
int error_lsb = GetTopPACBit(address, kInstructionPointer) - 2;
4290
if (((address >> error_lsb) & 0x3) != 0x0) {
4291
VIXL_ABORT_WITH_MSG("Failed to authenticate pointer.");
4292
}
4293
4294
4295
if ((addr_reg == 31) && ((address % 16) != 0)) {
4296
// When the base register is SP the stack pointer is required to be
4297
// quadword aligned prior to the address calculation and write-backs.
4298
// Misalignment will cause a stack alignment fault.
4299
VIXL_ALIGNMENT_EXCEPTION();
4300
}
4301
4302
int64_t offset = instr->GetImmLSPAC();
4303
address += offset;
4304
4305
if (instr->Mask(LoadStorePACPreBit) == LoadStorePACPreBit) {
4306
// Pre-index mode.
4307
VIXL_ASSERT(offset != 0);
4308
WriteXRegister(addr_reg, address, LogRegWrites, Reg31IsStackPointer);
4309
}
4310
4311
uintptr_t addr_ptr = static_cast<uintptr_t>(address);
4312
4313
// Verify that the calculated address is available to the host.
4314
VIXL_ASSERT(address == addr_ptr);
4315
4316
VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(addr_ptr));
4317
4318
WriteXRegister(dst, value, NoRegLog);
4319
unsigned access_size = 1 << 3;
4320
LogRead(dst, GetPrintRegisterFormatForSize(access_size), addr_ptr);
4321
}
4322
4323
4324
void Simulator::VisitLoadStoreRegisterOffset(const Instruction* instr) {
4325
Extend ext = static_cast<Extend>(instr->GetExtendMode());
4326
VIXL_ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
4327
unsigned shift_amount = instr->GetImmShiftLS() * instr->GetSizeLS();
4328
4329
int64_t offset =
4330
ExtendValue(kXRegSize, ReadXRegister(instr->GetRm()), ext, shift_amount);
4331
LoadStoreHelper(instr, offset, Offset);
4332
}
4333
4334
4335
void Simulator::LoadStoreHelper(const Instruction* instr,
4336
int64_t offset,
4337
AddrMode addrmode) {
4338
unsigned srcdst = instr->GetRt();
4339
uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4340
4341
bool rt_is_vreg = false;
4342
int extend_to_size = 0;
4343
LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
4344
switch (op) {
4345
case LDRB_w: {
4346
VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address));
4347
WriteWRegister(srcdst, value, NoRegLog);
4348
extend_to_size = kWRegSizeInBytes;
4349
break;
4350
}
4351
case LDRH_w: {
4352
VIXL_DEFINE_OR_RETURN(value, MemRead<uint16_t>(address));
4353
WriteWRegister(srcdst, value, NoRegLog);
4354
extend_to_size = kWRegSizeInBytes;
4355
break;
4356
}
4357
case LDR_w: {
4358
VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));
4359
WriteWRegister(srcdst, value, NoRegLog);
4360
extend_to_size = kWRegSizeInBytes;
4361
break;
4362
}
4363
case LDR_x: {
4364
VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));
4365
WriteXRegister(srcdst, value, NoRegLog);
4366
extend_to_size = kXRegSizeInBytes;
4367
break;
4368
}
4369
case LDRSB_w: {
4370
VIXL_DEFINE_OR_RETURN(value, MemRead<int8_t>(address));
4371
WriteWRegister(srcdst, value, NoRegLog);
4372
extend_to_size = kWRegSizeInBytes;
4373
break;
4374
}
4375
case LDRSH_w: {
4376
VIXL_DEFINE_OR_RETURN(value, MemRead<int16_t>(address));
4377
WriteWRegister(srcdst, value, NoRegLog);
4378
extend_to_size = kWRegSizeInBytes;
4379
break;
4380
}
4381
case LDRSB_x: {
4382
VIXL_DEFINE_OR_RETURN(value, MemRead<int8_t>(address));
4383
WriteXRegister(srcdst, value, NoRegLog);
4384
extend_to_size = kXRegSizeInBytes;
4385
break;
4386
}
4387
case LDRSH_x: {
4388
VIXL_DEFINE_OR_RETURN(value, MemRead<int16_t>(address));
4389
WriteXRegister(srcdst, value, NoRegLog);
4390
extend_to_size = kXRegSizeInBytes;
4391
break;
4392
}
4393
case LDRSW_x: {
4394
VIXL_DEFINE_OR_RETURN(value, MemRead<int32_t>(address));
4395
WriteXRegister(srcdst, value, NoRegLog);
4396
extend_to_size = kXRegSizeInBytes;
4397
break;
4398
}
4399
case LDR_b: {
4400
VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address));
4401
WriteBRegister(srcdst, value, NoRegLog);
4402
rt_is_vreg = true;
4403
break;
4404
}
4405
case LDR_h: {
4406
VIXL_DEFINE_OR_RETURN(value, MemRead<uint16_t>(address));
4407
WriteHRegister(srcdst, value, NoRegLog);
4408
rt_is_vreg = true;
4409
break;
4410
}
4411
case LDR_s: {
4412
VIXL_DEFINE_OR_RETURN(value, MemRead<float>(address));
4413
WriteSRegister(srcdst, value, NoRegLog);
4414
rt_is_vreg = true;
4415
break;
4416
}
4417
case LDR_d: {
4418
VIXL_DEFINE_OR_RETURN(value, MemRead<double>(address));
4419
WriteDRegister(srcdst, value, NoRegLog);
4420
rt_is_vreg = true;
4421
break;
4422
}
4423
case LDR_q: {
4424
VIXL_DEFINE_OR_RETURN(value, MemRead<qreg_t>(address));
4425
WriteQRegister(srcdst, value, NoRegLog);
4426
rt_is_vreg = true;
4427
break;
4428
}
4429
4430
case STRB_w:
4431
if (!MemWrite<uint8_t>(address, ReadWRegister(srcdst))) return;
4432
break;
4433
case STRH_w:
4434
if (!MemWrite<uint16_t>(address, ReadWRegister(srcdst))) return;
4435
break;
4436
case STR_w:
4437
if (!MemWrite<uint32_t>(address, ReadWRegister(srcdst))) return;
4438
break;
4439
case STR_x:
4440
if (!MemWrite<uint64_t>(address, ReadXRegister(srcdst))) return;
4441
break;
4442
case STR_b:
4443
if (!MemWrite<uint8_t>(address, ReadBRegister(srcdst))) return;
4444
rt_is_vreg = true;
4445
break;
4446
case STR_h:
4447
if (!MemWrite<uint16_t>(address, ReadHRegisterBits(srcdst))) return;
4448
rt_is_vreg = true;
4449
break;
4450
case STR_s:
4451
if (!MemWrite<float>(address, ReadSRegister(srcdst))) return;
4452
rt_is_vreg = true;
4453
break;
4454
case STR_d:
4455
if (!MemWrite<double>(address, ReadDRegister(srcdst))) return;
4456
rt_is_vreg = true;
4457
break;
4458
case STR_q:
4459
if (!MemWrite<qreg_t>(address, ReadQRegister(srcdst))) return;
4460
rt_is_vreg = true;
4461
break;
4462
4463
// Ignore prfm hint instructions.
4464
case PRFM:
4465
break;
4466
4467
default:
4468
VIXL_UNIMPLEMENTED();
4469
}
4470
4471
// Print a detailed trace (including the memory address).
4472
bool extend = (extend_to_size != 0);
4473
unsigned access_size = 1 << instr->GetSizeLS();
4474
unsigned result_size = extend ? extend_to_size : access_size;
4475
PrintRegisterFormat print_format =
4476
rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4477
: GetPrintRegisterFormatForSize(result_size);
4478
4479
if (instr->IsLoad()) {
4480
if (rt_is_vreg) {
4481
LogVRead(srcdst, print_format, address);
4482
} else {
4483
LogExtendingRead(srcdst, print_format, access_size, address);
4484
}
4485
} else if (instr->IsStore()) {
4486
if (rt_is_vreg) {
4487
LogVWrite(srcdst, print_format, address);
4488
} else {
4489
LogWrite(srcdst, GetPrintRegisterFormatForSize(result_size), address);
4490
}
4491
} else {
4492
VIXL_ASSERT(op == PRFM);
4493
}
4494
4495
local_monitor_.MaybeClear();
4496
}
4497
4498
4499
void Simulator::VisitLoadStorePairOffset(const Instruction* instr) {
4500
LoadStorePairHelper(instr, Offset);
4501
}
4502
4503
4504
void Simulator::VisitLoadStorePairPreIndex(const Instruction* instr) {
4505
LoadStorePairHelper(instr, PreIndex);
4506
}
4507
4508
4509
void Simulator::VisitLoadStorePairPostIndex(const Instruction* instr) {
4510
LoadStorePairHelper(instr, PostIndex);
4511
}
4512
4513
4514
void Simulator::VisitLoadStorePairNonTemporal(const Instruction* instr) {
4515
LoadStorePairHelper(instr, Offset);
4516
}
4517
4518
4519
void Simulator::LoadStorePairHelper(const Instruction* instr,
4520
AddrMode addrmode) {
4521
unsigned rt = instr->GetRt();
4522
unsigned rt2 = instr->GetRt2();
4523
int element_size = 1 << instr->GetSizeLSPair();
4524
int64_t offset = instr->GetImmLSPair() * element_size;
4525
uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addrmode);
4526
uintptr_t address2 = address + element_size;
4527
4528
LoadStorePairOp op =
4529
static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
4530
4531
// 'rt' and 'rt2' can only be aliased for stores.
4532
VIXL_ASSERT(((op & LoadStorePairLBit) == 0) || (rt != rt2));
4533
4534
bool rt_is_vreg = false;
4535
bool sign_extend = false;
4536
switch (op) {
4537
// Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS). We
4538
// will print a more detailed log.
4539
case LDP_w: {
4540
VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));
4541
VIXL_DEFINE_OR_RETURN(value2, MemRead<uint32_t>(address2));
4542
WriteWRegister(rt, value, NoRegLog);
4543
WriteWRegister(rt2, value2, NoRegLog);
4544
break;
4545
}
4546
case LDP_s: {
4547
VIXL_DEFINE_OR_RETURN(value, MemRead<float>(address));
4548
VIXL_DEFINE_OR_RETURN(value2, MemRead<float>(address2));
4549
WriteSRegister(rt, value, NoRegLog);
4550
WriteSRegister(rt2, value2, NoRegLog);
4551
rt_is_vreg = true;
4552
break;
4553
}
4554
case LDP_x: {
4555
VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));
4556
VIXL_DEFINE_OR_RETURN(value2, MemRead<uint64_t>(address2));
4557
WriteXRegister(rt, value, NoRegLog);
4558
WriteXRegister(rt2, value2, NoRegLog);
4559
break;
4560
}
4561
case LDP_d: {
4562
VIXL_DEFINE_OR_RETURN(value, MemRead<double>(address));
4563
VIXL_DEFINE_OR_RETURN(value2, MemRead<double>(address2));
4564
WriteDRegister(rt, value, NoRegLog);
4565
WriteDRegister(rt2, value2, NoRegLog);
4566
rt_is_vreg = true;
4567
break;
4568
}
4569
case LDP_q: {
4570
VIXL_DEFINE_OR_RETURN(value, MemRead<qreg_t>(address));
4571
VIXL_DEFINE_OR_RETURN(value2, MemRead<qreg_t>(address2));
4572
WriteQRegister(rt, value, NoRegLog);
4573
WriteQRegister(rt2, value2, NoRegLog);
4574
rt_is_vreg = true;
4575
break;
4576
}
4577
case LDPSW_x: {
4578
VIXL_DEFINE_OR_RETURN(value, MemRead<int32_t>(address));
4579
VIXL_DEFINE_OR_RETURN(value2, MemRead<int32_t>(address2));
4580
WriteXRegister(rt, value, NoRegLog);
4581
WriteXRegister(rt2, value2, NoRegLog);
4582
sign_extend = true;
4583
break;
4584
}
4585
case STP_w: {
4586
if (!MemWrite<uint32_t>(address, ReadWRegister(rt))) return;
4587
if (!MemWrite<uint32_t>(address2, ReadWRegister(rt2))) return;
4588
break;
4589
}
4590
case STP_s: {
4591
if (!MemWrite<float>(address, ReadSRegister(rt))) return;
4592
if (!MemWrite<float>(address2, ReadSRegister(rt2))) return;
4593
rt_is_vreg = true;
4594
break;
4595
}
4596
case STP_x: {
4597
if (!MemWrite<uint64_t>(address, ReadXRegister(rt))) return;
4598
if (!MemWrite<uint64_t>(address2, ReadXRegister(rt2))) return;
4599
break;
4600
}
4601
case STP_d: {
4602
if (!MemWrite<double>(address, ReadDRegister(rt))) return;
4603
if (!MemWrite<double>(address2, ReadDRegister(rt2))) return;
4604
rt_is_vreg = true;
4605
break;
4606
}
4607
case STP_q: {
4608
if (!MemWrite<qreg_t>(address, ReadQRegister(rt))) return;
4609
if (!MemWrite<qreg_t>(address2, ReadQRegister(rt2))) return;
4610
rt_is_vreg = true;
4611
break;
4612
}
4613
default:
4614
VIXL_UNREACHABLE();
4615
}
4616
4617
// Print a detailed trace (including the memory address).
4618
unsigned result_size = sign_extend ? kXRegSizeInBytes : element_size;
4619
PrintRegisterFormat print_format =
4620
rt_is_vreg ? GetPrintRegisterFormatForSizeTryFP(result_size)
4621
: GetPrintRegisterFormatForSize(result_size);
4622
4623
if (instr->IsLoad()) {
4624
if (rt_is_vreg) {
4625
LogVRead(rt, print_format, address);
4626
LogVRead(rt2, print_format, address2);
4627
} else if (sign_extend) {
4628
LogExtendingRead(rt, print_format, element_size, address);
4629
LogExtendingRead(rt2, print_format, element_size, address2);
4630
} else {
4631
LogRead(rt, print_format, address);
4632
LogRead(rt2, print_format, address2);
4633
}
4634
} else {
4635
if (rt_is_vreg) {
4636
LogVWrite(rt, print_format, address);
4637
LogVWrite(rt2, print_format, address2);
4638
} else {
4639
LogWrite(rt, print_format, address);
4640
LogWrite(rt2, print_format, address2);
4641
}
4642
}
4643
4644
local_monitor_.MaybeClear();
4645
}
4646
4647
4648
template <typename T>
4649
void Simulator::CompareAndSwapHelper(const Instruction* instr) {
4650
unsigned rs = instr->GetRs();
4651
unsigned rt = instr->GetRt();
4652
unsigned rn = instr->GetRn();
4653
4654
unsigned element_size = sizeof(T);
4655
uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4656
4657
CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
4658
4659
bool is_acquire = instr->ExtractBit(22) == 1;
4660
bool is_release = instr->ExtractBit(15) == 1;
4661
4662
T comparevalue = ReadRegister<T>(rs);
4663
T newvalue = ReadRegister<T>(rt);
4664
4665
// The architecture permits that the data read clears any exclusive monitors
4666
// associated with that location, even if the compare subsequently fails.
4667
local_monitor_.Clear();
4668
4669
VIXL_DEFINE_OR_RETURN(data, MemRead<T>(address));
4670
4671
if (is_acquire) {
4672
// Approximate load-acquire by issuing a full barrier after the load.
4673
__sync_synchronize();
4674
}
4675
4676
if (data == comparevalue) {
4677
if (is_release) {
4678
// Approximate store-release by issuing a full barrier before the store.
4679
__sync_synchronize();
4680
}
4681
if (!MemWrite<T>(address, newvalue)) return;
4682
LogWrite(rt, GetPrintRegisterFormatForSize(element_size), address);
4683
}
4684
WriteRegister<T>(rs, data, NoRegLog);
4685
LogRead(rs, GetPrintRegisterFormatForSize(element_size), address);
4686
}
4687
4688
4689
template <typename T>
4690
void Simulator::CompareAndSwapPairHelper(const Instruction* instr) {
4691
VIXL_ASSERT((sizeof(T) == 4) || (sizeof(T) == 8));
4692
unsigned rs = instr->GetRs();
4693
unsigned rt = instr->GetRt();
4694
unsigned rn = instr->GetRn();
4695
4696
VIXL_ASSERT((rs % 2 == 0) && (rt % 2 == 0));
4697
4698
unsigned element_size = sizeof(T);
4699
uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4700
4701
CheckIsValidUnalignedAtomicAccess(rn, address, element_size * 2);
4702
4703
uint64_t address2 = address + element_size;
4704
4705
bool is_acquire = instr->ExtractBit(22) == 1;
4706
bool is_release = instr->ExtractBit(15) == 1;
4707
4708
T comparevalue_high = ReadRegister<T>(rs + 1);
4709
T comparevalue_low = ReadRegister<T>(rs);
4710
T newvalue_high = ReadRegister<T>(rt + 1);
4711
T newvalue_low = ReadRegister<T>(rt);
4712
4713
// The architecture permits that the data read clears any exclusive monitors
4714
// associated with that location, even if the compare subsequently fails.
4715
local_monitor_.Clear();
4716
4717
VIXL_DEFINE_OR_RETURN(data_low, MemRead<T>(address));
4718
VIXL_DEFINE_OR_RETURN(data_high, MemRead<T>(address2));
4719
4720
if (is_acquire) {
4721
// Approximate load-acquire by issuing a full barrier after the load.
4722
__sync_synchronize();
4723
}
4724
4725
bool same =
4726
(data_high == comparevalue_high) && (data_low == comparevalue_low);
4727
if (same) {
4728
if (is_release) {
4729
// Approximate store-release by issuing a full barrier before the store.
4730
__sync_synchronize();
4731
}
4732
4733
if (!MemWrite<T>(address, newvalue_low)) return;
4734
if (!MemWrite<T>(address2, newvalue_high)) return;
4735
}
4736
4737
WriteRegister<T>(rs + 1, data_high, NoRegLog);
4738
WriteRegister<T>(rs, data_low, NoRegLog);
4739
4740
PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
4741
LogRead(rs, format, address);
4742
LogRead(rs + 1, format, address2);
4743
4744
if (same) {
4745
LogWrite(rt, format, address);
4746
LogWrite(rt + 1, format, address2);
4747
}
4748
}
4749
4750
bool Simulator::CanReadMemory(uintptr_t address, size_t size) {
4751
// To simulate fault-tolerant loads, we need to know what host addresses we
4752
// can access without generating a real fault. One way to do that is to
4753
// attempt to `write()` the memory to a placeholder pipe[1]. This is more
4754
// portable and less intrusive than using (global) signal handlers.
4755
//
4756
// [1]: https://stackoverflow.com/questions/7134590
4757
4758
size_t written = 0;
4759
bool can_read = true;
4760
// `write` will normally return after one invocation, but it is allowed to
4761
// handle only part of the operation, so wrap it in a loop.
4762
while (can_read && (written < size)) {
4763
ssize_t result = write(placeholder_pipe_fd_[1],
4764
reinterpret_cast<void*>(address + written),
4765
size - written);
4766
if (result > 0) {
4767
written += result;
4768
} else {
4769
switch (result) {
4770
case -EPERM:
4771
case -EFAULT:
4772
// The address range is not accessible.
4773
// `write` is supposed to return -EFAULT in this case, but in practice
4774
// it seems to return -EPERM, so we accept that too.
4775
can_read = false;
4776
break;
4777
case -EINTR:
4778
// The call was interrupted by a signal. Just try again.
4779
break;
4780
default:
4781
// Any other error is fatal.
4782
VIXL_ABORT();
4783
}
4784
}
4785
}
4786
// Drain the read side of the pipe. If we don't do this, we'll leak memory as
4787
// the placeholder data is buffered. As before, we expect to drain the whole
4788
// write in one invocation, but cannot guarantee that, so we wrap it in a
4789
// loop. This function is primarily intended to implement SVE fault-tolerant
4790
// loads, so the maximum Z register size is a good default buffer size.
4791
char buffer[kZRegMaxSizeInBytes];
4792
while (written > 0) {
4793
ssize_t result = read(placeholder_pipe_fd_[0],
4794
reinterpret_cast<void*>(buffer),
4795
sizeof(buffer));
4796
// `read` blocks, and returns 0 only at EOF. We should not hit EOF until
4797
// we've read everything that was written, so treat 0 as an error.
4798
if (result > 0) {
4799
VIXL_ASSERT(static_cast<size_t>(result) <= written);
4800
written -= result;
4801
} else {
4802
// For -EINTR, just try again. We can't handle any other error.
4803
VIXL_CHECK(result == -EINTR);
4804
}
4805
}
4806
4807
return can_read;
4808
}
4809
4810
void Simulator::PrintExclusiveAccessWarning() {
4811
if (print_exclusive_access_warning_) {
4812
fprintf(stderr,
4813
"%sWARNING:%s VIXL simulator support for "
4814
"load-/store-/clear-exclusive "
4815
"instructions is limited. Refer to the README for details.%s\n",
4816
clr_warning,
4817
clr_warning_message,
4818
clr_normal);
4819
print_exclusive_access_warning_ = false;
4820
}
4821
}
4822
4823
void Simulator::VisitLoadStoreExclusive(const Instruction* instr) {
4824
LoadStoreExclusive op =
4825
static_cast<LoadStoreExclusive>(instr->Mask(LoadStoreExclusiveMask));
4826
4827
switch (op) {
4828
case CAS_w:
4829
case CASA_w:
4830
case CASL_w:
4831
case CASAL_w:
4832
CompareAndSwapHelper<uint32_t>(instr);
4833
break;
4834
case CAS_x:
4835
case CASA_x:
4836
case CASL_x:
4837
case CASAL_x:
4838
CompareAndSwapHelper<uint64_t>(instr);
4839
break;
4840
case CASB:
4841
case CASAB:
4842
case CASLB:
4843
case CASALB:
4844
CompareAndSwapHelper<uint8_t>(instr);
4845
break;
4846
case CASH:
4847
case CASAH:
4848
case CASLH:
4849
case CASALH:
4850
CompareAndSwapHelper<uint16_t>(instr);
4851
break;
4852
case CASP_w:
4853
case CASPA_w:
4854
case CASPL_w:
4855
case CASPAL_w:
4856
CompareAndSwapPairHelper<uint32_t>(instr);
4857
break;
4858
case CASP_x:
4859
case CASPA_x:
4860
case CASPL_x:
4861
case CASPAL_x:
4862
CompareAndSwapPairHelper<uint64_t>(instr);
4863
break;
4864
default:
4865
PrintExclusiveAccessWarning();
4866
4867
unsigned rs = instr->GetRs();
4868
unsigned rt = instr->GetRt();
4869
unsigned rt2 = instr->GetRt2();
4870
unsigned rn = instr->GetRn();
4871
4872
bool is_exclusive = !instr->GetLdStXNotExclusive();
4873
bool is_acquire_release =
4874
!is_exclusive || instr->GetLdStXAcquireRelease();
4875
bool is_load = instr->GetLdStXLoad();
4876
bool is_pair = instr->GetLdStXPair();
4877
4878
unsigned element_size = 1 << instr->GetLdStXSizeLog2();
4879
unsigned access_size = is_pair ? element_size * 2 : element_size;
4880
uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
4881
4882
CheckIsValidUnalignedAtomicAccess(rn, address, access_size);
4883
4884
if (is_load) {
4885
if (is_exclusive) {
4886
local_monitor_.MarkExclusive(address, access_size);
4887
} else {
4888
// Any non-exclusive load can clear the local monitor as a side
4889
// effect. We don't need to do this, but it is useful to stress the
4890
// simulated code.
4891
local_monitor_.Clear();
4892
}
4893
4894
// Use NoRegLog to suppress the register trace (LOG_REGS, LOG_FP_REGS).
4895
// We will print a more detailed log.
4896
unsigned reg_size = 0;
4897
switch (op) {
4898
case LDXRB_w:
4899
case LDAXRB_w:
4900
case LDARB_w:
4901
case LDLARB: {
4902
VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address));
4903
WriteWRegister(rt, value, NoRegLog);
4904
reg_size = kWRegSizeInBytes;
4905
break;
4906
}
4907
case LDXRH_w:
4908
case LDAXRH_w:
4909
case LDARH_w:
4910
case LDLARH: {
4911
VIXL_DEFINE_OR_RETURN(value, MemRead<uint16_t>(address));
4912
WriteWRegister(rt, value, NoRegLog);
4913
reg_size = kWRegSizeInBytes;
4914
break;
4915
}
4916
case LDXR_w:
4917
case LDAXR_w:
4918
case LDAR_w:
4919
case LDLAR_w: {
4920
VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));
4921
WriteWRegister(rt, value, NoRegLog);
4922
reg_size = kWRegSizeInBytes;
4923
break;
4924
}
4925
case LDXR_x:
4926
case LDAXR_x:
4927
case LDAR_x:
4928
case LDLAR_x: {
4929
VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));
4930
WriteXRegister(rt, value, NoRegLog);
4931
reg_size = kXRegSizeInBytes;
4932
break;
4933
}
4934
case LDXP_w:
4935
case LDAXP_w: {
4936
VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));
4937
VIXL_DEFINE_OR_RETURN(value2,
4938
MemRead<uint32_t>(address + element_size));
4939
WriteWRegister(rt, value, NoRegLog);
4940
WriteWRegister(rt2, value2, NoRegLog);
4941
reg_size = kWRegSizeInBytes;
4942
break;
4943
}
4944
case LDXP_x:
4945
case LDAXP_x: {
4946
VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));
4947
VIXL_DEFINE_OR_RETURN(value2,
4948
MemRead<uint64_t>(address + element_size));
4949
WriteXRegister(rt, value, NoRegLog);
4950
WriteXRegister(rt2, value2, NoRegLog);
4951
reg_size = kXRegSizeInBytes;
4952
break;
4953
}
4954
default:
4955
VIXL_UNREACHABLE();
4956
}
4957
4958
if (is_acquire_release) {
4959
// Approximate load-acquire by issuing a full barrier after the load.
4960
__sync_synchronize();
4961
}
4962
4963
PrintRegisterFormat format = GetPrintRegisterFormatForSize(reg_size);
4964
LogExtendingRead(rt, format, element_size, address);
4965
if (is_pair) {
4966
LogExtendingRead(rt2, format, element_size, address + element_size);
4967
}
4968
} else {
4969
if (is_acquire_release) {
4970
// Approximate store-release by issuing a full barrier before the
4971
// store.
4972
__sync_synchronize();
4973
}
4974
4975
bool do_store = true;
4976
if (is_exclusive) {
4977
do_store = local_monitor_.IsExclusive(address, access_size) &&
4978
global_monitor_.IsExclusive(address, access_size);
4979
WriteWRegister(rs, do_store ? 0 : 1);
4980
4981
// - All exclusive stores explicitly clear the local monitor.
4982
local_monitor_.Clear();
4983
} else {
4984
// - Any other store can clear the local monitor as a side effect.
4985
local_monitor_.MaybeClear();
4986
}
4987
4988
if (do_store) {
4989
switch (op) {
4990
case STXRB_w:
4991
case STLXRB_w:
4992
case STLRB_w:
4993
case STLLRB:
4994
if (!MemWrite<uint8_t>(address, ReadWRegister(rt))) return;
4995
break;
4996
case STXRH_w:
4997
case STLXRH_w:
4998
case STLRH_w:
4999
case STLLRH:
5000
if (!MemWrite<uint16_t>(address, ReadWRegister(rt))) return;
5001
break;
5002
case STXR_w:
5003
case STLXR_w:
5004
case STLR_w:
5005
case STLLR_w:
5006
if (!MemWrite<uint32_t>(address, ReadWRegister(rt))) return;
5007
break;
5008
case STXR_x:
5009
case STLXR_x:
5010
case STLR_x:
5011
case STLLR_x:
5012
if (!MemWrite<uint64_t>(address, ReadXRegister(rt))) return;
5013
break;
5014
case STXP_w:
5015
case STLXP_w:
5016
if (!MemWrite<uint32_t>(address, ReadWRegister(rt))) return;
5017
if (!MemWrite<uint32_t>(address + element_size,
5018
ReadWRegister(rt2))) {
5019
return;
5020
}
5021
break;
5022
case STXP_x:
5023
case STLXP_x:
5024
if (!MemWrite<uint64_t>(address, ReadXRegister(rt))) return;
5025
if (!MemWrite<uint64_t>(address + element_size,
5026
ReadXRegister(rt2))) {
5027
return;
5028
}
5029
break;
5030
default:
5031
VIXL_UNREACHABLE();
5032
}
5033
5034
PrintRegisterFormat format =
5035
GetPrintRegisterFormatForSize(element_size);
5036
LogWrite(rt, format, address);
5037
if (is_pair) {
5038
LogWrite(rt2, format, address + element_size);
5039
}
5040
}
5041
}
5042
}
5043
}
5044
5045
template <typename T>
5046
void Simulator::AtomicMemorySimpleHelper(const Instruction* instr) {
5047
unsigned rs = instr->GetRs();
5048
unsigned rt = instr->GetRt();
5049
unsigned rn = instr->GetRn();
5050
5051
bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
5052
bool is_release = instr->ExtractBit(22) == 1;
5053
5054
unsigned element_size = sizeof(T);
5055
uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
5056
5057
CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
5058
5059
T value = ReadRegister<T>(rs);
5060
5061
VIXL_DEFINE_OR_RETURN(data, MemRead<T>(address));
5062
5063
if (is_acquire) {
5064
// Approximate load-acquire by issuing a full barrier after the load.
5065
__sync_synchronize();
5066
}
5067
5068
T result = 0;
5069
switch (instr->Mask(AtomicMemorySimpleOpMask)) {
5070
case LDADDOp:
5071
result = data + value;
5072
break;
5073
case LDCLROp:
5074
VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
5075
result = data & ~value;
5076
break;
5077
case LDEOROp:
5078
VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
5079
result = data ^ value;
5080
break;
5081
case LDSETOp:
5082
VIXL_ASSERT(!std::numeric_limits<T>::is_signed);
5083
result = data | value;
5084
break;
5085
5086
// Signed/Unsigned difference is done via the templated type T.
5087
case LDSMAXOp:
5088
case LDUMAXOp:
5089
result = (data > value) ? data : value;
5090
break;
5091
case LDSMINOp:
5092
case LDUMINOp:
5093
result = (data > value) ? value : data;
5094
break;
5095
}
5096
5097
if (is_release) {
5098
// Approximate store-release by issuing a full barrier before the store.
5099
__sync_synchronize();
5100
}
5101
5102
WriteRegister<T>(rt, data, NoRegLog);
5103
5104
unsigned register_size = element_size;
5105
if (element_size < kXRegSizeInBytes) {
5106
register_size = kWRegSizeInBytes;
5107
}
5108
PrintRegisterFormat format = GetPrintRegisterFormatForSize(register_size);
5109
LogExtendingRead(rt, format, element_size, address);
5110
5111
if (!MemWrite<T>(address, result)) return;
5112
format = GetPrintRegisterFormatForSize(element_size);
5113
LogWrite(rs, format, address);
5114
}
5115
5116
template <typename T>
5117
void Simulator::AtomicMemorySwapHelper(const Instruction* instr) {
5118
unsigned rs = instr->GetRs();
5119
unsigned rt = instr->GetRt();
5120
unsigned rn = instr->GetRn();
5121
5122
bool is_acquire = (instr->ExtractBit(23) == 1) && (rt != kZeroRegCode);
5123
bool is_release = instr->ExtractBit(22) == 1;
5124
5125
unsigned element_size = sizeof(T);
5126
uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
5127
5128
CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
5129
5130
VIXL_DEFINE_OR_RETURN(data, MemRead<T>(address));
5131
5132
if (is_acquire) {
5133
// Approximate load-acquire by issuing a full barrier after the load.
5134
__sync_synchronize();
5135
}
5136
5137
if (is_release) {
5138
// Approximate store-release by issuing a full barrier before the store.
5139
__sync_synchronize();
5140
}
5141
if (!MemWrite<T>(address, ReadRegister<T>(rs))) return;
5142
5143
WriteRegister<T>(rt, data);
5144
5145
PrintRegisterFormat format = GetPrintRegisterFormatForSize(element_size);
5146
LogRead(rt, format, address);
5147
LogWrite(rs, format, address);
5148
}
5149
5150
template <typename T>
5151
void Simulator::LoadAcquireRCpcHelper(const Instruction* instr) {
5152
unsigned rt = instr->GetRt();
5153
unsigned rn = instr->GetRn();
5154
5155
unsigned element_size = sizeof(T);
5156
uint64_t address = ReadRegister<uint64_t>(rn, Reg31IsStackPointer);
5157
5158
CheckIsValidUnalignedAtomicAccess(rn, address, element_size);
5159
5160
VIXL_DEFINE_OR_RETURN(value, MemRead<T>(address));
5161
5162
WriteRegister<T>(rt, value);
5163
5164
// Approximate load-acquire by issuing a full barrier after the load.
5165
__sync_synchronize();
5166
5167
LogRead(rt, GetPrintRegisterFormatForSize(element_size), address);
5168
}
5169
5170
#define ATOMIC_MEMORY_SIMPLE_UINT_LIST(V) \
5171
V(LDADD) \
5172
V(LDCLR) \
5173
V(LDEOR) \
5174
V(LDSET) \
5175
V(LDUMAX) \
5176
V(LDUMIN)
5177
5178
#define ATOMIC_MEMORY_SIMPLE_INT_LIST(V) \
5179
V(LDSMAX) \
5180
V(LDSMIN)
5181
5182
void Simulator::VisitAtomicMemory(const Instruction* instr) {
5183
switch (instr->Mask(AtomicMemoryMask)) {
5184
// clang-format off
5185
#define SIM_FUNC_B(A) \
5186
case A##B: \
5187
case A##AB: \
5188
case A##LB: \
5189
case A##ALB:
5190
#define SIM_FUNC_H(A) \
5191
case A##H: \
5192
case A##AH: \
5193
case A##LH: \
5194
case A##ALH:
5195
#define SIM_FUNC_w(A) \
5196
case A##_w: \
5197
case A##A_w: \
5198
case A##L_w: \
5199
case A##AL_w:
5200
#define SIM_FUNC_x(A) \
5201
case A##_x: \
5202
case A##A_x: \
5203
case A##L_x: \
5204
case A##AL_x:
5205
5206
ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_B)
5207
AtomicMemorySimpleHelper<uint8_t>(instr);
5208
break;
5209
ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_B)
5210
AtomicMemorySimpleHelper<int8_t>(instr);
5211
break;
5212
ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_H)
5213
AtomicMemorySimpleHelper<uint16_t>(instr);
5214
break;
5215
ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_H)
5216
AtomicMemorySimpleHelper<int16_t>(instr);
5217
break;
5218
ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_w)
5219
AtomicMemorySimpleHelper<uint32_t>(instr);
5220
break;
5221
ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_w)
5222
AtomicMemorySimpleHelper<int32_t>(instr);
5223
break;
5224
ATOMIC_MEMORY_SIMPLE_UINT_LIST(SIM_FUNC_x)
5225
AtomicMemorySimpleHelper<uint64_t>(instr);
5226
break;
5227
ATOMIC_MEMORY_SIMPLE_INT_LIST(SIM_FUNC_x)
5228
AtomicMemorySimpleHelper<int64_t>(instr);
5229
break;
5230
// clang-format on
5231
5232
case SWPB:
5233
case SWPAB:
5234
case SWPLB:
5235
case SWPALB:
5236
AtomicMemorySwapHelper<uint8_t>(instr);
5237
break;
5238
case SWPH:
5239
case SWPAH:
5240
case SWPLH:
5241
case SWPALH:
5242
AtomicMemorySwapHelper<uint16_t>(instr);
5243
break;
5244
case SWP_w:
5245
case SWPA_w:
5246
case SWPL_w:
5247
case SWPAL_w:
5248
AtomicMemorySwapHelper<uint32_t>(instr);
5249
break;
5250
case SWP_x:
5251
case SWPA_x:
5252
case SWPL_x:
5253
case SWPAL_x:
5254
AtomicMemorySwapHelper<uint64_t>(instr);
5255
break;
5256
case LDAPRB:
5257
LoadAcquireRCpcHelper<uint8_t>(instr);
5258
break;
5259
case LDAPRH:
5260
LoadAcquireRCpcHelper<uint16_t>(instr);
5261
break;
5262
case LDAPR_w:
5263
LoadAcquireRCpcHelper<uint32_t>(instr);
5264
break;
5265
case LDAPR_x:
5266
LoadAcquireRCpcHelper<uint64_t>(instr);
5267
break;
5268
}
5269
}
5270
5271
5272
void Simulator::VisitLoadLiteral(const Instruction* instr) {
5273
unsigned rt = instr->GetRt();
5274
uint64_t address = instr->GetLiteralAddress<uint64_t>();
5275
5276
// Verify that the calculated address is available to the host.
5277
VIXL_ASSERT(address == static_cast<uintptr_t>(address));
5278
5279
switch (instr->Mask(LoadLiteralMask)) {
5280
// Use NoRegLog to suppress the register trace (LOG_REGS, LOG_VREGS), then
5281
// print a more detailed log.
5282
case LDR_w_lit: {
5283
VIXL_DEFINE_OR_RETURN(value, MemRead<uint32_t>(address));
5284
WriteWRegister(rt, value, NoRegLog);
5285
LogRead(rt, kPrintWReg, address);
5286
break;
5287
}
5288
case LDR_x_lit: {
5289
VIXL_DEFINE_OR_RETURN(value, MemRead<uint64_t>(address));
5290
WriteXRegister(rt, value, NoRegLog);
5291
LogRead(rt, kPrintXReg, address);
5292
break;
5293
}
5294
case LDR_s_lit: {
5295
VIXL_DEFINE_OR_RETURN(value, MemRead<float>(address));
5296
WriteSRegister(rt, value, NoRegLog);
5297
LogVRead(rt, kPrintSRegFP, address);
5298
break;
5299
}
5300
case LDR_d_lit: {
5301
VIXL_DEFINE_OR_RETURN(value, MemRead<double>(address));
5302
WriteDRegister(rt, value, NoRegLog);
5303
LogVRead(rt, kPrintDRegFP, address);
5304
break;
5305
}
5306
case LDR_q_lit: {
5307
VIXL_DEFINE_OR_RETURN(value, MemRead<qreg_t>(address));
5308
WriteQRegister(rt, value, NoRegLog);
5309
LogVRead(rt, kPrintReg1Q, address);
5310
break;
5311
}
5312
case LDRSW_x_lit: {
5313
VIXL_DEFINE_OR_RETURN(value, MemRead<int32_t>(address));
5314
WriteXRegister(rt, value, NoRegLog);
5315
LogExtendingRead(rt, kPrintXReg, kWRegSizeInBytes, address);
5316
break;
5317
}
5318
5319
// Ignore prfm hint instructions.
5320
case PRFM_lit:
5321
break;
5322
5323
default:
5324
VIXL_UNREACHABLE();
5325
}
5326
5327
local_monitor_.MaybeClear();
5328
}
5329
5330
5331
uintptr_t Simulator::AddressModeHelper(unsigned addr_reg,
5332
int64_t offset,
5333
AddrMode addrmode) {
5334
uint64_t address = ReadXRegister(addr_reg, Reg31IsStackPointer);
5335
5336
if ((addr_reg == 31) && ((address % 16) != 0)) {
5337
// When the base register is SP the stack pointer is required to be
5338
// quadword aligned prior to the address calculation and write-backs.
5339
// Misalignment will cause a stack alignment fault.
5340
VIXL_ALIGNMENT_EXCEPTION();
5341
}
5342
5343
if ((addrmode == PreIndex) || (addrmode == PostIndex)) {
5344
VIXL_ASSERT(offset != 0);
5345
// Only preindex should log the register update here. For Postindex, the
5346
// update will be printed automatically by LogWrittenRegisters _after_ the
5347
// memory access itself is logged.
5348
RegLogMode log_mode = (addrmode == PreIndex) ? LogRegWrites : NoRegLog;
5349
WriteXRegister(addr_reg, address + offset, log_mode, Reg31IsStackPointer);
5350
}
5351
5352
if ((addrmode == Offset) || (addrmode == PreIndex)) {
5353
address += offset;
5354
}
5355
5356
// Verify that the calculated address is available to the host.
5357
VIXL_ASSERT(address == static_cast<uintptr_t>(address));
5358
5359
return static_cast<uintptr_t>(address);
5360
}
5361
5362
5363
void Simulator::VisitMoveWideImmediate(const Instruction* instr) {
5364
MoveWideImmediateOp mov_op =
5365
static_cast<MoveWideImmediateOp>(instr->Mask(MoveWideImmediateMask));
5366
int64_t new_xn_val = 0;
5367
5368
bool is_64_bits = instr->GetSixtyFourBits() == 1;
5369
// Shift is limited for W operations.
5370
VIXL_ASSERT(is_64_bits || (instr->GetShiftMoveWide() < 2));
5371
5372
// Get the shifted immediate.
5373
int64_t shift = instr->GetShiftMoveWide() * 16;
5374
int64_t shifted_imm16 = static_cast<int64_t>(instr->GetImmMoveWide())
5375
<< shift;
5376
5377
// Compute the new value.
5378
switch (mov_op) {
5379
case MOVN_w:
5380
case MOVN_x: {
5381
new_xn_val = ~shifted_imm16;
5382
if (!is_64_bits) new_xn_val &= kWRegMask;
5383
break;
5384
}
5385
case MOVK_w:
5386
case MOVK_x: {
5387
unsigned reg_code = instr->GetRd();
5388
int64_t prev_xn_val =
5389
is_64_bits ? ReadXRegister(reg_code) : ReadWRegister(reg_code);
5390
new_xn_val = (prev_xn_val & ~(INT64_C(0xffff) << shift)) | shifted_imm16;
5391
break;
5392
}
5393
case MOVZ_w:
5394
case MOVZ_x: {
5395
new_xn_val = shifted_imm16;
5396
break;
5397
}
5398
default:
5399
VIXL_UNREACHABLE();
5400
}
5401
5402
// Update the destination register.
5403
WriteXRegister(instr->GetRd(), new_xn_val);
5404
}
5405
5406
5407
void Simulator::VisitConditionalSelect(const Instruction* instr) {
5408
uint64_t new_val = ReadXRegister(instr->GetRn());
5409
5410
if (ConditionFailed(static_cast<Condition>(instr->GetCondition()))) {
5411
new_val = ReadXRegister(instr->GetRm());
5412
switch (instr->Mask(ConditionalSelectMask)) {
5413
case CSEL_w:
5414
case CSEL_x:
5415
break;
5416
case CSINC_w:
5417
case CSINC_x:
5418
new_val++;
5419
break;
5420
case CSINV_w:
5421
case CSINV_x:
5422
new_val = ~new_val;
5423
break;
5424
case CSNEG_w:
5425
case CSNEG_x:
5426
new_val = -new_val;
5427
break;
5428
default:
5429
VIXL_UNIMPLEMENTED();
5430
}
5431
}
5432
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5433
WriteRegister(reg_size, instr->GetRd(), new_val);
5434
}
5435
5436
5437
#define PAUTH_MODES_REGISTER_CONTEXT(V) \
5438
V(i, a, kPACKeyIA, kInstructionPointer) \
5439
V(i, b, kPACKeyIB, kInstructionPointer) \
5440
V(d, a, kPACKeyDA, kDataPointer) \
5441
V(d, b, kPACKeyDB, kDataPointer)
5442
5443
void Simulator::VisitDataProcessing1Source(const Instruction* instr) {
5444
unsigned dst = instr->GetRd();
5445
unsigned src = instr->GetRn();
5446
Reg31Mode r31_pac = Reg31IsStackPointer;
5447
5448
switch (form_hash_) {
5449
#define DEFINE_PAUTH_FUNCS(SUF0, SUF1, KEY, D) \
5450
case "pac" #SUF0 "z" #SUF1 "_64z_dp_1src"_h: \
5451
VIXL_ASSERT(src == kZeroRegCode); \
5452
r31_pac = Reg31IsZeroRegister; \
5453
VIXL_FALLTHROUGH(); \
5454
case "pac" #SUF0 #SUF1 "_64p_dp_1src"_h: { \
5455
uint64_t mod = ReadXRegister(src, r31_pac); \
5456
uint64_t ptr = ReadXRegister(dst); \
5457
WriteXRegister(dst, AddPAC(ptr, mod, KEY, D)); \
5458
break; \
5459
} \
5460
case "aut" #SUF0 "z" #SUF1 "_64z_dp_1src"_h: \
5461
VIXL_ASSERT(src == kZeroRegCode); \
5462
r31_pac = Reg31IsZeroRegister; \
5463
VIXL_FALLTHROUGH(); \
5464
case "aut" #SUF0 #SUF1 "_64p_dp_1src"_h: { \
5465
uint64_t mod = ReadXRegister(src, r31_pac); \
5466
uint64_t ptr = ReadXRegister(dst); \
5467
WriteXRegister(dst, AuthPAC(ptr, mod, KEY, D)); \
5468
break; \
5469
}
5470
PAUTH_MODES_REGISTER_CONTEXT(DEFINE_PAUTH_FUNCS)
5471
#undef DEFINE_PAUTH_FUNCS
5472
5473
case "xpaci_64z_dp_1src"_h:
5474
WriteXRegister(dst, StripPAC(ReadXRegister(dst), kInstructionPointer));
5475
break;
5476
case "xpacd_64z_dp_1src"_h:
5477
WriteXRegister(dst, StripPAC(ReadXRegister(dst), kDataPointer));
5478
break;
5479
case "rbit_32_dp_1src"_h:
5480
WriteWRegister(dst, ReverseBits(ReadWRegister(src)));
5481
break;
5482
case "rbit_64_dp_1src"_h:
5483
WriteXRegister(dst, ReverseBits(ReadXRegister(src)));
5484
break;
5485
case "rev16_32_dp_1src"_h:
5486
WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 1));
5487
break;
5488
case "rev16_64_dp_1src"_h:
5489
WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 1));
5490
break;
5491
case "rev_32_dp_1src"_h:
5492
WriteWRegister(dst, ReverseBytes(ReadWRegister(src), 2));
5493
break;
5494
case "rev32_64_dp_1src"_h:
5495
WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 2));
5496
break;
5497
case "rev_64_dp_1src"_h:
5498
WriteXRegister(dst, ReverseBytes(ReadXRegister(src), 3));
5499
break;
5500
case "clz_32_dp_1src"_h:
5501
WriteWRegister(dst, CountLeadingZeros(ReadWRegister(src)));
5502
break;
5503
case "clz_64_dp_1src"_h:
5504
WriteXRegister(dst, CountLeadingZeros(ReadXRegister(src)));
5505
break;
5506
case "cls_32_dp_1src"_h:
5507
WriteWRegister(dst, CountLeadingSignBits(ReadWRegister(src)));
5508
break;
5509
case "cls_64_dp_1src"_h:
5510
WriteXRegister(dst, CountLeadingSignBits(ReadXRegister(src)));
5511
break;
5512
case "abs_32_dp_1src"_h:
5513
WriteWRegister(dst, Abs(ReadWRegister(src)));
5514
break;
5515
case "abs_64_dp_1src"_h:
5516
WriteXRegister(dst, Abs(ReadXRegister(src)));
5517
break;
5518
case "cnt_32_dp_1src"_h:
5519
WriteWRegister(dst, CountSetBits(ReadWRegister(src)));
5520
break;
5521
case "cnt_64_dp_1src"_h:
5522
WriteXRegister(dst, CountSetBits(ReadXRegister(src)));
5523
break;
5524
case "ctz_32_dp_1src"_h:
5525
WriteWRegister(dst, CountTrailingZeros(ReadWRegister(src)));
5526
break;
5527
case "ctz_64_dp_1src"_h:
5528
WriteXRegister(dst, CountTrailingZeros(ReadXRegister(src)));
5529
break;
5530
}
5531
}
5532
5533
uint32_t Simulator::Poly32Mod2(unsigned n, uint64_t data, uint32_t poly) {
5534
VIXL_ASSERT((n > 32) && (n <= 64));
5535
for (unsigned i = (n - 1); i >= 32; i--) {
5536
if (((data >> i) & 1) != 0) {
5537
uint64_t polysh32 = (uint64_t)poly << (i - 32);
5538
uint64_t mask = (UINT64_C(1) << i) - 1;
5539
data = ((data & mask) ^ polysh32);
5540
}
5541
}
5542
return data & 0xffffffff;
5543
}
5544
5545
5546
template <typename T>
5547
uint32_t Simulator::Crc32Checksum(uint32_t acc, T val, uint32_t poly) {
5548
unsigned size = sizeof(val) * 8; // Number of bits in type T.
5549
VIXL_ASSERT((size == 8) || (size == 16) || (size == 32));
5550
uint64_t tempacc = static_cast<uint64_t>(ReverseBits(acc)) << size;
5551
uint64_t tempval = static_cast<uint64_t>(ReverseBits(val)) << 32;
5552
return ReverseBits(Poly32Mod2(32 + size, tempacc ^ tempval, poly));
5553
}
5554
5555
5556
uint32_t Simulator::Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly) {
5557
// Poly32Mod2 cannot handle inputs with more than 32 bits, so compute
5558
// the CRC of each 32-bit word sequentially.
5559
acc = Crc32Checksum(acc, (uint32_t)(val & 0xffffffff), poly);
5560
return Crc32Checksum(acc, (uint32_t)(val >> 32), poly);
5561
}
5562
5563
5564
void Simulator::VisitDataProcessing2Source(const Instruction* instr) {
5565
Shift shift_op = NO_SHIFT;
5566
int64_t result = 0;
5567
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5568
5569
switch (instr->Mask(DataProcessing2SourceMask)) {
5570
case SDIV_w: {
5571
int32_t rn = ReadWRegister(instr->GetRn());
5572
int32_t rm = ReadWRegister(instr->GetRm());
5573
if ((rn == kWMinInt) && (rm == -1)) {
5574
result = kWMinInt;
5575
} else if (rm == 0) {
5576
// Division by zero can be trapped, but not on A-class processors.
5577
result = 0;
5578
} else {
5579
result = rn / rm;
5580
}
5581
break;
5582
}
5583
case SDIV_x: {
5584
int64_t rn = ReadXRegister(instr->GetRn());
5585
int64_t rm = ReadXRegister(instr->GetRm());
5586
if ((rn == kXMinInt) && (rm == -1)) {
5587
result = kXMinInt;
5588
} else if (rm == 0) {
5589
// Division by zero can be trapped, but not on A-class processors.
5590
result = 0;
5591
} else {
5592
result = rn / rm;
5593
}
5594
break;
5595
}
5596
case UDIV_w: {
5597
uint32_t rn = static_cast<uint32_t>(ReadWRegister(instr->GetRn()));
5598
uint32_t rm = static_cast<uint32_t>(ReadWRegister(instr->GetRm()));
5599
if (rm == 0) {
5600
// Division by zero can be trapped, but not on A-class processors.
5601
result = 0;
5602
} else {
5603
result = rn / rm;
5604
}
5605
break;
5606
}
5607
case UDIV_x: {
5608
uint64_t rn = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5609
uint64_t rm = static_cast<uint64_t>(ReadXRegister(instr->GetRm()));
5610
if (rm == 0) {
5611
// Division by zero can be trapped, but not on A-class processors.
5612
result = 0;
5613
} else {
5614
result = rn / rm;
5615
}
5616
break;
5617
}
5618
case LSLV_w:
5619
case LSLV_x:
5620
shift_op = LSL;
5621
break;
5622
case LSRV_w:
5623
case LSRV_x:
5624
shift_op = LSR;
5625
break;
5626
case ASRV_w:
5627
case ASRV_x:
5628
shift_op = ASR;
5629
break;
5630
case RORV_w:
5631
case RORV_x:
5632
shift_op = ROR;
5633
break;
5634
case PACGA: {
5635
uint64_t dst = static_cast<uint64_t>(ReadXRegister(instr->GetRn()));
5636
uint64_t src = static_cast<uint64_t>(
5637
ReadXRegister(instr->GetRm(), Reg31IsStackPointer));
5638
uint64_t code = ComputePAC(dst, src, kPACKeyGA);
5639
result = code & 0xffffffff00000000;
5640
break;
5641
}
5642
case CRC32B: {
5643
uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5644
uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5645
result = Crc32Checksum(acc, val, CRC32_POLY);
5646
break;
5647
}
5648
case CRC32H: {
5649
uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5650
uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5651
result = Crc32Checksum(acc, val, CRC32_POLY);
5652
break;
5653
}
5654
case CRC32W: {
5655
uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5656
uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5657
result = Crc32Checksum(acc, val, CRC32_POLY);
5658
break;
5659
}
5660
case CRC32X: {
5661
uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5662
uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5663
result = Crc32Checksum(acc, val, CRC32_POLY);
5664
reg_size = kWRegSize;
5665
break;
5666
}
5667
case CRC32CB: {
5668
uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5669
uint8_t val = ReadRegister<uint8_t>(instr->GetRm());
5670
result = Crc32Checksum(acc, val, CRC32C_POLY);
5671
break;
5672
}
5673
case CRC32CH: {
5674
uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5675
uint16_t val = ReadRegister<uint16_t>(instr->GetRm());
5676
result = Crc32Checksum(acc, val, CRC32C_POLY);
5677
break;
5678
}
5679
case CRC32CW: {
5680
uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5681
uint32_t val = ReadRegister<uint32_t>(instr->GetRm());
5682
result = Crc32Checksum(acc, val, CRC32C_POLY);
5683
break;
5684
}
5685
case CRC32CX: {
5686
uint32_t acc = ReadRegister<uint32_t>(instr->GetRn());
5687
uint64_t val = ReadRegister<uint64_t>(instr->GetRm());
5688
result = Crc32Checksum(acc, val, CRC32C_POLY);
5689
reg_size = kWRegSize;
5690
break;
5691
}
5692
default:
5693
VIXL_UNIMPLEMENTED();
5694
}
5695
5696
if (shift_op != NO_SHIFT) {
5697
// Shift distance encoded in the least-significant five/six bits of the
5698
// register.
5699
int mask = (instr->GetSixtyFourBits() == 1) ? 0x3f : 0x1f;
5700
unsigned shift = ReadWRegister(instr->GetRm()) & mask;
5701
result = ShiftOperand(reg_size,
5702
ReadRegister(reg_size, instr->GetRn()),
5703
shift_op,
5704
shift);
5705
}
5706
WriteRegister(reg_size, instr->GetRd(), result);
5707
}
5708
5709
void Simulator::SimulateSignedMinMax(const Instruction* instr) {
5710
int32_t wn = ReadWRegister(instr->GetRn());
5711
int32_t wm = ReadWRegister(instr->GetRm());
5712
int64_t xn = ReadXRegister(instr->GetRn());
5713
int64_t xm = ReadXRegister(instr->GetRm());
5714
int32_t imm = instr->ExtractSignedBits(17, 10);
5715
int dst = instr->GetRd();
5716
5717
switch (form_hash_) {
5718
case "smax_64_minmax_imm"_h:
5719
case "smin_64_minmax_imm"_h:
5720
xm = imm;
5721
break;
5722
case "smax_32_minmax_imm"_h:
5723
case "smin_32_minmax_imm"_h:
5724
wm = imm;
5725
break;
5726
}
5727
5728
switch (form_hash_) {
5729
case "smax_32_minmax_imm"_h:
5730
case "smax_32_dp_2src"_h:
5731
WriteWRegister(dst, std::max(wn, wm));
5732
break;
5733
case "smax_64_minmax_imm"_h:
5734
case "smax_64_dp_2src"_h:
5735
WriteXRegister(dst, std::max(xn, xm));
5736
break;
5737
case "smin_32_minmax_imm"_h:
5738
case "smin_32_dp_2src"_h:
5739
WriteWRegister(dst, std::min(wn, wm));
5740
break;
5741
case "smin_64_minmax_imm"_h:
5742
case "smin_64_dp_2src"_h:
5743
WriteXRegister(dst, std::min(xn, xm));
5744
break;
5745
}
5746
}
5747
5748
void Simulator::SimulateUnsignedMinMax(const Instruction* instr) {
5749
uint64_t xn = ReadXRegister(instr->GetRn());
5750
uint64_t xm = ReadXRegister(instr->GetRm());
5751
uint32_t imm = instr->ExtractBits(17, 10);
5752
int dst = instr->GetRd();
5753
5754
switch (form_hash_) {
5755
case "umax_64u_minmax_imm"_h:
5756
case "umax_32u_minmax_imm"_h:
5757
case "umin_64u_minmax_imm"_h:
5758
case "umin_32u_minmax_imm"_h:
5759
xm = imm;
5760
break;
5761
}
5762
5763
switch (form_hash_) {
5764
case "umax_32u_minmax_imm"_h:
5765
case "umax_32_dp_2src"_h:
5766
xn &= 0xffff'ffff;
5767
xm &= 0xffff'ffff;
5768
VIXL_FALLTHROUGH();
5769
case "umax_64u_minmax_imm"_h:
5770
case "umax_64_dp_2src"_h:
5771
WriteXRegister(dst, std::max(xn, xm));
5772
break;
5773
case "umin_32u_minmax_imm"_h:
5774
case "umin_32_dp_2src"_h:
5775
xn &= 0xffff'ffff;
5776
xm &= 0xffff'ffff;
5777
VIXL_FALLTHROUGH();
5778
case "umin_64u_minmax_imm"_h:
5779
case "umin_64_dp_2src"_h:
5780
WriteXRegister(dst, std::min(xn, xm));
5781
break;
5782
}
5783
}
5784
5785
void Simulator::VisitDataProcessing3Source(const Instruction* instr) {
5786
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5787
5788
uint64_t result = 0;
5789
// Extract and sign- or zero-extend 32-bit arguments for widening operations.
5790
uint64_t rn_u32 = ReadRegister<uint32_t>(instr->GetRn());
5791
uint64_t rm_u32 = ReadRegister<uint32_t>(instr->GetRm());
5792
int64_t rn_s32 = ReadRegister<int32_t>(instr->GetRn());
5793
int64_t rm_s32 = ReadRegister<int32_t>(instr->GetRm());
5794
uint64_t rn_u64 = ReadXRegister(instr->GetRn());
5795
uint64_t rm_u64 = ReadXRegister(instr->GetRm());
5796
switch (instr->Mask(DataProcessing3SourceMask)) {
5797
case MADD_w:
5798
case MADD_x:
5799
result = ReadXRegister(instr->GetRa()) + (rn_u64 * rm_u64);
5800
break;
5801
case MSUB_w:
5802
case MSUB_x:
5803
result = ReadXRegister(instr->GetRa()) - (rn_u64 * rm_u64);
5804
break;
5805
case SMADDL_x:
5806
result = ReadXRegister(instr->GetRa()) +
5807
static_cast<uint64_t>(rn_s32 * rm_s32);
5808
break;
5809
case SMSUBL_x:
5810
result = ReadXRegister(instr->GetRa()) -
5811
static_cast<uint64_t>(rn_s32 * rm_s32);
5812
break;
5813
case UMADDL_x:
5814
result = ReadXRegister(instr->GetRa()) + (rn_u32 * rm_u32);
5815
break;
5816
case UMSUBL_x:
5817
result = ReadXRegister(instr->GetRa()) - (rn_u32 * rm_u32);
5818
break;
5819
case UMULH_x:
5820
result =
5821
internal::MultiplyHigh<64>(ReadRegister<uint64_t>(instr->GetRn()),
5822
ReadRegister<uint64_t>(instr->GetRm()));
5823
break;
5824
case SMULH_x:
5825
result = internal::MultiplyHigh<64>(ReadXRegister(instr->GetRn()),
5826
ReadXRegister(instr->GetRm()));
5827
break;
5828
default:
5829
VIXL_UNIMPLEMENTED();
5830
}
5831
WriteRegister(reg_size, instr->GetRd(), result);
5832
}
5833
5834
5835
void Simulator::VisitBitfield(const Instruction* instr) {
5836
unsigned reg_size = instr->GetSixtyFourBits() ? kXRegSize : kWRegSize;
5837
int64_t reg_mask = instr->GetSixtyFourBits() ? kXRegMask : kWRegMask;
5838
int R = instr->GetImmR();
5839
int S = instr->GetImmS();
5840
5841
if (instr->GetSixtyFourBits() != instr->GetBitN()) {
5842
VisitUnallocated(instr);
5843
}
5844
5845
if ((instr->GetSixtyFourBits() == 0) && ((S > 31) || (R > 31))) {
5846
VisitUnallocated(instr);
5847
}
5848
5849
int diff = S - R;
5850
uint64_t mask;
5851
if (diff >= 0) {
5852
mask = ~UINT64_C(0) >> (64 - (diff + 1));
5853
mask = (static_cast<unsigned>(diff) < (reg_size - 1)) ? mask : reg_mask;
5854
} else {
5855
mask = ~UINT64_C(0) >> (64 - (S + 1));
5856
mask = RotateRight(mask, R, reg_size);
5857
diff += reg_size;
5858
}
5859
5860
// inzero indicates if the extracted bitfield is inserted into the
5861
// destination register value or in zero.
5862
// If extend is true, extend the sign of the extracted bitfield.
5863
bool inzero = false;
5864
bool extend = false;
5865
switch (instr->Mask(BitfieldMask)) {
5866
case BFM_x:
5867
case BFM_w:
5868
break;
5869
case SBFM_x:
5870
case SBFM_w:
5871
inzero = true;
5872
extend = true;
5873
break;
5874
case UBFM_x:
5875
case UBFM_w:
5876
inzero = true;
5877
break;
5878
default:
5879
VIXL_UNIMPLEMENTED();
5880
}
5881
5882
uint64_t dst = inzero ? 0 : ReadRegister(reg_size, instr->GetRd());
5883
uint64_t src = ReadRegister(reg_size, instr->GetRn());
5884
// Rotate source bitfield into place.
5885
uint64_t result = RotateRight(src, R, reg_size);
5886
// Determine the sign extension.
5887
uint64_t topbits = (diff == 63) ? 0 : (~UINT64_C(0) << (diff + 1));
5888
uint64_t signbits = extend && ((src >> S) & 1) ? topbits : 0;
5889
5890
// Merge sign extension, dest/zero and bitfield.
5891
result = signbits | (result & mask) | (dst & ~mask);
5892
5893
WriteRegister(reg_size, instr->GetRd(), result);
5894
}
5895
5896
5897
void Simulator::VisitExtract(const Instruction* instr) {
5898
unsigned lsb = instr->GetImmS();
5899
unsigned reg_size = (instr->GetSixtyFourBits() == 1) ? kXRegSize : kWRegSize;
5900
uint64_t low_res =
5901
static_cast<uint64_t>(ReadRegister(reg_size, instr->GetRm())) >> lsb;
5902
uint64_t high_res = (lsb == 0)
5903
? 0
5904
: ReadRegister<uint64_t>(reg_size, instr->GetRn())
5905
<< (reg_size - lsb);
5906
WriteRegister(reg_size, instr->GetRd(), low_res | high_res);
5907
}
5908
5909
5910
void Simulator::VisitFPImmediate(const Instruction* instr) {
5911
AssertSupportedFPCR();
5912
unsigned dest = instr->GetRd();
5913
switch (instr->Mask(FPImmediateMask)) {
5914
case FMOV_h_imm:
5915
WriteHRegister(dest, Float16ToRawbits(instr->GetImmFP16()));
5916
break;
5917
case FMOV_s_imm:
5918
WriteSRegister(dest, instr->GetImmFP32());
5919
break;
5920
case FMOV_d_imm:
5921
WriteDRegister(dest, instr->GetImmFP64());
5922
break;
5923
default:
5924
VIXL_UNREACHABLE();
5925
}
5926
}
5927
5928
5929
void Simulator::VisitFPIntegerConvert(const Instruction* instr) {
5930
AssertSupportedFPCR();
5931
5932
unsigned dst = instr->GetRd();
5933
unsigned src = instr->GetRn();
5934
5935
FPRounding round = ReadRMode();
5936
5937
switch (instr->Mask(FPIntegerConvertMask)) {
5938
case FCVTAS_wh:
5939
WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieAway));
5940
break;
5941
case FCVTAS_xh:
5942
WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieAway));
5943
break;
5944
case FCVTAS_ws:
5945
WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieAway));
5946
break;
5947
case FCVTAS_xs:
5948
WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieAway));
5949
break;
5950
case FCVTAS_wd:
5951
WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieAway));
5952
break;
5953
case FCVTAS_xd:
5954
WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieAway));
5955
break;
5956
case FCVTAU_wh:
5957
WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieAway));
5958
break;
5959
case FCVTAU_xh:
5960
WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieAway));
5961
break;
5962
case FCVTAU_ws:
5963
WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieAway));
5964
break;
5965
case FCVTAU_xs:
5966
WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieAway));
5967
break;
5968
case FCVTAU_wd:
5969
WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieAway));
5970
break;
5971
case FCVTAU_xd:
5972
WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieAway));
5973
break;
5974
case FCVTMS_wh:
5975
WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPNegativeInfinity));
5976
break;
5977
case FCVTMS_xh:
5978
WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPNegativeInfinity));
5979
break;
5980
case FCVTMS_ws:
5981
WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPNegativeInfinity));
5982
break;
5983
case FCVTMS_xs:
5984
WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPNegativeInfinity));
5985
break;
5986
case FCVTMS_wd:
5987
WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPNegativeInfinity));
5988
break;
5989
case FCVTMS_xd:
5990
WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPNegativeInfinity));
5991
break;
5992
case FCVTMU_wh:
5993
WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPNegativeInfinity));
5994
break;
5995
case FCVTMU_xh:
5996
WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPNegativeInfinity));
5997
break;
5998
case FCVTMU_ws:
5999
WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPNegativeInfinity));
6000
break;
6001
case FCVTMU_xs:
6002
WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPNegativeInfinity));
6003
break;
6004
case FCVTMU_wd:
6005
WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPNegativeInfinity));
6006
break;
6007
case FCVTMU_xd:
6008
WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPNegativeInfinity));
6009
break;
6010
case FCVTPS_wh:
6011
WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPPositiveInfinity));
6012
break;
6013
case FCVTPS_xh:
6014
WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPPositiveInfinity));
6015
break;
6016
case FCVTPS_ws:
6017
WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPPositiveInfinity));
6018
break;
6019
case FCVTPS_xs:
6020
WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPPositiveInfinity));
6021
break;
6022
case FCVTPS_wd:
6023
WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPPositiveInfinity));
6024
break;
6025
case FCVTPS_xd:
6026
WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPPositiveInfinity));
6027
break;
6028
case FCVTPU_wh:
6029
WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPPositiveInfinity));
6030
break;
6031
case FCVTPU_xh:
6032
WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPPositiveInfinity));
6033
break;
6034
case FCVTPU_ws:
6035
WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPPositiveInfinity));
6036
break;
6037
case FCVTPU_xs:
6038
WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPPositiveInfinity));
6039
break;
6040
case FCVTPU_wd:
6041
WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPPositiveInfinity));
6042
break;
6043
case FCVTPU_xd:
6044
WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPPositiveInfinity));
6045
break;
6046
case FCVTNS_wh:
6047
WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPTieEven));
6048
break;
6049
case FCVTNS_xh:
6050
WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPTieEven));
6051
break;
6052
case FCVTNS_ws:
6053
WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPTieEven));
6054
break;
6055
case FCVTNS_xs:
6056
WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPTieEven));
6057
break;
6058
case FCVTNS_wd:
6059
WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPTieEven));
6060
break;
6061
case FCVTNS_xd:
6062
WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPTieEven));
6063
break;
6064
case FCVTNU_wh:
6065
WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPTieEven));
6066
break;
6067
case FCVTNU_xh:
6068
WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPTieEven));
6069
break;
6070
case FCVTNU_ws:
6071
WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPTieEven));
6072
break;
6073
case FCVTNU_xs:
6074
WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPTieEven));
6075
break;
6076
case FCVTNU_wd:
6077
WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPTieEven));
6078
break;
6079
case FCVTNU_xd:
6080
WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPTieEven));
6081
break;
6082
case FCVTZS_wh:
6083
WriteWRegister(dst, FPToInt32(ReadHRegister(src), FPZero));
6084
break;
6085
case FCVTZS_xh:
6086
WriteXRegister(dst, FPToInt64(ReadHRegister(src), FPZero));
6087
break;
6088
case FCVTZS_ws:
6089
WriteWRegister(dst, FPToInt32(ReadSRegister(src), FPZero));
6090
break;
6091
case FCVTZS_xs:
6092
WriteXRegister(dst, FPToInt64(ReadSRegister(src), FPZero));
6093
break;
6094
case FCVTZS_wd:
6095
WriteWRegister(dst, FPToInt32(ReadDRegister(src), FPZero));
6096
break;
6097
case FCVTZS_xd:
6098
WriteXRegister(dst, FPToInt64(ReadDRegister(src), FPZero));
6099
break;
6100
case FCVTZU_wh:
6101
WriteWRegister(dst, FPToUInt32(ReadHRegister(src), FPZero));
6102
break;
6103
case FCVTZU_xh:
6104
WriteXRegister(dst, FPToUInt64(ReadHRegister(src), FPZero));
6105
break;
6106
case FCVTZU_ws:
6107
WriteWRegister(dst, FPToUInt32(ReadSRegister(src), FPZero));
6108
break;
6109
case FCVTZU_xs:
6110
WriteXRegister(dst, FPToUInt64(ReadSRegister(src), FPZero));
6111
break;
6112
case FCVTZU_wd:
6113
WriteWRegister(dst, FPToUInt32(ReadDRegister(src), FPZero));
6114
break;
6115
case FCVTZU_xd:
6116
WriteXRegister(dst, FPToUInt64(ReadDRegister(src), FPZero));
6117
break;
6118
case FJCVTZS:
6119
WriteWRegister(dst, FPToFixedJS(ReadDRegister(src)));
6120
break;
6121
case FMOV_hw:
6122
WriteHRegister(dst, ReadWRegister(src) & kHRegMask);
6123
break;
6124
case FMOV_wh:
6125
WriteWRegister(dst, ReadHRegisterBits(src));
6126
break;
6127
case FMOV_xh:
6128
WriteXRegister(dst, ReadHRegisterBits(src));
6129
break;
6130
case FMOV_hx:
6131
WriteHRegister(dst, ReadXRegister(src) & kHRegMask);
6132
break;
6133
case FMOV_ws:
6134
WriteWRegister(dst, ReadSRegisterBits(src));
6135
break;
6136
case FMOV_xd:
6137
WriteXRegister(dst, ReadDRegisterBits(src));
6138
break;
6139
case FMOV_sw:
6140
WriteSRegisterBits(dst, ReadWRegister(src));
6141
break;
6142
case FMOV_dx:
6143
WriteDRegisterBits(dst, ReadXRegister(src));
6144
break;
6145
case FMOV_d1_x:
6146
// Zero bits beyond the MSB of a Q register.
6147
mov(kFormat16B, ReadVRegister(dst), ReadVRegister(dst));
6148
LogicVRegister(ReadVRegister(dst))
6149
.SetUint(kFormatD, 1, ReadXRegister(src));
6150
break;
6151
case FMOV_x_d1:
6152
WriteXRegister(dst, LogicVRegister(ReadVRegister(src)).Uint(kFormatD, 1));
6153
break;
6154
6155
// A 32-bit input can be handled in the same way as a 64-bit input, since
6156
// the sign- or zero-extension will not affect the conversion.
6157
case SCVTF_dx:
6158
WriteDRegister(dst, FixedToDouble(ReadXRegister(src), 0, round));
6159
break;
6160
case SCVTF_dw:
6161
WriteDRegister(dst, FixedToDouble(ReadWRegister(src), 0, round));
6162
break;
6163
case UCVTF_dx:
6164
WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), 0, round));
6165
break;
6166
case UCVTF_dw: {
6167
WriteDRegister(dst,
6168
UFixedToDouble(ReadRegister<uint32_t>(src), 0, round));
6169
break;
6170
}
6171
case SCVTF_sx:
6172
WriteSRegister(dst, FixedToFloat(ReadXRegister(src), 0, round));
6173
break;
6174
case SCVTF_sw:
6175
WriteSRegister(dst, FixedToFloat(ReadWRegister(src), 0, round));
6176
break;
6177
case UCVTF_sx:
6178
WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), 0, round));
6179
break;
6180
case UCVTF_sw: {
6181
WriteSRegister(dst, UFixedToFloat(ReadRegister<uint32_t>(src), 0, round));
6182
break;
6183
}
6184
case SCVTF_hx:
6185
WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), 0, round));
6186
break;
6187
case SCVTF_hw:
6188
WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), 0, round));
6189
break;
6190
case UCVTF_hx:
6191
WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), 0, round));
6192
break;
6193
case UCVTF_hw: {
6194
WriteHRegister(dst,
6195
UFixedToFloat16(ReadRegister<uint32_t>(src), 0, round));
6196
break;
6197
}
6198
6199
default:
6200
VIXL_UNREACHABLE();
6201
}
6202
}
6203
6204
6205
void Simulator::VisitFPFixedPointConvert(const Instruction* instr) {
6206
AssertSupportedFPCR();
6207
6208
unsigned dst = instr->GetRd();
6209
unsigned src = instr->GetRn();
6210
int fbits = 64 - instr->GetFPScale();
6211
6212
FPRounding round = ReadRMode();
6213
6214
switch (instr->Mask(FPFixedPointConvertMask)) {
6215
// A 32-bit input can be handled in the same way as a 64-bit input, since
6216
// the sign- or zero-extension will not affect the conversion.
6217
case SCVTF_dx_fixed:
6218
WriteDRegister(dst, FixedToDouble(ReadXRegister(src), fbits, round));
6219
break;
6220
case SCVTF_dw_fixed:
6221
WriteDRegister(dst, FixedToDouble(ReadWRegister(src), fbits, round));
6222
break;
6223
case UCVTF_dx_fixed:
6224
WriteDRegister(dst, UFixedToDouble(ReadXRegister(src), fbits, round));
6225
break;
6226
case UCVTF_dw_fixed: {
6227
WriteDRegister(dst,
6228
UFixedToDouble(ReadRegister<uint32_t>(src), fbits, round));
6229
break;
6230
}
6231
case SCVTF_sx_fixed:
6232
WriteSRegister(dst, FixedToFloat(ReadXRegister(src), fbits, round));
6233
break;
6234
case SCVTF_sw_fixed:
6235
WriteSRegister(dst, FixedToFloat(ReadWRegister(src), fbits, round));
6236
break;
6237
case UCVTF_sx_fixed:
6238
WriteSRegister(dst, UFixedToFloat(ReadXRegister(src), fbits, round));
6239
break;
6240
case UCVTF_sw_fixed: {
6241
WriteSRegister(dst,
6242
UFixedToFloat(ReadRegister<uint32_t>(src), fbits, round));
6243
break;
6244
}
6245
case SCVTF_hx_fixed:
6246
WriteHRegister(dst, FixedToFloat16(ReadXRegister(src), fbits, round));
6247
break;
6248
case SCVTF_hw_fixed:
6249
WriteHRegister(dst, FixedToFloat16(ReadWRegister(src), fbits, round));
6250
break;
6251
case UCVTF_hx_fixed:
6252
WriteHRegister(dst, UFixedToFloat16(ReadXRegister(src), fbits, round));
6253
break;
6254
case UCVTF_hw_fixed: {
6255
WriteHRegister(dst,
6256
UFixedToFloat16(ReadRegister<uint32_t>(src),
6257
fbits,
6258
round));
6259
break;
6260
}
6261
case FCVTZS_xd_fixed:
6262
WriteXRegister(dst,
6263
FPToInt64(ReadDRegister(src) * std::pow(2.0, fbits),
6264
FPZero));
6265
break;
6266
case FCVTZS_wd_fixed:
6267
WriteWRegister(dst,
6268
FPToInt32(ReadDRegister(src) * std::pow(2.0, fbits),
6269
FPZero));
6270
break;
6271
case FCVTZU_xd_fixed:
6272
WriteXRegister(dst,
6273
FPToUInt64(ReadDRegister(src) * std::pow(2.0, fbits),
6274
FPZero));
6275
break;
6276
case FCVTZU_wd_fixed:
6277
WriteWRegister(dst,
6278
FPToUInt32(ReadDRegister(src) * std::pow(2.0, fbits),
6279
FPZero));
6280
break;
6281
case FCVTZS_xs_fixed:
6282
WriteXRegister(dst,
6283
FPToInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
6284
FPZero));
6285
break;
6286
case FCVTZS_ws_fixed:
6287
WriteWRegister(dst,
6288
FPToInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
6289
FPZero));
6290
break;
6291
case FCVTZU_xs_fixed:
6292
WriteXRegister(dst,
6293
FPToUInt64(ReadSRegister(src) * std::pow(2.0f, fbits),
6294
FPZero));
6295
break;
6296
case FCVTZU_ws_fixed:
6297
WriteWRegister(dst,
6298
FPToUInt32(ReadSRegister(src) * std::pow(2.0f, fbits),
6299
FPZero));
6300
break;
6301
case FCVTZS_xh_fixed: {
6302
double output =
6303
static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
6304
WriteXRegister(dst, FPToInt64(output, FPZero));
6305
break;
6306
}
6307
case FCVTZS_wh_fixed: {
6308
double output =
6309
static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
6310
WriteWRegister(dst, FPToInt32(output, FPZero));
6311
break;
6312
}
6313
case FCVTZU_xh_fixed: {
6314
double output =
6315
static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
6316
WriteXRegister(dst, FPToUInt64(output, FPZero));
6317
break;
6318
}
6319
case FCVTZU_wh_fixed: {
6320
double output =
6321
static_cast<double>(ReadHRegister(src)) * std::pow(2.0, fbits);
6322
WriteWRegister(dst, FPToUInt32(output, FPZero));
6323
break;
6324
}
6325
default:
6326
VIXL_UNREACHABLE();
6327
}
6328
}
6329
6330
6331
void Simulator::VisitFPCompare(const Instruction* instr) {
6332
AssertSupportedFPCR();
6333
6334
FPTrapFlags trap = DisableTrap;
6335
switch (instr->Mask(FPCompareMask)) {
6336
case FCMPE_h:
6337
trap = EnableTrap;
6338
VIXL_FALLTHROUGH();
6339
case FCMP_h:
6340
FPCompare(ReadHRegister(instr->GetRn()),
6341
ReadHRegister(instr->GetRm()),
6342
trap);
6343
break;
6344
case FCMPE_s:
6345
trap = EnableTrap;
6346
VIXL_FALLTHROUGH();
6347
case FCMP_s:
6348
FPCompare(ReadSRegister(instr->GetRn()),
6349
ReadSRegister(instr->GetRm()),
6350
trap);
6351
break;
6352
case FCMPE_d:
6353
trap = EnableTrap;
6354
VIXL_FALLTHROUGH();
6355
case FCMP_d:
6356
FPCompare(ReadDRegister(instr->GetRn()),
6357
ReadDRegister(instr->GetRm()),
6358
trap);
6359
break;
6360
case FCMPE_h_zero:
6361
trap = EnableTrap;
6362
VIXL_FALLTHROUGH();
6363
case FCMP_h_zero:
6364
FPCompare(ReadHRegister(instr->GetRn()), SimFloat16(0.0), trap);
6365
break;
6366
case FCMPE_s_zero:
6367
trap = EnableTrap;
6368
VIXL_FALLTHROUGH();
6369
case FCMP_s_zero:
6370
FPCompare(ReadSRegister(instr->GetRn()), 0.0f, trap);
6371
break;
6372
case FCMPE_d_zero:
6373
trap = EnableTrap;
6374
VIXL_FALLTHROUGH();
6375
case FCMP_d_zero:
6376
FPCompare(ReadDRegister(instr->GetRn()), 0.0, trap);
6377
break;
6378
default:
6379
VIXL_UNIMPLEMENTED();
6380
}
6381
}
6382
6383
6384
void Simulator::VisitFPConditionalCompare(const Instruction* instr) {
6385
AssertSupportedFPCR();
6386
6387
FPTrapFlags trap = DisableTrap;
6388
switch (instr->Mask(FPConditionalCompareMask)) {
6389
case FCCMPE_h:
6390
trap = EnableTrap;
6391
VIXL_FALLTHROUGH();
6392
case FCCMP_h:
6393
if (ConditionPassed(instr->GetCondition())) {
6394
FPCompare(ReadHRegister(instr->GetRn()),
6395
ReadHRegister(instr->GetRm()),
6396
trap);
6397
} else {
6398
ReadNzcv().SetFlags(instr->GetNzcv());
6399
LogSystemRegister(NZCV);
6400
}
6401
break;
6402
case FCCMPE_s:
6403
trap = EnableTrap;
6404
VIXL_FALLTHROUGH();
6405
case FCCMP_s:
6406
if (ConditionPassed(instr->GetCondition())) {
6407
FPCompare(ReadSRegister(instr->GetRn()),
6408
ReadSRegister(instr->GetRm()),
6409
trap);
6410
} else {
6411
ReadNzcv().SetFlags(instr->GetNzcv());
6412
LogSystemRegister(NZCV);
6413
}
6414
break;
6415
case FCCMPE_d:
6416
trap = EnableTrap;
6417
VIXL_FALLTHROUGH();
6418
case FCCMP_d:
6419
if (ConditionPassed(instr->GetCondition())) {
6420
FPCompare(ReadDRegister(instr->GetRn()),
6421
ReadDRegister(instr->GetRm()),
6422
trap);
6423
} else {
6424
ReadNzcv().SetFlags(instr->GetNzcv());
6425
LogSystemRegister(NZCV);
6426
}
6427
break;
6428
default:
6429
VIXL_UNIMPLEMENTED();
6430
}
6431
}
6432
6433
6434
void Simulator::VisitFPConditionalSelect(const Instruction* instr) {
6435
AssertSupportedFPCR();
6436
6437
Instr selected;
6438
if (ConditionPassed(instr->GetCondition())) {
6439
selected = instr->GetRn();
6440
} else {
6441
selected = instr->GetRm();
6442
}
6443
6444
switch (instr->Mask(FPConditionalSelectMask)) {
6445
case FCSEL_h:
6446
WriteHRegister(instr->GetRd(), ReadHRegister(selected));
6447
break;
6448
case FCSEL_s:
6449
WriteSRegister(instr->GetRd(), ReadSRegister(selected));
6450
break;
6451
case FCSEL_d:
6452
WriteDRegister(instr->GetRd(), ReadDRegister(selected));
6453
break;
6454
default:
6455
VIXL_UNIMPLEMENTED();
6456
}
6457
}
6458
6459
6460
void Simulator::VisitFPDataProcessing1Source(const Instruction* instr) {
6461
AssertSupportedFPCR();
6462
6463
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
6464
VectorFormat vform;
6465
switch (instr->Mask(FPTypeMask)) {
6466
default:
6467
VIXL_UNREACHABLE_OR_FALLTHROUGH();
6468
case FP64:
6469
vform = kFormatD;
6470
break;
6471
case FP32:
6472
vform = kFormatS;
6473
break;
6474
case FP16:
6475
vform = kFormatH;
6476
break;
6477
}
6478
6479
SimVRegister& rd = ReadVRegister(instr->GetRd());
6480
SimVRegister& rn = ReadVRegister(instr->GetRn());
6481
bool inexact_exception = false;
6482
FrintMode frint_mode = kFrintToInteger;
6483
6484
unsigned fd = instr->GetRd();
6485
unsigned fn = instr->GetRn();
6486
6487
switch (instr->Mask(FPDataProcessing1SourceMask)) {
6488
case FMOV_h:
6489
WriteHRegister(fd, ReadHRegister(fn));
6490
return;
6491
case FMOV_s:
6492
WriteSRegister(fd, ReadSRegister(fn));
6493
return;
6494
case FMOV_d:
6495
WriteDRegister(fd, ReadDRegister(fn));
6496
return;
6497
case FABS_h:
6498
case FABS_s:
6499
case FABS_d:
6500
fabs_(vform, ReadVRegister(fd), ReadVRegister(fn));
6501
// Explicitly log the register update whilst we have type information.
6502
LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6503
return;
6504
case FNEG_h:
6505
case FNEG_s:
6506
case FNEG_d:
6507
fneg(vform, ReadVRegister(fd), ReadVRegister(fn));
6508
// Explicitly log the register update whilst we have type information.
6509
LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6510
return;
6511
case FCVT_ds:
6512
WriteDRegister(fd, FPToDouble(ReadSRegister(fn), ReadDN()));
6513
return;
6514
case FCVT_sd:
6515
WriteSRegister(fd, FPToFloat(ReadDRegister(fn), FPTieEven, ReadDN()));
6516
return;
6517
case FCVT_hs:
6518
WriteHRegister(fd,
6519
Float16ToRawbits(
6520
FPToFloat16(ReadSRegister(fn), FPTieEven, ReadDN())));
6521
return;
6522
case FCVT_sh:
6523
WriteSRegister(fd, FPToFloat(ReadHRegister(fn), ReadDN()));
6524
return;
6525
case FCVT_dh:
6526
WriteDRegister(fd, FPToDouble(ReadHRegister(fn), ReadDN()));
6527
return;
6528
case FCVT_hd:
6529
WriteHRegister(fd,
6530
Float16ToRawbits(
6531
FPToFloat16(ReadDRegister(fn), FPTieEven, ReadDN())));
6532
return;
6533
case FSQRT_h:
6534
case FSQRT_s:
6535
case FSQRT_d:
6536
fsqrt(vform, rd, rn);
6537
// Explicitly log the register update whilst we have type information.
6538
LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6539
return;
6540
case FRINT32X_s:
6541
case FRINT32X_d:
6542
inexact_exception = true;
6543
frint_mode = kFrintToInt32;
6544
break; // Use FPCR rounding mode.
6545
case FRINT64X_s:
6546
case FRINT64X_d:
6547
inexact_exception = true;
6548
frint_mode = kFrintToInt64;
6549
break; // Use FPCR rounding mode.
6550
case FRINT32Z_s:
6551
case FRINT32Z_d:
6552
inexact_exception = true;
6553
frint_mode = kFrintToInt32;
6554
fpcr_rounding = FPZero;
6555
break;
6556
case FRINT64Z_s:
6557
case FRINT64Z_d:
6558
inexact_exception = true;
6559
frint_mode = kFrintToInt64;
6560
fpcr_rounding = FPZero;
6561
break;
6562
case FRINTI_h:
6563
case FRINTI_s:
6564
case FRINTI_d:
6565
break; // Use FPCR rounding mode.
6566
case FRINTX_h:
6567
case FRINTX_s:
6568
case FRINTX_d:
6569
inexact_exception = true;
6570
break;
6571
case FRINTA_h:
6572
case FRINTA_s:
6573
case FRINTA_d:
6574
fpcr_rounding = FPTieAway;
6575
break;
6576
case FRINTM_h:
6577
case FRINTM_s:
6578
case FRINTM_d:
6579
fpcr_rounding = FPNegativeInfinity;
6580
break;
6581
case FRINTN_h:
6582
case FRINTN_s:
6583
case FRINTN_d:
6584
fpcr_rounding = FPTieEven;
6585
break;
6586
case FRINTP_h:
6587
case FRINTP_s:
6588
case FRINTP_d:
6589
fpcr_rounding = FPPositiveInfinity;
6590
break;
6591
case FRINTZ_h:
6592
case FRINTZ_s:
6593
case FRINTZ_d:
6594
fpcr_rounding = FPZero;
6595
break;
6596
default:
6597
VIXL_UNIMPLEMENTED();
6598
}
6599
6600
// Only FRINT* instructions fall through the switch above.
6601
frint(vform, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
6602
// Explicitly log the register update whilst we have type information.
6603
LogVRegister(fd, GetPrintRegisterFormatFP(vform));
6604
}
6605
6606
6607
void Simulator::VisitFPDataProcessing2Source(const Instruction* instr) {
6608
AssertSupportedFPCR();
6609
6610
VectorFormat vform;
6611
switch (instr->Mask(FPTypeMask)) {
6612
default:
6613
VIXL_UNREACHABLE_OR_FALLTHROUGH();
6614
case FP64:
6615
vform = kFormatD;
6616
break;
6617
case FP32:
6618
vform = kFormatS;
6619
break;
6620
case FP16:
6621
vform = kFormatH;
6622
break;
6623
}
6624
SimVRegister& rd = ReadVRegister(instr->GetRd());
6625
SimVRegister& rn = ReadVRegister(instr->GetRn());
6626
SimVRegister& rm = ReadVRegister(instr->GetRm());
6627
6628
switch (instr->Mask(FPDataProcessing2SourceMask)) {
6629
case FADD_h:
6630
case FADD_s:
6631
case FADD_d:
6632
fadd(vform, rd, rn, rm);
6633
break;
6634
case FSUB_h:
6635
case FSUB_s:
6636
case FSUB_d:
6637
fsub(vform, rd, rn, rm);
6638
break;
6639
case FMUL_h:
6640
case FMUL_s:
6641
case FMUL_d:
6642
fmul(vform, rd, rn, rm);
6643
break;
6644
case FNMUL_h:
6645
case FNMUL_s:
6646
case FNMUL_d:
6647
fnmul(vform, rd, rn, rm);
6648
break;
6649
case FDIV_h:
6650
case FDIV_s:
6651
case FDIV_d:
6652
fdiv(vform, rd, rn, rm);
6653
break;
6654
case FMAX_h:
6655
case FMAX_s:
6656
case FMAX_d:
6657
fmax(vform, rd, rn, rm);
6658
break;
6659
case FMIN_h:
6660
case FMIN_s:
6661
case FMIN_d:
6662
fmin(vform, rd, rn, rm);
6663
break;
6664
case FMAXNM_h:
6665
case FMAXNM_s:
6666
case FMAXNM_d:
6667
fmaxnm(vform, rd, rn, rm);
6668
break;
6669
case FMINNM_h:
6670
case FMINNM_s:
6671
case FMINNM_d:
6672
fminnm(vform, rd, rn, rm);
6673
break;
6674
default:
6675
VIXL_UNREACHABLE();
6676
}
6677
// Explicitly log the register update whilst we have type information.
6678
LogVRegister(instr->GetRd(), GetPrintRegisterFormatFP(vform));
6679
}
6680
6681
6682
void Simulator::VisitFPDataProcessing3Source(const Instruction* instr) {
6683
AssertSupportedFPCR();
6684
6685
unsigned fd = instr->GetRd();
6686
unsigned fn = instr->GetRn();
6687
unsigned fm = instr->GetRm();
6688
unsigned fa = instr->GetRa();
6689
6690
switch (instr->Mask(FPDataProcessing3SourceMask)) {
6691
// fd = fa +/- (fn * fm)
6692
case FMADD_h:
6693
WriteHRegister(fd,
6694
FPMulAdd(ReadHRegister(fa),
6695
ReadHRegister(fn),
6696
ReadHRegister(fm)));
6697
break;
6698
case FMSUB_h:
6699
WriteHRegister(fd,
6700
FPMulAdd(ReadHRegister(fa),
6701
-ReadHRegister(fn),
6702
ReadHRegister(fm)));
6703
break;
6704
case FMADD_s:
6705
WriteSRegister(fd,
6706
FPMulAdd(ReadSRegister(fa),
6707
ReadSRegister(fn),
6708
ReadSRegister(fm)));
6709
break;
6710
case FMSUB_s:
6711
WriteSRegister(fd,
6712
FPMulAdd(ReadSRegister(fa),
6713
-ReadSRegister(fn),
6714
ReadSRegister(fm)));
6715
break;
6716
case FMADD_d:
6717
WriteDRegister(fd,
6718
FPMulAdd(ReadDRegister(fa),
6719
ReadDRegister(fn),
6720
ReadDRegister(fm)));
6721
break;
6722
case FMSUB_d:
6723
WriteDRegister(fd,
6724
FPMulAdd(ReadDRegister(fa),
6725
-ReadDRegister(fn),
6726
ReadDRegister(fm)));
6727
break;
6728
// Negated variants of the above.
6729
case FNMADD_h:
6730
WriteHRegister(fd,
6731
FPMulAdd(-ReadHRegister(fa),
6732
-ReadHRegister(fn),
6733
ReadHRegister(fm)));
6734
break;
6735
case FNMSUB_h:
6736
WriteHRegister(fd,
6737
FPMulAdd(-ReadHRegister(fa),
6738
ReadHRegister(fn),
6739
ReadHRegister(fm)));
6740
break;
6741
case FNMADD_s:
6742
WriteSRegister(fd,
6743
FPMulAdd(-ReadSRegister(fa),
6744
-ReadSRegister(fn),
6745
ReadSRegister(fm)));
6746
break;
6747
case FNMSUB_s:
6748
WriteSRegister(fd,
6749
FPMulAdd(-ReadSRegister(fa),
6750
ReadSRegister(fn),
6751
ReadSRegister(fm)));
6752
break;
6753
case FNMADD_d:
6754
WriteDRegister(fd,
6755
FPMulAdd(-ReadDRegister(fa),
6756
-ReadDRegister(fn),
6757
ReadDRegister(fm)));
6758
break;
6759
case FNMSUB_d:
6760
WriteDRegister(fd,
6761
FPMulAdd(-ReadDRegister(fa),
6762
ReadDRegister(fn),
6763
ReadDRegister(fm)));
6764
break;
6765
default:
6766
VIXL_UNIMPLEMENTED();
6767
}
6768
}
6769
6770
6771
bool Simulator::FPProcessNaNs(const Instruction* instr) {
6772
unsigned fd = instr->GetRd();
6773
unsigned fn = instr->GetRn();
6774
unsigned fm = instr->GetRm();
6775
bool done = false;
6776
6777
if (instr->Mask(FP64) == FP64) {
6778
double result = FPProcessNaNs(ReadDRegister(fn), ReadDRegister(fm));
6779
if (IsNaN(result)) {
6780
WriteDRegister(fd, result);
6781
done = true;
6782
}
6783
} else if (instr->Mask(FP32) == FP32) {
6784
float result = FPProcessNaNs(ReadSRegister(fn), ReadSRegister(fm));
6785
if (IsNaN(result)) {
6786
WriteSRegister(fd, result);
6787
done = true;
6788
}
6789
} else {
6790
VIXL_ASSERT(instr->Mask(FP16) == FP16);
6791
VIXL_UNIMPLEMENTED();
6792
}
6793
6794
return done;
6795
}
6796
6797
6798
void Simulator::SysOp_W(int op, int64_t val) {
6799
switch (op) {
6800
case IVAU:
6801
case CVAC:
6802
case CVAU:
6803
case CVAP:
6804
case CVADP:
6805
case CIVAC:
6806
case CGVAC:
6807
case CGDVAC:
6808
case CGVAP:
6809
case CGDVAP:
6810
case CIGVAC:
6811
case CIGDVAC: {
6812
// Perform a placeholder memory access to ensure that we have read access
6813
// to the specified address. The read access does not require a tag match,
6814
// so temporarily disable MTE.
6815
bool mte_enabled = MetaDataDepot::MetaDataMTE::IsActive();
6816
MetaDataDepot::MetaDataMTE::SetActive(false);
6817
volatile uint8_t y = *MemRead<uint8_t>(val);
6818
MetaDataDepot::MetaDataMTE::SetActive(mte_enabled);
6819
USE(y);
6820
// TODO: Implement ZVA, GVA, GZVA.
6821
break;
6822
}
6823
default:
6824
VIXL_UNIMPLEMENTED();
6825
}
6826
}
6827
6828
void Simulator::PACHelper(int dst,
6829
int src,
6830
PACKey key,
6831
decltype(&Simulator::AddPAC) pac_fn) {
6832
VIXL_ASSERT((dst == 17) || (dst == 30));
6833
VIXL_ASSERT((src == -1) || (src == 16) || (src == 31));
6834
6835
uint64_t modifier = (src == -1) ? 0 : ReadXRegister(src, Reg31IsStackPointer);
6836
uint64_t result =
6837
(this->*pac_fn)(ReadXRegister(dst), modifier, key, kInstructionPointer);
6838
WriteXRegister(dst, result);
6839
}
6840
6841
void Simulator::VisitSystem(const Instruction* instr) {
6842
PACKey pac_key = kPACKeyIA; // Default key for PAC/AUTH handling.
6843
6844
switch (form_hash_) {
6845
case "cfinv_m_pstate"_h:
6846
ReadNzcv().SetC(!ReadC());
6847
break;
6848
case "axflag_m_pstate"_h:
6849
ReadNzcv().SetN(0);
6850
ReadNzcv().SetZ(ReadNzcv().GetZ() | ReadNzcv().GetV());
6851
ReadNzcv().SetC(ReadNzcv().GetC() & ~ReadNzcv().GetV());
6852
ReadNzcv().SetV(0);
6853
break;
6854
case "xaflag_m_pstate"_h: {
6855
// Can't set the flags in place due to the logical dependencies.
6856
uint32_t n = (~ReadNzcv().GetC() & ~ReadNzcv().GetZ()) & 1;
6857
uint32_t z = ReadNzcv().GetZ() & ReadNzcv().GetC();
6858
uint32_t c = ReadNzcv().GetC() | ReadNzcv().GetZ();
6859
uint32_t v = ~ReadNzcv().GetC() & ReadNzcv().GetZ();
6860
ReadNzcv().SetN(n);
6861
ReadNzcv().SetZ(z);
6862
ReadNzcv().SetC(c);
6863
ReadNzcv().SetV(v);
6864
break;
6865
}
6866
case "xpaclri_hi_hints"_h:
6867
WriteXRegister(30, StripPAC(ReadXRegister(30), kInstructionPointer));
6868
break;
6869
case "clrex_bn_barriers"_h:
6870
PrintExclusiveAccessWarning();
6871
ClearLocalMonitor();
6872
break;
6873
case "msr_sr_systemmove"_h:
6874
switch (instr->GetImmSystemRegister()) {
6875
case NZCV:
6876
ReadNzcv().SetRawValue(ReadWRegister(instr->GetRt()));
6877
LogSystemRegister(NZCV);
6878
break;
6879
case FPCR:
6880
ReadFpcr().SetRawValue(ReadWRegister(instr->GetRt()));
6881
LogSystemRegister(FPCR);
6882
break;
6883
default:
6884
VIXL_UNIMPLEMENTED();
6885
}
6886
break;
6887
case "mrs_rs_systemmove"_h:
6888
switch (instr->GetImmSystemRegister()) {
6889
case NZCV:
6890
WriteXRegister(instr->GetRt(), ReadNzcv().GetRawValue());
6891
break;
6892
case FPCR:
6893
WriteXRegister(instr->GetRt(), ReadFpcr().GetRawValue());
6894
break;
6895
case RNDR:
6896
case RNDRRS: {
6897
uint64_t high = jrand48(rand_state_);
6898
uint64_t low = jrand48(rand_state_);
6899
uint64_t rand_num = (high << 32) | (low & 0xffffffff);
6900
WriteXRegister(instr->GetRt(), rand_num);
6901
// Simulate successful random number generation.
6902
// TODO: Return failure occasionally as a random number cannot be
6903
// returned in a period of time.
6904
ReadNzcv().SetRawValue(NoFlag);
6905
LogSystemRegister(NZCV);
6906
break;
6907
}
6908
default:
6909
VIXL_UNIMPLEMENTED();
6910
}
6911
break;
6912
case "nop_hi_hints"_h:
6913
case "esb_hi_hints"_h:
6914
case "csdb_hi_hints"_h:
6915
break;
6916
case "bti_hb_hints"_h:
6917
switch (instr->GetImmHint()) {
6918
case BTI_jc:
6919
break;
6920
case BTI:
6921
if (PcIsInGuardedPage() && (ReadBType() != DefaultBType)) {
6922
VIXL_ABORT_WITH_MSG("Executing BTI with wrong BType.");
6923
}
6924
break;
6925
case BTI_c:
6926
if (PcIsInGuardedPage() &&
6927
(ReadBType() == BranchFromGuardedNotToIP)) {
6928
VIXL_ABORT_WITH_MSG("Executing BTI c with wrong BType.");
6929
}
6930
break;
6931
case BTI_j:
6932
if (PcIsInGuardedPage() && (ReadBType() == BranchAndLink)) {
6933
VIXL_ABORT_WITH_MSG("Executing BTI j with wrong BType.");
6934
}
6935
break;
6936
default:
6937
VIXL_UNREACHABLE();
6938
}
6939
return;
6940
case "pacib1716_hi_hints"_h:
6941
pac_key = kPACKeyIB;
6942
VIXL_FALLTHROUGH();
6943
case "pacia1716_hi_hints"_h:
6944
PACHelper(17, 16, pac_key, &Simulator::AddPAC);
6945
break;
6946
case "pacibsp_hi_hints"_h:
6947
pac_key = kPACKeyIB;
6948
VIXL_FALLTHROUGH();
6949
case "paciasp_hi_hints"_h:
6950
PACHelper(30, 31, pac_key, &Simulator::AddPAC);
6951
6952
// Check BType allows PACI[AB]SP instructions.
6953
if (PcIsInGuardedPage()) {
6954
switch (ReadBType()) {
6955
case BranchFromGuardedNotToIP:
6956
// TODO: This case depends on the value of SCTLR_EL1.BT0, which we
6957
// assume here to be zero. This allows execution of PACI[AB]SP when
6958
// BTYPE is BranchFromGuardedNotToIP (0b11).
6959
case DefaultBType:
6960
case BranchFromUnguardedOrToIP:
6961
case BranchAndLink:
6962
break;
6963
}
6964
}
6965
break;
6966
case "pacibz_hi_hints"_h:
6967
pac_key = kPACKeyIB;
6968
VIXL_FALLTHROUGH();
6969
case "paciaz_hi_hints"_h:
6970
PACHelper(30, -1, pac_key, &Simulator::AddPAC);
6971
break;
6972
case "autib1716_hi_hints"_h:
6973
pac_key = kPACKeyIB;
6974
VIXL_FALLTHROUGH();
6975
case "autia1716_hi_hints"_h:
6976
PACHelper(17, 16, pac_key, &Simulator::AuthPAC);
6977
break;
6978
case "autibsp_hi_hints"_h:
6979
pac_key = kPACKeyIB;
6980
VIXL_FALLTHROUGH();
6981
case "autiasp_hi_hints"_h:
6982
PACHelper(30, 31, pac_key, &Simulator::AuthPAC);
6983
break;
6984
case "autibz_hi_hints"_h:
6985
pac_key = kPACKeyIB;
6986
VIXL_FALLTHROUGH();
6987
case "autiaz_hi_hints"_h:
6988
PACHelper(30, -1, pac_key, &Simulator::AuthPAC);
6989
break;
6990
case "dsb_bo_barriers"_h:
6991
case "dmb_bo_barriers"_h:
6992
case "isb_bi_barriers"_h:
6993
__sync_synchronize();
6994
break;
6995
case "sys_cr_systeminstrs"_h:
6996
SysOp_W(instr->GetSysOp(), ReadXRegister(instr->GetRt()));
6997
break;
6998
default:
6999
VIXL_UNIMPLEMENTED();
7000
}
7001
}
7002
7003
7004
void Simulator::VisitException(const Instruction* instr) {
7005
switch (instr->Mask(ExceptionMask)) {
7006
case HLT:
7007
switch (instr->GetImmException()) {
7008
case kUnreachableOpcode:
7009
DoUnreachable(instr);
7010
return;
7011
case kTraceOpcode:
7012
DoTrace(instr);
7013
return;
7014
case kLogOpcode:
7015
DoLog(instr);
7016
return;
7017
case kPrintfOpcode:
7018
DoPrintf(instr);
7019
return;
7020
case kRuntimeCallOpcode:
7021
DoRuntimeCall(instr);
7022
return;
7023
case kSetCPUFeaturesOpcode:
7024
case kEnableCPUFeaturesOpcode:
7025
case kDisableCPUFeaturesOpcode:
7026
DoConfigureCPUFeatures(instr);
7027
return;
7028
case kSaveCPUFeaturesOpcode:
7029
DoSaveCPUFeatures(instr);
7030
return;
7031
case kRestoreCPUFeaturesOpcode:
7032
DoRestoreCPUFeatures(instr);
7033
return;
7034
case kMTEActive:
7035
MetaDataDepot::MetaDataMTE::SetActive(true);
7036
return;
7037
case kMTEInactive:
7038
MetaDataDepot::MetaDataMTE::SetActive(false);
7039
return;
7040
default:
7041
HostBreakpoint();
7042
return;
7043
}
7044
case BRK:
7045
if (debugger_enabled_) {
7046
uint64_t next_instr =
7047
reinterpret_cast<uint64_t>(pc_->GetNextInstruction());
7048
if (!debugger_->IsBreakpoint(next_instr)) {
7049
debugger_->RegisterBreakpoint(next_instr);
7050
}
7051
} else {
7052
HostBreakpoint();
7053
}
7054
return;
7055
default:
7056
VIXL_UNIMPLEMENTED();
7057
}
7058
}
7059
7060
7061
void Simulator::VisitCrypto2RegSHA(const Instruction* instr) {
7062
VisitUnimplemented(instr);
7063
}
7064
7065
7066
void Simulator::VisitCrypto3RegSHA(const Instruction* instr) {
7067
VisitUnimplemented(instr);
7068
}
7069
7070
7071
void Simulator::VisitCryptoAES(const Instruction* instr) {
7072
VisitUnimplemented(instr);
7073
}
7074
7075
7076
void Simulator::VisitNEON2RegMisc(const Instruction* instr) {
7077
NEONFormatDecoder nfd(instr);
7078
VectorFormat vf = nfd.GetVectorFormat();
7079
7080
static const NEONFormatMap map_lp =
7081
{{23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
7082
VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
7083
7084
static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
7085
VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
7086
7087
static const NEONFormatMap map_fcvtn = {{22, 30},
7088
{NF_4H, NF_8H, NF_2S, NF_4S}};
7089
VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
7090
7091
SimVRegister& rd = ReadVRegister(instr->GetRd());
7092
SimVRegister& rn = ReadVRegister(instr->GetRn());
7093
7094
if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
7095
// These instructions all use a two bit size field, except NOT and RBIT,
7096
// which use the field to encode the operation.
7097
switch (instr->Mask(NEON2RegMiscMask)) {
7098
case NEON_REV64:
7099
rev64(vf, rd, rn);
7100
break;
7101
case NEON_REV32:
7102
rev32(vf, rd, rn);
7103
break;
7104
case NEON_REV16:
7105
rev16(vf, rd, rn);
7106
break;
7107
case NEON_SUQADD:
7108
suqadd(vf, rd, rd, rn);
7109
break;
7110
case NEON_USQADD:
7111
usqadd(vf, rd, rd, rn);
7112
break;
7113
case NEON_CLS:
7114
cls(vf, rd, rn);
7115
break;
7116
case NEON_CLZ:
7117
clz(vf, rd, rn);
7118
break;
7119
case NEON_CNT:
7120
cnt(vf, rd, rn);
7121
break;
7122
case NEON_SQABS:
7123
abs(vf, rd, rn).SignedSaturate(vf);
7124
break;
7125
case NEON_SQNEG:
7126
neg(vf, rd, rn).SignedSaturate(vf);
7127
break;
7128
case NEON_CMGT_zero:
7129
cmp(vf, rd, rn, 0, gt);
7130
break;
7131
case NEON_CMGE_zero:
7132
cmp(vf, rd, rn, 0, ge);
7133
break;
7134
case NEON_CMEQ_zero:
7135
cmp(vf, rd, rn, 0, eq);
7136
break;
7137
case NEON_CMLE_zero:
7138
cmp(vf, rd, rn, 0, le);
7139
break;
7140
case NEON_CMLT_zero:
7141
cmp(vf, rd, rn, 0, lt);
7142
break;
7143
case NEON_ABS:
7144
abs(vf, rd, rn);
7145
break;
7146
case NEON_NEG:
7147
neg(vf, rd, rn);
7148
break;
7149
case NEON_SADDLP:
7150
saddlp(vf_lp, rd, rn);
7151
break;
7152
case NEON_UADDLP:
7153
uaddlp(vf_lp, rd, rn);
7154
break;
7155
case NEON_SADALP:
7156
sadalp(vf_lp, rd, rn);
7157
break;
7158
case NEON_UADALP:
7159
uadalp(vf_lp, rd, rn);
7160
break;
7161
case NEON_RBIT_NOT:
7162
vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
7163
switch (instr->GetFPType()) {
7164
case 0:
7165
not_(vf, rd, rn);
7166
break;
7167
case 1:
7168
rbit(vf, rd, rn);
7169
break;
7170
default:
7171
VIXL_UNIMPLEMENTED();
7172
}
7173
break;
7174
}
7175
} else {
7176
VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
7177
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
7178
bool inexact_exception = false;
7179
FrintMode frint_mode = kFrintToInteger;
7180
7181
// These instructions all use a one bit size field, except XTN, SQXTUN,
7182
// SHLL, SQXTN and UQXTN, which use a two bit size field.
7183
switch (instr->Mask(NEON2RegMiscFPMask)) {
7184
case NEON_FABS:
7185
fabs_(fpf, rd, rn);
7186
return;
7187
case NEON_FNEG:
7188
fneg(fpf, rd, rn);
7189
return;
7190
case NEON_FSQRT:
7191
fsqrt(fpf, rd, rn);
7192
return;
7193
case NEON_FCVTL:
7194
if (instr->Mask(NEON_Q)) {
7195
fcvtl2(vf_fcvtl, rd, rn);
7196
} else {
7197
fcvtl(vf_fcvtl, rd, rn);
7198
}
7199
return;
7200
case NEON_FCVTN:
7201
if (instr->Mask(NEON_Q)) {
7202
fcvtn2(vf_fcvtn, rd, rn);
7203
} else {
7204
fcvtn(vf_fcvtn, rd, rn);
7205
}
7206
return;
7207
case NEON_FCVTXN:
7208
if (instr->Mask(NEON_Q)) {
7209
fcvtxn2(vf_fcvtn, rd, rn);
7210
} else {
7211
fcvtxn(vf_fcvtn, rd, rn);
7212
}
7213
return;
7214
7215
// The following instructions break from the switch statement, rather
7216
// than return.
7217
case NEON_FRINT32X:
7218
inexact_exception = true;
7219
frint_mode = kFrintToInt32;
7220
break; // Use FPCR rounding mode.
7221
case NEON_FRINT32Z:
7222
inexact_exception = true;
7223
frint_mode = kFrintToInt32;
7224
fpcr_rounding = FPZero;
7225
break;
7226
case NEON_FRINT64X:
7227
inexact_exception = true;
7228
frint_mode = kFrintToInt64;
7229
break; // Use FPCR rounding mode.
7230
case NEON_FRINT64Z:
7231
inexact_exception = true;
7232
frint_mode = kFrintToInt64;
7233
fpcr_rounding = FPZero;
7234
break;
7235
case NEON_FRINTI:
7236
break; // Use FPCR rounding mode.
7237
case NEON_FRINTX:
7238
inexact_exception = true;
7239
break;
7240
case NEON_FRINTA:
7241
fpcr_rounding = FPTieAway;
7242
break;
7243
case NEON_FRINTM:
7244
fpcr_rounding = FPNegativeInfinity;
7245
break;
7246
case NEON_FRINTN:
7247
fpcr_rounding = FPTieEven;
7248
break;
7249
case NEON_FRINTP:
7250
fpcr_rounding = FPPositiveInfinity;
7251
break;
7252
case NEON_FRINTZ:
7253
fpcr_rounding = FPZero;
7254
break;
7255
7256
case NEON_FCVTNS:
7257
fcvts(fpf, rd, rn, FPTieEven);
7258
return;
7259
case NEON_FCVTNU:
7260
fcvtu(fpf, rd, rn, FPTieEven);
7261
return;
7262
case NEON_FCVTPS:
7263
fcvts(fpf, rd, rn, FPPositiveInfinity);
7264
return;
7265
case NEON_FCVTPU:
7266
fcvtu(fpf, rd, rn, FPPositiveInfinity);
7267
return;
7268
case NEON_FCVTMS:
7269
fcvts(fpf, rd, rn, FPNegativeInfinity);
7270
return;
7271
case NEON_FCVTMU:
7272
fcvtu(fpf, rd, rn, FPNegativeInfinity);
7273
return;
7274
case NEON_FCVTZS:
7275
fcvts(fpf, rd, rn, FPZero);
7276
return;
7277
case NEON_FCVTZU:
7278
fcvtu(fpf, rd, rn, FPZero);
7279
return;
7280
case NEON_FCVTAS:
7281
fcvts(fpf, rd, rn, FPTieAway);
7282
return;
7283
case NEON_FCVTAU:
7284
fcvtu(fpf, rd, rn, FPTieAway);
7285
return;
7286
case NEON_SCVTF:
7287
scvtf(fpf, rd, rn, 0, fpcr_rounding);
7288
return;
7289
case NEON_UCVTF:
7290
ucvtf(fpf, rd, rn, 0, fpcr_rounding);
7291
return;
7292
case NEON_URSQRTE:
7293
ursqrte(fpf, rd, rn);
7294
return;
7295
case NEON_URECPE:
7296
urecpe(fpf, rd, rn);
7297
return;
7298
case NEON_FRSQRTE:
7299
frsqrte(fpf, rd, rn);
7300
return;
7301
case NEON_FRECPE:
7302
frecpe(fpf, rd, rn, fpcr_rounding);
7303
return;
7304
case NEON_FCMGT_zero:
7305
fcmp_zero(fpf, rd, rn, gt);
7306
return;
7307
case NEON_FCMGE_zero:
7308
fcmp_zero(fpf, rd, rn, ge);
7309
return;
7310
case NEON_FCMEQ_zero:
7311
fcmp_zero(fpf, rd, rn, eq);
7312
return;
7313
case NEON_FCMLE_zero:
7314
fcmp_zero(fpf, rd, rn, le);
7315
return;
7316
case NEON_FCMLT_zero:
7317
fcmp_zero(fpf, rd, rn, lt);
7318
return;
7319
default:
7320
if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
7321
(instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
7322
switch (instr->Mask(NEON2RegMiscMask)) {
7323
case NEON_XTN:
7324
xtn(vf, rd, rn);
7325
return;
7326
case NEON_SQXTN:
7327
sqxtn(vf, rd, rn);
7328
return;
7329
case NEON_UQXTN:
7330
uqxtn(vf, rd, rn);
7331
return;
7332
case NEON_SQXTUN:
7333
sqxtun(vf, rd, rn);
7334
return;
7335
case NEON_SHLL:
7336
vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7337
if (instr->Mask(NEON_Q)) {
7338
shll2(vf, rd, rn);
7339
} else {
7340
shll(vf, rd, rn);
7341
}
7342
return;
7343
default:
7344
VIXL_UNIMPLEMENTED();
7345
}
7346
} else {
7347
VIXL_UNIMPLEMENTED();
7348
}
7349
}
7350
7351
// Only FRINT* instructions fall through the switch above.
7352
frint(fpf, rd, rn, fpcr_rounding, inexact_exception, frint_mode);
7353
}
7354
}
7355
7356
7357
void Simulator::VisitNEON2RegMiscFP16(const Instruction* instr) {
7358
static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
7359
NEONFormatDecoder nfd(instr);
7360
VectorFormat fpf = nfd.GetVectorFormat(&map_half);
7361
7362
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
7363
7364
SimVRegister& rd = ReadVRegister(instr->GetRd());
7365
SimVRegister& rn = ReadVRegister(instr->GetRn());
7366
7367
switch (instr->Mask(NEON2RegMiscFP16Mask)) {
7368
case NEON_SCVTF_H:
7369
scvtf(fpf, rd, rn, 0, fpcr_rounding);
7370
return;
7371
case NEON_UCVTF_H:
7372
ucvtf(fpf, rd, rn, 0, fpcr_rounding);
7373
return;
7374
case NEON_FCVTNS_H:
7375
fcvts(fpf, rd, rn, FPTieEven);
7376
return;
7377
case NEON_FCVTNU_H:
7378
fcvtu(fpf, rd, rn, FPTieEven);
7379
return;
7380
case NEON_FCVTPS_H:
7381
fcvts(fpf, rd, rn, FPPositiveInfinity);
7382
return;
7383
case NEON_FCVTPU_H:
7384
fcvtu(fpf, rd, rn, FPPositiveInfinity);
7385
return;
7386
case NEON_FCVTMS_H:
7387
fcvts(fpf, rd, rn, FPNegativeInfinity);
7388
return;
7389
case NEON_FCVTMU_H:
7390
fcvtu(fpf, rd, rn, FPNegativeInfinity);
7391
return;
7392
case NEON_FCVTZS_H:
7393
fcvts(fpf, rd, rn, FPZero);
7394
return;
7395
case NEON_FCVTZU_H:
7396
fcvtu(fpf, rd, rn, FPZero);
7397
return;
7398
case NEON_FCVTAS_H:
7399
fcvts(fpf, rd, rn, FPTieAway);
7400
return;
7401
case NEON_FCVTAU_H:
7402
fcvtu(fpf, rd, rn, FPTieAway);
7403
return;
7404
case NEON_FRINTI_H:
7405
frint(fpf, rd, rn, fpcr_rounding, false);
7406
return;
7407
case NEON_FRINTX_H:
7408
frint(fpf, rd, rn, fpcr_rounding, true);
7409
return;
7410
case NEON_FRINTA_H:
7411
frint(fpf, rd, rn, FPTieAway, false);
7412
return;
7413
case NEON_FRINTM_H:
7414
frint(fpf, rd, rn, FPNegativeInfinity, false);
7415
return;
7416
case NEON_FRINTN_H:
7417
frint(fpf, rd, rn, FPTieEven, false);
7418
return;
7419
case NEON_FRINTP_H:
7420
frint(fpf, rd, rn, FPPositiveInfinity, false);
7421
return;
7422
case NEON_FRINTZ_H:
7423
frint(fpf, rd, rn, FPZero, false);
7424
return;
7425
case NEON_FABS_H:
7426
fabs_(fpf, rd, rn);
7427
return;
7428
case NEON_FNEG_H:
7429
fneg(fpf, rd, rn);
7430
return;
7431
case NEON_FSQRT_H:
7432
fsqrt(fpf, rd, rn);
7433
return;
7434
case NEON_FRSQRTE_H:
7435
frsqrte(fpf, rd, rn);
7436
return;
7437
case NEON_FRECPE_H:
7438
frecpe(fpf, rd, rn, fpcr_rounding);
7439
return;
7440
case NEON_FCMGT_H_zero:
7441
fcmp_zero(fpf, rd, rn, gt);
7442
return;
7443
case NEON_FCMGE_H_zero:
7444
fcmp_zero(fpf, rd, rn, ge);
7445
return;
7446
case NEON_FCMEQ_H_zero:
7447
fcmp_zero(fpf, rd, rn, eq);
7448
return;
7449
case NEON_FCMLE_H_zero:
7450
fcmp_zero(fpf, rd, rn, le);
7451
return;
7452
case NEON_FCMLT_H_zero:
7453
fcmp_zero(fpf, rd, rn, lt);
7454
return;
7455
default:
7456
VIXL_UNIMPLEMENTED();
7457
return;
7458
}
7459
}
7460
7461
7462
void Simulator::VisitNEON3Same(const Instruction* instr) {
7463
NEONFormatDecoder nfd(instr);
7464
SimVRegister& rd = ReadVRegister(instr->GetRd());
7465
SimVRegister& rn = ReadVRegister(instr->GetRn());
7466
SimVRegister& rm = ReadVRegister(instr->GetRm());
7467
7468
if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
7469
VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
7470
switch (instr->Mask(NEON3SameLogicalMask)) {
7471
case NEON_AND:
7472
and_(vf, rd, rn, rm);
7473
break;
7474
case NEON_ORR:
7475
orr(vf, rd, rn, rm);
7476
break;
7477
case NEON_ORN:
7478
orn(vf, rd, rn, rm);
7479
break;
7480
case NEON_EOR:
7481
eor(vf, rd, rn, rm);
7482
break;
7483
case NEON_BIC:
7484
bic(vf, rd, rn, rm);
7485
break;
7486
case NEON_BIF:
7487
bif(vf, rd, rn, rm);
7488
break;
7489
case NEON_BIT:
7490
bit(vf, rd, rn, rm);
7491
break;
7492
case NEON_BSL:
7493
bsl(vf, rd, rd, rn, rm);
7494
break;
7495
default:
7496
VIXL_UNIMPLEMENTED();
7497
}
7498
} else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
7499
VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
7500
switch (instr->Mask(NEON3SameFPMask)) {
7501
case NEON_FADD:
7502
fadd(vf, rd, rn, rm);
7503
break;
7504
case NEON_FSUB:
7505
fsub(vf, rd, rn, rm);
7506
break;
7507
case NEON_FMUL:
7508
fmul(vf, rd, rn, rm);
7509
break;
7510
case NEON_FDIV:
7511
fdiv(vf, rd, rn, rm);
7512
break;
7513
case NEON_FMAX:
7514
fmax(vf, rd, rn, rm);
7515
break;
7516
case NEON_FMIN:
7517
fmin(vf, rd, rn, rm);
7518
break;
7519
case NEON_FMAXNM:
7520
fmaxnm(vf, rd, rn, rm);
7521
break;
7522
case NEON_FMINNM:
7523
fminnm(vf, rd, rn, rm);
7524
break;
7525
case NEON_FMLA:
7526
fmla(vf, rd, rd, rn, rm);
7527
break;
7528
case NEON_FMLS:
7529
fmls(vf, rd, rd, rn, rm);
7530
break;
7531
case NEON_FMULX:
7532
fmulx(vf, rd, rn, rm);
7533
break;
7534
case NEON_FACGE:
7535
fabscmp(vf, rd, rn, rm, ge);
7536
break;
7537
case NEON_FACGT:
7538
fabscmp(vf, rd, rn, rm, gt);
7539
break;
7540
case NEON_FCMEQ:
7541
fcmp(vf, rd, rn, rm, eq);
7542
break;
7543
case NEON_FCMGE:
7544
fcmp(vf, rd, rn, rm, ge);
7545
break;
7546
case NEON_FCMGT:
7547
fcmp(vf, rd, rn, rm, gt);
7548
break;
7549
case NEON_FRECPS:
7550
frecps(vf, rd, rn, rm);
7551
break;
7552
case NEON_FRSQRTS:
7553
frsqrts(vf, rd, rn, rm);
7554
break;
7555
case NEON_FABD:
7556
fabd(vf, rd, rn, rm);
7557
break;
7558
case NEON_FADDP:
7559
faddp(vf, rd, rn, rm);
7560
break;
7561
case NEON_FMAXP:
7562
fmaxp(vf, rd, rn, rm);
7563
break;
7564
case NEON_FMAXNMP:
7565
fmaxnmp(vf, rd, rn, rm);
7566
break;
7567
case NEON_FMINP:
7568
fminp(vf, rd, rn, rm);
7569
break;
7570
case NEON_FMINNMP:
7571
fminnmp(vf, rd, rn, rm);
7572
break;
7573
default:
7574
// FMLAL{2} and FMLSL{2} have special-case encodings.
7575
switch (instr->Mask(NEON3SameFHMMask)) {
7576
case NEON_FMLAL:
7577
fmlal(vf, rd, rn, rm);
7578
break;
7579
case NEON_FMLAL2:
7580
fmlal2(vf, rd, rn, rm);
7581
break;
7582
case NEON_FMLSL:
7583
fmlsl(vf, rd, rn, rm);
7584
break;
7585
case NEON_FMLSL2:
7586
fmlsl2(vf, rd, rn, rm);
7587
break;
7588
default:
7589
VIXL_UNIMPLEMENTED();
7590
}
7591
}
7592
} else {
7593
VectorFormat vf = nfd.GetVectorFormat();
7594
switch (instr->Mask(NEON3SameMask)) {
7595
case NEON_ADD:
7596
add(vf, rd, rn, rm);
7597
break;
7598
case NEON_ADDP:
7599
addp(vf, rd, rn, rm);
7600
break;
7601
case NEON_CMEQ:
7602
cmp(vf, rd, rn, rm, eq);
7603
break;
7604
case NEON_CMGE:
7605
cmp(vf, rd, rn, rm, ge);
7606
break;
7607
case NEON_CMGT:
7608
cmp(vf, rd, rn, rm, gt);
7609
break;
7610
case NEON_CMHI:
7611
cmp(vf, rd, rn, rm, hi);
7612
break;
7613
case NEON_CMHS:
7614
cmp(vf, rd, rn, rm, hs);
7615
break;
7616
case NEON_CMTST:
7617
cmptst(vf, rd, rn, rm);
7618
break;
7619
case NEON_MLS:
7620
mls(vf, rd, rd, rn, rm);
7621
break;
7622
case NEON_MLA:
7623
mla(vf, rd, rd, rn, rm);
7624
break;
7625
case NEON_MUL:
7626
mul(vf, rd, rn, rm);
7627
break;
7628
case NEON_PMUL:
7629
pmul(vf, rd, rn, rm);
7630
break;
7631
case NEON_SMAX:
7632
smax(vf, rd, rn, rm);
7633
break;
7634
case NEON_SMAXP:
7635
smaxp(vf, rd, rn, rm);
7636
break;
7637
case NEON_SMIN:
7638
smin(vf, rd, rn, rm);
7639
break;
7640
case NEON_SMINP:
7641
sminp(vf, rd, rn, rm);
7642
break;
7643
case NEON_SUB:
7644
sub(vf, rd, rn, rm);
7645
break;
7646
case NEON_UMAX:
7647
umax(vf, rd, rn, rm);
7648
break;
7649
case NEON_UMAXP:
7650
umaxp(vf, rd, rn, rm);
7651
break;
7652
case NEON_UMIN:
7653
umin(vf, rd, rn, rm);
7654
break;
7655
case NEON_UMINP:
7656
uminp(vf, rd, rn, rm);
7657
break;
7658
case NEON_SSHL:
7659
sshl(vf, rd, rn, rm);
7660
break;
7661
case NEON_USHL:
7662
ushl(vf, rd, rn, rm);
7663
break;
7664
case NEON_SABD:
7665
absdiff(vf, rd, rn, rm, true);
7666
break;
7667
case NEON_UABD:
7668
absdiff(vf, rd, rn, rm, false);
7669
break;
7670
case NEON_SABA:
7671
saba(vf, rd, rn, rm);
7672
break;
7673
case NEON_UABA:
7674
uaba(vf, rd, rn, rm);
7675
break;
7676
case NEON_UQADD:
7677
add(vf, rd, rn, rm).UnsignedSaturate(vf);
7678
break;
7679
case NEON_SQADD:
7680
add(vf, rd, rn, rm).SignedSaturate(vf);
7681
break;
7682
case NEON_UQSUB:
7683
sub(vf, rd, rn, rm).UnsignedSaturate(vf);
7684
break;
7685
case NEON_SQSUB:
7686
sub(vf, rd, rn, rm).SignedSaturate(vf);
7687
break;
7688
case NEON_SQDMULH:
7689
sqdmulh(vf, rd, rn, rm);
7690
break;
7691
case NEON_SQRDMULH:
7692
sqrdmulh(vf, rd, rn, rm);
7693
break;
7694
case NEON_UQSHL:
7695
ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
7696
break;
7697
case NEON_SQSHL:
7698
sshl(vf, rd, rn, rm).SignedSaturate(vf);
7699
break;
7700
case NEON_URSHL:
7701
ushl(vf, rd, rn, rm).Round(vf);
7702
break;
7703
case NEON_SRSHL:
7704
sshl(vf, rd, rn, rm).Round(vf);
7705
break;
7706
case NEON_UQRSHL:
7707
ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
7708
break;
7709
case NEON_SQRSHL:
7710
sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
7711
break;
7712
case NEON_UHADD:
7713
add(vf, rd, rn, rm).Uhalve(vf);
7714
break;
7715
case NEON_URHADD:
7716
add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
7717
break;
7718
case NEON_SHADD:
7719
add(vf, rd, rn, rm).Halve(vf);
7720
break;
7721
case NEON_SRHADD:
7722
add(vf, rd, rn, rm).Halve(vf).Round(vf);
7723
break;
7724
case NEON_UHSUB:
7725
sub(vf, rd, rn, rm).Uhalve(vf);
7726
break;
7727
case NEON_SHSUB:
7728
sub(vf, rd, rn, rm).Halve(vf);
7729
break;
7730
default:
7731
VIXL_UNIMPLEMENTED();
7732
}
7733
}
7734
}
7735
7736
7737
void Simulator::VisitNEON3SameFP16(const Instruction* instr) {
7738
NEONFormatDecoder nfd(instr);
7739
SimVRegister& rd = ReadVRegister(instr->GetRd());
7740
SimVRegister& rn = ReadVRegister(instr->GetRn());
7741
SimVRegister& rm = ReadVRegister(instr->GetRm());
7742
7743
VectorFormat vf = nfd.GetVectorFormat(nfd.FP16FormatMap());
7744
switch (instr->Mask(NEON3SameFP16Mask)) {
7745
#define SIM_FUNC(A, B) \
7746
case NEON_##A##_H: \
7747
B(vf, rd, rn, rm); \
7748
break;
7749
SIM_FUNC(FMAXNM, fmaxnm);
7750
SIM_FUNC(FADD, fadd);
7751
SIM_FUNC(FMULX, fmulx);
7752
SIM_FUNC(FMAX, fmax);
7753
SIM_FUNC(FRECPS, frecps);
7754
SIM_FUNC(FMINNM, fminnm);
7755
SIM_FUNC(FSUB, fsub);
7756
SIM_FUNC(FMIN, fmin);
7757
SIM_FUNC(FRSQRTS, frsqrts);
7758
SIM_FUNC(FMAXNMP, fmaxnmp);
7759
SIM_FUNC(FADDP, faddp);
7760
SIM_FUNC(FMUL, fmul);
7761
SIM_FUNC(FMAXP, fmaxp);
7762
SIM_FUNC(FDIV, fdiv);
7763
SIM_FUNC(FMINNMP, fminnmp);
7764
SIM_FUNC(FABD, fabd);
7765
SIM_FUNC(FMINP, fminp);
7766
#undef SIM_FUNC
7767
case NEON_FMLA_H:
7768
fmla(vf, rd, rd, rn, rm);
7769
break;
7770
case NEON_FMLS_H:
7771
fmls(vf, rd, rd, rn, rm);
7772
break;
7773
case NEON_FCMEQ_H:
7774
fcmp(vf, rd, rn, rm, eq);
7775
break;
7776
case NEON_FCMGE_H:
7777
fcmp(vf, rd, rn, rm, ge);
7778
break;
7779
case NEON_FACGE_H:
7780
fabscmp(vf, rd, rn, rm, ge);
7781
break;
7782
case NEON_FCMGT_H:
7783
fcmp(vf, rd, rn, rm, gt);
7784
break;
7785
case NEON_FACGT_H:
7786
fabscmp(vf, rd, rn, rm, gt);
7787
break;
7788
default:
7789
VIXL_UNIMPLEMENTED();
7790
break;
7791
}
7792
}
7793
7794
void Simulator::VisitNEON3SameExtra(const Instruction* instr) {
7795
NEONFormatDecoder nfd(instr);
7796
SimVRegister& rd = ReadVRegister(instr->GetRd());
7797
SimVRegister& rn = ReadVRegister(instr->GetRn());
7798
SimVRegister& rm = ReadVRegister(instr->GetRm());
7799
int rot = 0;
7800
VectorFormat vf = nfd.GetVectorFormat();
7801
7802
switch (form_hash_) {
7803
case "fcmla_asimdsame2_c"_h:
7804
rot = instr->GetImmRotFcmlaVec();
7805
fcmla(vf, rd, rn, rm, rd, rot);
7806
break;
7807
case "fcadd_asimdsame2_c"_h:
7808
rot = instr->GetImmRotFcadd();
7809
fcadd(vf, rd, rn, rm, rot);
7810
break;
7811
case "sdot_asimdsame2_d"_h:
7812
sdot(vf, rd, rn, rm);
7813
break;
7814
case "udot_asimdsame2_d"_h:
7815
udot(vf, rd, rn, rm);
7816
break;
7817
case "usdot_asimdsame2_d"_h:
7818
usdot(vf, rd, rn, rm);
7819
break;
7820
case "sqrdmlah_asimdsame2_only"_h:
7821
sqrdmlah(vf, rd, rn, rm);
7822
break;
7823
case "sqrdmlsh_asimdsame2_only"_h:
7824
sqrdmlsh(vf, rd, rn, rm);
7825
break;
7826
}
7827
}
7828
7829
7830
void Simulator::VisitNEON3Different(const Instruction* instr) {
7831
NEONFormatDecoder nfd(instr);
7832
VectorFormat vf = nfd.GetVectorFormat();
7833
VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
7834
7835
SimVRegister& rd = ReadVRegister(instr->GetRd());
7836
SimVRegister& rn = ReadVRegister(instr->GetRn());
7837
SimVRegister& rm = ReadVRegister(instr->GetRm());
7838
int size = instr->GetNEONSize();
7839
7840
switch (instr->Mask(NEON3DifferentMask)) {
7841
case NEON_PMULL:
7842
if ((size == 1) || (size == 2)) { // S/D reserved.
7843
VisitUnallocated(instr);
7844
} else {
7845
if (size == 3) vf_l = kFormat1Q;
7846
pmull(vf_l, rd, rn, rm);
7847
}
7848
break;
7849
case NEON_PMULL2:
7850
if ((size == 1) || (size == 2)) { // S/D reserved.
7851
VisitUnallocated(instr);
7852
} else {
7853
if (size == 3) vf_l = kFormat1Q;
7854
pmull2(vf_l, rd, rn, rm);
7855
}
7856
break;
7857
case NEON_UADDL:
7858
uaddl(vf_l, rd, rn, rm);
7859
break;
7860
case NEON_UADDL2:
7861
uaddl2(vf_l, rd, rn, rm);
7862
break;
7863
case NEON_SADDL:
7864
saddl(vf_l, rd, rn, rm);
7865
break;
7866
case NEON_SADDL2:
7867
saddl2(vf_l, rd, rn, rm);
7868
break;
7869
case NEON_USUBL:
7870
usubl(vf_l, rd, rn, rm);
7871
break;
7872
case NEON_USUBL2:
7873
usubl2(vf_l, rd, rn, rm);
7874
break;
7875
case NEON_SSUBL:
7876
ssubl(vf_l, rd, rn, rm);
7877
break;
7878
case NEON_SSUBL2:
7879
ssubl2(vf_l, rd, rn, rm);
7880
break;
7881
case NEON_SABAL:
7882
sabal(vf_l, rd, rn, rm);
7883
break;
7884
case NEON_SABAL2:
7885
sabal2(vf_l, rd, rn, rm);
7886
break;
7887
case NEON_UABAL:
7888
uabal(vf_l, rd, rn, rm);
7889
break;
7890
case NEON_UABAL2:
7891
uabal2(vf_l, rd, rn, rm);
7892
break;
7893
case NEON_SABDL:
7894
sabdl(vf_l, rd, rn, rm);
7895
break;
7896
case NEON_SABDL2:
7897
sabdl2(vf_l, rd, rn, rm);
7898
break;
7899
case NEON_UABDL:
7900
uabdl(vf_l, rd, rn, rm);
7901
break;
7902
case NEON_UABDL2:
7903
uabdl2(vf_l, rd, rn, rm);
7904
break;
7905
case NEON_SMLAL:
7906
smlal(vf_l, rd, rn, rm);
7907
break;
7908
case NEON_SMLAL2:
7909
smlal2(vf_l, rd, rn, rm);
7910
break;
7911
case NEON_UMLAL:
7912
umlal(vf_l, rd, rn, rm);
7913
break;
7914
case NEON_UMLAL2:
7915
umlal2(vf_l, rd, rn, rm);
7916
break;
7917
case NEON_SMLSL:
7918
smlsl(vf_l, rd, rn, rm);
7919
break;
7920
case NEON_SMLSL2:
7921
smlsl2(vf_l, rd, rn, rm);
7922
break;
7923
case NEON_UMLSL:
7924
umlsl(vf_l, rd, rn, rm);
7925
break;
7926
case NEON_UMLSL2:
7927
umlsl2(vf_l, rd, rn, rm);
7928
break;
7929
case NEON_SMULL:
7930
smull(vf_l, rd, rn, rm);
7931
break;
7932
case NEON_SMULL2:
7933
smull2(vf_l, rd, rn, rm);
7934
break;
7935
case NEON_UMULL:
7936
umull(vf_l, rd, rn, rm);
7937
break;
7938
case NEON_UMULL2:
7939
umull2(vf_l, rd, rn, rm);
7940
break;
7941
case NEON_SQDMLAL:
7942
sqdmlal(vf_l, rd, rn, rm);
7943
break;
7944
case NEON_SQDMLAL2:
7945
sqdmlal2(vf_l, rd, rn, rm);
7946
break;
7947
case NEON_SQDMLSL:
7948
sqdmlsl(vf_l, rd, rn, rm);
7949
break;
7950
case NEON_SQDMLSL2:
7951
sqdmlsl2(vf_l, rd, rn, rm);
7952
break;
7953
case NEON_SQDMULL:
7954
sqdmull(vf_l, rd, rn, rm);
7955
break;
7956
case NEON_SQDMULL2:
7957
sqdmull2(vf_l, rd, rn, rm);
7958
break;
7959
case NEON_UADDW:
7960
uaddw(vf_l, rd, rn, rm);
7961
break;
7962
case NEON_UADDW2:
7963
uaddw2(vf_l, rd, rn, rm);
7964
break;
7965
case NEON_SADDW:
7966
saddw(vf_l, rd, rn, rm);
7967
break;
7968
case NEON_SADDW2:
7969
saddw2(vf_l, rd, rn, rm);
7970
break;
7971
case NEON_USUBW:
7972
usubw(vf_l, rd, rn, rm);
7973
break;
7974
case NEON_USUBW2:
7975
usubw2(vf_l, rd, rn, rm);
7976
break;
7977
case NEON_SSUBW:
7978
ssubw(vf_l, rd, rn, rm);
7979
break;
7980
case NEON_SSUBW2:
7981
ssubw2(vf_l, rd, rn, rm);
7982
break;
7983
case NEON_ADDHN:
7984
addhn(vf, rd, rn, rm);
7985
break;
7986
case NEON_ADDHN2:
7987
addhn2(vf, rd, rn, rm);
7988
break;
7989
case NEON_RADDHN:
7990
raddhn(vf, rd, rn, rm);
7991
break;
7992
case NEON_RADDHN2:
7993
raddhn2(vf, rd, rn, rm);
7994
break;
7995
case NEON_SUBHN:
7996
subhn(vf, rd, rn, rm);
7997
break;
7998
case NEON_SUBHN2:
7999
subhn2(vf, rd, rn, rm);
8000
break;
8001
case NEON_RSUBHN:
8002
rsubhn(vf, rd, rn, rm);
8003
break;
8004
case NEON_RSUBHN2:
8005
rsubhn2(vf, rd, rn, rm);
8006
break;
8007
default:
8008
VIXL_UNIMPLEMENTED();
8009
}
8010
}
8011
8012
8013
void Simulator::VisitNEONAcrossLanes(const Instruction* instr) {
8014
NEONFormatDecoder nfd(instr);
8015
8016
static const NEONFormatMap map_half = {{30}, {NF_4H, NF_8H}};
8017
8018
SimVRegister& rd = ReadVRegister(instr->GetRd());
8019
SimVRegister& rn = ReadVRegister(instr->GetRn());
8020
8021
if (instr->Mask(NEONAcrossLanesFP16FMask) == NEONAcrossLanesFP16Fixed) {
8022
VectorFormat vf = nfd.GetVectorFormat(&map_half);
8023
switch (instr->Mask(NEONAcrossLanesFP16Mask)) {
8024
case NEON_FMAXV_H:
8025
fmaxv(vf, rd, rn);
8026
break;
8027
case NEON_FMINV_H:
8028
fminv(vf, rd, rn);
8029
break;
8030
case NEON_FMAXNMV_H:
8031
fmaxnmv(vf, rd, rn);
8032
break;
8033
case NEON_FMINNMV_H:
8034
fminnmv(vf, rd, rn);
8035
break;
8036
default:
8037
VIXL_UNIMPLEMENTED();
8038
}
8039
} else if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
8040
// The input operand's VectorFormat is passed for these instructions.
8041
VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
8042
8043
switch (instr->Mask(NEONAcrossLanesFPMask)) {
8044
case NEON_FMAXV:
8045
fmaxv(vf, rd, rn);
8046
break;
8047
case NEON_FMINV:
8048
fminv(vf, rd, rn);
8049
break;
8050
case NEON_FMAXNMV:
8051
fmaxnmv(vf, rd, rn);
8052
break;
8053
case NEON_FMINNMV:
8054
fminnmv(vf, rd, rn);
8055
break;
8056
default:
8057
VIXL_UNIMPLEMENTED();
8058
}
8059
} else {
8060
VectorFormat vf = nfd.GetVectorFormat();
8061
8062
switch (instr->Mask(NEONAcrossLanesMask)) {
8063
case NEON_ADDV:
8064
addv(vf, rd, rn);
8065
break;
8066
case NEON_SMAXV:
8067
smaxv(vf, rd, rn);
8068
break;
8069
case NEON_SMINV:
8070
sminv(vf, rd, rn);
8071
break;
8072
case NEON_UMAXV:
8073
umaxv(vf, rd, rn);
8074
break;
8075
case NEON_UMINV:
8076
uminv(vf, rd, rn);
8077
break;
8078
case NEON_SADDLV:
8079
saddlv(vf, rd, rn);
8080
break;
8081
case NEON_UADDLV:
8082
uaddlv(vf, rd, rn);
8083
break;
8084
default:
8085
VIXL_UNIMPLEMENTED();
8086
}
8087
}
8088
}
8089
8090
void Simulator::SimulateNEONMulByElementLong(const Instruction* instr) {
8091
NEONFormatDecoder nfd(instr);
8092
VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
8093
8094
SimVRegister& rd = ReadVRegister(instr->GetRd());
8095
SimVRegister& rn = ReadVRegister(instr->GetRn());
8096
8097
int rm_reg = instr->GetRm();
8098
int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8099
if (instr->GetNEONSize() == 1) {
8100
rm_reg = instr->GetRmLow16();
8101
index = (index << 1) | instr->GetNEONM();
8102
}
8103
SimVRegister& rm = ReadVRegister(rm_reg);
8104
8105
SimVRegister temp;
8106
VectorFormat indexform =
8107
VectorFormatHalfWidthDoubleLanes(VectorFormatFillQ(vf));
8108
dup_element(indexform, temp, rm, index);
8109
8110
bool is_2 = instr->Mask(NEON_Q) ? true : false;
8111
8112
switch (form_hash_) {
8113
case "smull_asimdelem_l"_h:
8114
smull(vf, rd, rn, temp, is_2);
8115
break;
8116
case "umull_asimdelem_l"_h:
8117
umull(vf, rd, rn, temp, is_2);
8118
break;
8119
case "smlal_asimdelem_l"_h:
8120
smlal(vf, rd, rn, temp, is_2);
8121
break;
8122
case "umlal_asimdelem_l"_h:
8123
umlal(vf, rd, rn, temp, is_2);
8124
break;
8125
case "smlsl_asimdelem_l"_h:
8126
smlsl(vf, rd, rn, temp, is_2);
8127
break;
8128
case "umlsl_asimdelem_l"_h:
8129
umlsl(vf, rd, rn, temp, is_2);
8130
break;
8131
case "sqdmull_asimdelem_l"_h:
8132
sqdmull(vf, rd, rn, temp, is_2);
8133
break;
8134
case "sqdmlal_asimdelem_l"_h:
8135
sqdmlal(vf, rd, rn, temp, is_2);
8136
break;
8137
case "sqdmlsl_asimdelem_l"_h:
8138
sqdmlsl(vf, rd, rn, temp, is_2);
8139
break;
8140
default:
8141
VIXL_UNREACHABLE();
8142
}
8143
}
8144
8145
void Simulator::SimulateNEONFPMulByElementLong(const Instruction* instr) {
8146
VectorFormat vform = instr->GetNEONQ() ? kFormat4S : kFormat2S;
8147
SimVRegister& rd = ReadVRegister(instr->GetRd());
8148
SimVRegister& rn = ReadVRegister(instr->GetRn());
8149
SimVRegister& rm = ReadVRegister(instr->GetRmLow16());
8150
8151
int index =
8152
(instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
8153
8154
switch (form_hash_) {
8155
case "fmlal_asimdelem_lh"_h:
8156
fmlal(vform, rd, rn, rm, index);
8157
break;
8158
case "fmlal2_asimdelem_lh"_h:
8159
fmlal2(vform, rd, rn, rm, index);
8160
break;
8161
case "fmlsl_asimdelem_lh"_h:
8162
fmlsl(vform, rd, rn, rm, index);
8163
break;
8164
case "fmlsl2_asimdelem_lh"_h:
8165
fmlsl2(vform, rd, rn, rm, index);
8166
break;
8167
default:
8168
VIXL_UNREACHABLE();
8169
}
8170
}
8171
8172
void Simulator::SimulateNEONFPMulByElement(const Instruction* instr) {
8173
NEONFormatDecoder nfd(instr);
8174
static const NEONFormatMap map =
8175
{{23, 22, 30},
8176
{NF_4H, NF_8H, NF_UNDEF, NF_UNDEF, NF_2S, NF_4S, NF_UNDEF, NF_2D}};
8177
VectorFormat vform = nfd.GetVectorFormat(&map);
8178
8179
SimVRegister& rd = ReadVRegister(instr->GetRd());
8180
SimVRegister& rn = ReadVRegister(instr->GetRn());
8181
8182
int rm_reg = instr->GetRm();
8183
int index =
8184
(instr->GetNEONH() << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
8185
8186
if ((vform == kFormat4H) || (vform == kFormat8H)) {
8187
rm_reg &= 0xf;
8188
} else if ((vform == kFormat2S) || (vform == kFormat4S)) {
8189
index >>= 1;
8190
} else {
8191
VIXL_ASSERT(vform == kFormat2D);
8192
VIXL_ASSERT(instr->GetNEONL() == 0);
8193
index >>= 2;
8194
}
8195
8196
SimVRegister& rm = ReadVRegister(rm_reg);
8197
8198
switch (form_hash_) {
8199
case "fmul_asimdelem_rh_h"_h:
8200
case "fmul_asimdelem_r_sd"_h:
8201
fmul(vform, rd, rn, rm, index);
8202
break;
8203
case "fmla_asimdelem_rh_h"_h:
8204
case "fmla_asimdelem_r_sd"_h:
8205
fmla(vform, rd, rn, rm, index);
8206
break;
8207
case "fmls_asimdelem_rh_h"_h:
8208
case "fmls_asimdelem_r_sd"_h:
8209
fmls(vform, rd, rn, rm, index);
8210
break;
8211
case "fmulx_asimdelem_rh_h"_h:
8212
case "fmulx_asimdelem_r_sd"_h:
8213
fmulx(vform, rd, rn, rm, index);
8214
break;
8215
default:
8216
VIXL_UNREACHABLE();
8217
}
8218
}
8219
8220
void Simulator::SimulateNEONComplexMulByElement(const Instruction* instr) {
8221
VectorFormat vform = instr->GetNEONQ() ? kFormat8H : kFormat4H;
8222
SimVRegister& rd = ReadVRegister(instr->GetRd());
8223
SimVRegister& rn = ReadVRegister(instr->GetRn());
8224
SimVRegister& rm = ReadVRegister(instr->GetRm());
8225
int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8226
8227
switch (form_hash_) {
8228
case "fcmla_asimdelem_c_s"_h:
8229
vform = kFormat4S;
8230
index >>= 1;
8231
VIXL_FALLTHROUGH();
8232
case "fcmla_asimdelem_c_h"_h:
8233
fcmla(vform, rd, rn, rm, index, instr->GetImmRotFcmlaSca());
8234
break;
8235
default:
8236
VIXL_UNREACHABLE();
8237
}
8238
}
8239
8240
void Simulator::SimulateNEONDotProdByElement(const Instruction* instr) {
8241
VectorFormat vform = instr->GetNEONQ() ? kFormat4S : kFormat2S;
8242
8243
SimVRegister& rd = ReadVRegister(instr->GetRd());
8244
SimVRegister& rn = ReadVRegister(instr->GetRn());
8245
SimVRegister& rm = ReadVRegister(instr->GetRm());
8246
int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8247
8248
SimVRegister temp;
8249
// NEON indexed `dot` allows the index value exceed the register size.
8250
// Promote the format to Q-sized vector format before the duplication.
8251
dup_elements_to_segments(VectorFormatFillQ(vform), temp, rm, index);
8252
8253
switch (form_hash_) {
8254
case "sdot_asimdelem_d"_h:
8255
sdot(vform, rd, rn, temp);
8256
break;
8257
case "udot_asimdelem_d"_h:
8258
udot(vform, rd, rn, temp);
8259
break;
8260
case "sudot_asimdelem_d"_h:
8261
usdot(vform, rd, temp, rn);
8262
break;
8263
case "usdot_asimdelem_d"_h:
8264
usdot(vform, rd, rn, temp);
8265
break;
8266
}
8267
}
8268
8269
void Simulator::VisitNEONByIndexedElement(const Instruction* instr) {
8270
NEONFormatDecoder nfd(instr);
8271
VectorFormat vform = nfd.GetVectorFormat();
8272
8273
SimVRegister& rd = ReadVRegister(instr->GetRd());
8274
SimVRegister& rn = ReadVRegister(instr->GetRn());
8275
8276
int rm_reg = instr->GetRm();
8277
int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
8278
8279
if ((vform == kFormat4H) || (vform == kFormat8H)) {
8280
rm_reg &= 0xf;
8281
index = (index << 1) | instr->GetNEONM();
8282
}
8283
8284
SimVRegister& rm = ReadVRegister(rm_reg);
8285
8286
switch (form_hash_) {
8287
case "mul_asimdelem_r"_h:
8288
mul(vform, rd, rn, rm, index);
8289
break;
8290
case "mla_asimdelem_r"_h:
8291
mla(vform, rd, rn, rm, index);
8292
break;
8293
case "mls_asimdelem_r"_h:
8294
mls(vform, rd, rn, rm, index);
8295
break;
8296
case "sqdmulh_asimdelem_r"_h:
8297
sqdmulh(vform, rd, rn, rm, index);
8298
break;
8299
case "sqrdmulh_asimdelem_r"_h:
8300
sqrdmulh(vform, rd, rn, rm, index);
8301
break;
8302
case "sqrdmlah_asimdelem_r"_h:
8303
sqrdmlah(vform, rd, rn, rm, index);
8304
break;
8305
case "sqrdmlsh_asimdelem_r"_h:
8306
sqrdmlsh(vform, rd, rn, rm, index);
8307
break;
8308
}
8309
}
8310
8311
8312
void Simulator::VisitNEONCopy(const Instruction* instr) {
8313
NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
8314
VectorFormat vf = nfd.GetVectorFormat();
8315
8316
SimVRegister& rd = ReadVRegister(instr->GetRd());
8317
SimVRegister& rn = ReadVRegister(instr->GetRn());
8318
int imm5 = instr->GetImmNEON5();
8319
int tz = CountTrailingZeros(imm5, 32);
8320
int reg_index = ExtractSignedBitfield32(31, tz + 1, imm5);
8321
8322
if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
8323
int imm4 = instr->GetImmNEON4();
8324
int rn_index = ExtractSignedBitfield32(31, tz, imm4);
8325
mov(kFormat16B, rd, rd); // Zero bits beyond the MSB of a Q register.
8326
ins_element(vf, rd, reg_index, rn, rn_index);
8327
} else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
8328
mov(kFormat16B, rd, rd); // Zero bits beyond the MSB of a Q register.
8329
ins_immediate(vf, rd, reg_index, ReadXRegister(instr->GetRn()));
8330
} else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
8331
uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
8332
value &= MaxUintFromFormat(vf);
8333
WriteXRegister(instr->GetRd(), value);
8334
} else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
8335
int64_t value = LogicVRegister(rn).Int(vf, reg_index);
8336
if (instr->GetNEONQ()) {
8337
WriteXRegister(instr->GetRd(), value);
8338
} else {
8339
WriteWRegister(instr->GetRd(), (int32_t)value);
8340
}
8341
} else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
8342
dup_element(vf, rd, rn, reg_index);
8343
} else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
8344
dup_immediate(vf, rd, ReadXRegister(instr->GetRn()));
8345
} else {
8346
VIXL_UNIMPLEMENTED();
8347
}
8348
}
8349
8350
8351
void Simulator::VisitNEONExtract(const Instruction* instr) {
8352
NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
8353
VectorFormat vf = nfd.GetVectorFormat();
8354
SimVRegister& rd = ReadVRegister(instr->GetRd());
8355
SimVRegister& rn = ReadVRegister(instr->GetRn());
8356
SimVRegister& rm = ReadVRegister(instr->GetRm());
8357
if (instr->Mask(NEONExtractMask) == NEON_EXT) {
8358
int index = instr->GetImmNEONExt();
8359
ext(vf, rd, rn, rm, index);
8360
} else {
8361
VIXL_UNIMPLEMENTED();
8362
}
8363
}
8364
8365
8366
void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
8367
AddrMode addr_mode) {
8368
NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
8369
VectorFormat vf = nfd.GetVectorFormat();
8370
8371
uint64_t addr_base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
8372
int reg_size = RegisterSizeInBytesFromFormat(vf);
8373
8374
int reg[4];
8375
uint64_t addr[4];
8376
for (int i = 0; i < 4; i++) {
8377
reg[i] = (instr->GetRt() + i) % kNumberOfVRegisters;
8378
addr[i] = addr_base + (i * reg_size);
8379
}
8380
int struct_parts = 1;
8381
int reg_count = 1;
8382
bool log_read = true;
8383
8384
// Bit 23 determines whether this is an offset or post-index addressing mode.
8385
// In offset mode, bits 20 to 16 should be zero; these bits encode the
8386
// register or immediate in post-index mode.
8387
if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
8388
VIXL_UNREACHABLE();
8389
}
8390
8391
// We use the PostIndex mask here, as it works in this case for both Offset
8392
// and PostIndex addressing.
8393
switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
8394
case NEON_LD1_4v:
8395
case NEON_LD1_4v_post:
8396
if (!ld1(vf, ReadVRegister(reg[3]), addr[3])) {
8397
return;
8398
}
8399
reg_count++;
8400
VIXL_FALLTHROUGH();
8401
case NEON_LD1_3v:
8402
case NEON_LD1_3v_post:
8403
if (!ld1(vf, ReadVRegister(reg[2]), addr[2])) {
8404
return;
8405
}
8406
reg_count++;
8407
VIXL_FALLTHROUGH();
8408
case NEON_LD1_2v:
8409
case NEON_LD1_2v_post:
8410
if (!ld1(vf, ReadVRegister(reg[1]), addr[1])) {
8411
return;
8412
}
8413
reg_count++;
8414
VIXL_FALLTHROUGH();
8415
case NEON_LD1_1v:
8416
case NEON_LD1_1v_post:
8417
if (!ld1(vf, ReadVRegister(reg[0]), addr[0])) {
8418
return;
8419
}
8420
break;
8421
case NEON_ST1_4v:
8422
case NEON_ST1_4v_post:
8423
if (!st1(vf, ReadVRegister(reg[3]), addr[3])) return;
8424
reg_count++;
8425
VIXL_FALLTHROUGH();
8426
case NEON_ST1_3v:
8427
case NEON_ST1_3v_post:
8428
if (!st1(vf, ReadVRegister(reg[2]), addr[2])) return;
8429
reg_count++;
8430
VIXL_FALLTHROUGH();
8431
case NEON_ST1_2v:
8432
case NEON_ST1_2v_post:
8433
if (!st1(vf, ReadVRegister(reg[1]), addr[1])) return;
8434
reg_count++;
8435
VIXL_FALLTHROUGH();
8436
case NEON_ST1_1v:
8437
case NEON_ST1_1v_post:
8438
if (!st1(vf, ReadVRegister(reg[0]), addr[0])) return;
8439
log_read = false;
8440
break;
8441
case NEON_LD2_post:
8442
case NEON_LD2:
8443
if (!ld2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0])) {
8444
return;
8445
}
8446
struct_parts = 2;
8447
reg_count = 2;
8448
break;
8449
case NEON_ST2:
8450
case NEON_ST2_post:
8451
if (!st2(vf, ReadVRegister(reg[0]), ReadVRegister(reg[1]), addr[0])) {
8452
return;
8453
}
8454
struct_parts = 2;
8455
reg_count = 2;
8456
log_read = false;
8457
break;
8458
case NEON_LD3_post:
8459
case NEON_LD3:
8460
if (!ld3(vf,
8461
ReadVRegister(reg[0]),
8462
ReadVRegister(reg[1]),
8463
ReadVRegister(reg[2]),
8464
addr[0])) {
8465
return;
8466
}
8467
struct_parts = 3;
8468
reg_count = 3;
8469
break;
8470
case NEON_ST3:
8471
case NEON_ST3_post:
8472
if (!st3(vf,
8473
ReadVRegister(reg[0]),
8474
ReadVRegister(reg[1]),
8475
ReadVRegister(reg[2]),
8476
addr[0])) {
8477
return;
8478
}
8479
struct_parts = 3;
8480
reg_count = 3;
8481
log_read = false;
8482
break;
8483
case NEON_ST4:
8484
case NEON_ST4_post:
8485
if (!st4(vf,
8486
ReadVRegister(reg[0]),
8487
ReadVRegister(reg[1]),
8488
ReadVRegister(reg[2]),
8489
ReadVRegister(reg[3]),
8490
addr[0])) {
8491
return;
8492
}
8493
struct_parts = 4;
8494
reg_count = 4;
8495
log_read = false;
8496
break;
8497
case NEON_LD4_post:
8498
case NEON_LD4:
8499
if (!ld4(vf,
8500
ReadVRegister(reg[0]),
8501
ReadVRegister(reg[1]),
8502
ReadVRegister(reg[2]),
8503
ReadVRegister(reg[3]),
8504
addr[0])) {
8505
return;
8506
}
8507
struct_parts = 4;
8508
reg_count = 4;
8509
break;
8510
default:
8511
VIXL_UNIMPLEMENTED();
8512
}
8513
8514
bool do_trace = log_read ? ShouldTraceVRegs() : ShouldTraceWrites();
8515
if (do_trace) {
8516
PrintRegisterFormat print_format =
8517
GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8518
const char* op;
8519
if (log_read) {
8520
op = "<-";
8521
} else {
8522
op = "->";
8523
// Stores don't represent a change to the source register's value, so only
8524
// print the relevant part of the value.
8525
print_format = GetPrintRegPartial(print_format);
8526
}
8527
8528
VIXL_ASSERT((struct_parts == reg_count) || (struct_parts == 1));
8529
for (int s = reg_count - struct_parts; s >= 0; s -= struct_parts) {
8530
uintptr_t address = addr_base + (s * RegisterSizeInBytesFromFormat(vf));
8531
PrintVStructAccess(reg[s], struct_parts, print_format, op, address);
8532
}
8533
}
8534
8535
if (addr_mode == PostIndex) {
8536
int rm = instr->GetRm();
8537
// The immediate post index addressing mode is indicated by rm = 31.
8538
// The immediate is implied by the number of vector registers used.
8539
addr_base += (rm == 31) ? (RegisterSizeInBytesFromFormat(vf) * reg_count)
8540
: ReadXRegister(rm);
8541
WriteXRegister(instr->GetRn(),
8542
addr_base,
8543
LogRegWrites,
8544
Reg31IsStackPointer);
8545
} else {
8546
VIXL_ASSERT(addr_mode == Offset);
8547
}
8548
}
8549
8550
8551
void Simulator::VisitNEONLoadStoreMultiStruct(const Instruction* instr) {
8552
NEONLoadStoreMultiStructHelper(instr, Offset);
8553
}
8554
8555
8556
void Simulator::VisitNEONLoadStoreMultiStructPostIndex(
8557
const Instruction* instr) {
8558
NEONLoadStoreMultiStructHelper(instr, PostIndex);
8559
}
8560
8561
8562
void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
8563
AddrMode addr_mode) {
8564
uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
8565
int rt = instr->GetRt();
8566
8567
// Bit 23 determines whether this is an offset or post-index addressing mode.
8568
// In offset mode, bits 20 to 16 should be zero; these bits encode the
8569
// register or immediate in post-index mode.
8570
if ((instr->ExtractBit(23) == 0) && (instr->ExtractBits(20, 16) != 0)) {
8571
VIXL_UNREACHABLE();
8572
}
8573
8574
// We use the PostIndex mask here, as it works in this case for both Offset
8575
// and PostIndex addressing.
8576
bool do_load = false;
8577
8578
bool replicating = false;
8579
8580
NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
8581
VectorFormat vf_t = nfd.GetVectorFormat();
8582
8583
VectorFormat vf = kFormat16B;
8584
switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
8585
case NEON_LD1_b:
8586
case NEON_LD1_b_post:
8587
case NEON_LD2_b:
8588
case NEON_LD2_b_post:
8589
case NEON_LD3_b:
8590
case NEON_LD3_b_post:
8591
case NEON_LD4_b:
8592
case NEON_LD4_b_post:
8593
do_load = true;
8594
VIXL_FALLTHROUGH();
8595
case NEON_ST1_b:
8596
case NEON_ST1_b_post:
8597
case NEON_ST2_b:
8598
case NEON_ST2_b_post:
8599
case NEON_ST3_b:
8600
case NEON_ST3_b_post:
8601
case NEON_ST4_b:
8602
case NEON_ST4_b_post:
8603
break;
8604
8605
case NEON_LD1_h:
8606
case NEON_LD1_h_post:
8607
case NEON_LD2_h:
8608
case NEON_LD2_h_post:
8609
case NEON_LD3_h:
8610
case NEON_LD3_h_post:
8611
case NEON_LD4_h:
8612
case NEON_LD4_h_post:
8613
do_load = true;
8614
VIXL_FALLTHROUGH();
8615
case NEON_ST1_h:
8616
case NEON_ST1_h_post:
8617
case NEON_ST2_h:
8618
case NEON_ST2_h_post:
8619
case NEON_ST3_h:
8620
case NEON_ST3_h_post:
8621
case NEON_ST4_h:
8622
case NEON_ST4_h_post:
8623
vf = kFormat8H;
8624
break;
8625
case NEON_LD1_s:
8626
case NEON_LD1_s_post:
8627
case NEON_LD2_s:
8628
case NEON_LD2_s_post:
8629
case NEON_LD3_s:
8630
case NEON_LD3_s_post:
8631
case NEON_LD4_s:
8632
case NEON_LD4_s_post:
8633
do_load = true;
8634
VIXL_FALLTHROUGH();
8635
case NEON_ST1_s:
8636
case NEON_ST1_s_post:
8637
case NEON_ST2_s:
8638
case NEON_ST2_s_post:
8639
case NEON_ST3_s:
8640
case NEON_ST3_s_post:
8641
case NEON_ST4_s:
8642
case NEON_ST4_s_post: {
8643
VIXL_STATIC_ASSERT((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d);
8644
VIXL_STATIC_ASSERT((NEON_LD1_s_post | (1 << NEONLSSize_offset)) ==
8645
NEON_LD1_d_post);
8646
VIXL_STATIC_ASSERT((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d);
8647
VIXL_STATIC_ASSERT((NEON_ST1_s_post | (1 << NEONLSSize_offset)) ==
8648
NEON_ST1_d_post);
8649
vf = ((instr->GetNEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
8650
break;
8651
}
8652
8653
case NEON_LD1R:
8654
case NEON_LD1R_post:
8655
case NEON_LD2R:
8656
case NEON_LD2R_post:
8657
case NEON_LD3R:
8658
case NEON_LD3R_post:
8659
case NEON_LD4R:
8660
case NEON_LD4R_post:
8661
vf = vf_t;
8662
do_load = true;
8663
replicating = true;
8664
break;
8665
8666
default:
8667
VIXL_UNIMPLEMENTED();
8668
}
8669
8670
int index_shift = LaneSizeInBytesLog2FromFormat(vf);
8671
int lane = instr->GetNEONLSIndex(index_shift);
8672
int reg_count = 0;
8673
int rt2 = (rt + 1) % kNumberOfVRegisters;
8674
int rt3 = (rt2 + 1) % kNumberOfVRegisters;
8675
int rt4 = (rt3 + 1) % kNumberOfVRegisters;
8676
switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
8677
case NEONLoadStoreSingle1:
8678
reg_count = 1;
8679
if (replicating) {
8680
VIXL_ASSERT(do_load);
8681
if (!ld1r(vf, ReadVRegister(rt), addr)) {
8682
return;
8683
}
8684
} else if (do_load) {
8685
if (!ld1(vf, ReadVRegister(rt), lane, addr)) {
8686
return;
8687
}
8688
} else {
8689
if (!st1(vf, ReadVRegister(rt), lane, addr)) return;
8690
}
8691
break;
8692
case NEONLoadStoreSingle2:
8693
reg_count = 2;
8694
if (replicating) {
8695
VIXL_ASSERT(do_load);
8696
if (!ld2r(vf, ReadVRegister(rt), ReadVRegister(rt2), addr)) {
8697
return;
8698
}
8699
} else if (do_load) {
8700
if (!ld2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr)) {
8701
return;
8702
}
8703
} else {
8704
if (!st2(vf, ReadVRegister(rt), ReadVRegister(rt2), lane, addr)) return;
8705
}
8706
break;
8707
case NEONLoadStoreSingle3:
8708
reg_count = 3;
8709
if (replicating) {
8710
VIXL_ASSERT(do_load);
8711
if (!ld3r(vf,
8712
ReadVRegister(rt),
8713
ReadVRegister(rt2),
8714
ReadVRegister(rt3),
8715
addr)) {
8716
return;
8717
}
8718
} else if (do_load) {
8719
if (!ld3(vf,
8720
ReadVRegister(rt),
8721
ReadVRegister(rt2),
8722
ReadVRegister(rt3),
8723
lane,
8724
addr)) {
8725
return;
8726
}
8727
} else {
8728
if (!st3(vf,
8729
ReadVRegister(rt),
8730
ReadVRegister(rt2),
8731
ReadVRegister(rt3),
8732
lane,
8733
addr)) {
8734
return;
8735
}
8736
}
8737
break;
8738
case NEONLoadStoreSingle4:
8739
reg_count = 4;
8740
if (replicating) {
8741
VIXL_ASSERT(do_load);
8742
if (!ld4r(vf,
8743
ReadVRegister(rt),
8744
ReadVRegister(rt2),
8745
ReadVRegister(rt3),
8746
ReadVRegister(rt4),
8747
addr)) {
8748
return;
8749
}
8750
} else if (do_load) {
8751
if (!ld4(vf,
8752
ReadVRegister(rt),
8753
ReadVRegister(rt2),
8754
ReadVRegister(rt3),
8755
ReadVRegister(rt4),
8756
lane,
8757
addr)) {
8758
return;
8759
}
8760
} else {
8761
if (!st4(vf,
8762
ReadVRegister(rt),
8763
ReadVRegister(rt2),
8764
ReadVRegister(rt3),
8765
ReadVRegister(rt4),
8766
lane,
8767
addr)) {
8768
return;
8769
}
8770
}
8771
break;
8772
default:
8773
VIXL_UNIMPLEMENTED();
8774
}
8775
8776
// Trace registers and/or memory writes.
8777
PrintRegisterFormat print_format =
8778
GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
8779
if (do_load) {
8780
if (ShouldTraceVRegs()) {
8781
if (replicating) {
8782
PrintVReplicatingStructAccess(rt, reg_count, print_format, "<-", addr);
8783
} else {
8784
PrintVSingleStructAccess(rt, reg_count, lane, print_format, "<-", addr);
8785
}
8786
}
8787
} else {
8788
if (ShouldTraceWrites()) {
8789
// Stores don't represent a change to the source register's value, so only
8790
// print the relevant part of the value.
8791
print_format = GetPrintRegPartial(print_format);
8792
PrintVSingleStructAccess(rt, reg_count, lane, print_format, "->", addr);
8793
}
8794
}
8795
8796
if (addr_mode == PostIndex) {
8797
int rm = instr->GetRm();
8798
int lane_size = LaneSizeInBytesFromFormat(vf);
8799
WriteXRegister(instr->GetRn(),
8800
addr + ((rm == 31) ? (reg_count * lane_size)
8801
: ReadXRegister(rm)),
8802
LogRegWrites,
8803
Reg31IsStackPointer);
8804
}
8805
}
8806
8807
8808
void Simulator::VisitNEONLoadStoreSingleStruct(const Instruction* instr) {
8809
NEONLoadStoreSingleStructHelper(instr, Offset);
8810
}
8811
8812
8813
void Simulator::VisitNEONLoadStoreSingleStructPostIndex(
8814
const Instruction* instr) {
8815
NEONLoadStoreSingleStructHelper(instr, PostIndex);
8816
}
8817
8818
8819
void Simulator::VisitNEONModifiedImmediate(const Instruction* instr) {
8820
SimVRegister& rd = ReadVRegister(instr->GetRd());
8821
int cmode = instr->GetNEONCmode();
8822
int cmode_3_1 = (cmode >> 1) & 7;
8823
int cmode_3 = (cmode >> 3) & 1;
8824
int cmode_2 = (cmode >> 2) & 1;
8825
int cmode_1 = (cmode >> 1) & 1;
8826
int cmode_0 = cmode & 1;
8827
int half_enc = instr->ExtractBit(11);
8828
int q = instr->GetNEONQ();
8829
int op_bit = instr->GetNEONModImmOp();
8830
uint64_t imm8 = instr->GetImmNEONabcdefgh();
8831
// Find the format and immediate value
8832
uint64_t imm = 0;
8833
VectorFormat vform = kFormatUndefined;
8834
switch (cmode_3_1) {
8835
case 0x0:
8836
case 0x1:
8837
case 0x2:
8838
case 0x3:
8839
vform = (q == 1) ? kFormat4S : kFormat2S;
8840
imm = imm8 << (8 * cmode_3_1);
8841
break;
8842
case 0x4:
8843
case 0x5:
8844
vform = (q == 1) ? kFormat8H : kFormat4H;
8845
imm = imm8 << (8 * cmode_1);
8846
break;
8847
case 0x6:
8848
vform = (q == 1) ? kFormat4S : kFormat2S;
8849
if (cmode_0 == 0) {
8850
imm = imm8 << 8 | 0x000000ff;
8851
} else {
8852
imm = imm8 << 16 | 0x0000ffff;
8853
}
8854
break;
8855
case 0x7:
8856
if (cmode_0 == 0 && op_bit == 0) {
8857
vform = q ? kFormat16B : kFormat8B;
8858
imm = imm8;
8859
} else if (cmode_0 == 0 && op_bit == 1) {
8860
vform = q ? kFormat2D : kFormat1D;
8861
imm = 0;
8862
for (int i = 0; i < 8; ++i) {
8863
if (imm8 & (1 << i)) {
8864
imm |= (UINT64_C(0xff) << (8 * i));
8865
}
8866
}
8867
} else { // cmode_0 == 1, cmode == 0xf.
8868
if (half_enc == 1) {
8869
vform = q ? kFormat8H : kFormat4H;
8870
imm = Float16ToRawbits(instr->GetImmNEONFP16());
8871
} else if (op_bit == 0) {
8872
vform = q ? kFormat4S : kFormat2S;
8873
imm = FloatToRawbits(instr->GetImmNEONFP32());
8874
} else if (q == 1) {
8875
vform = kFormat2D;
8876
imm = DoubleToRawbits(instr->GetImmNEONFP64());
8877
} else {
8878
VIXL_ASSERT((q == 0) && (op_bit == 1) && (cmode == 0xf));
8879
VisitUnallocated(instr);
8880
}
8881
}
8882
break;
8883
default:
8884
VIXL_UNREACHABLE();
8885
break;
8886
}
8887
8888
// Find the operation
8889
NEONModifiedImmediateOp op;
8890
if (cmode_3 == 0) {
8891
if (cmode_0 == 0) {
8892
op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8893
} else { // cmode<0> == '1'
8894
op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8895
}
8896
} else { // cmode<3> == '1'
8897
if (cmode_2 == 0) {
8898
if (cmode_0 == 0) {
8899
op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8900
} else { // cmode<0> == '1'
8901
op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
8902
}
8903
} else { // cmode<2> == '1'
8904
if (cmode_1 == 0) {
8905
op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
8906
} else { // cmode<1> == '1'
8907
if (cmode_0 == 0) {
8908
op = NEONModifiedImmediate_MOVI;
8909
} else { // cmode<0> == '1'
8910
op = NEONModifiedImmediate_MOVI;
8911
}
8912
}
8913
}
8914
}
8915
8916
// Call the logic function
8917
if (op == NEONModifiedImmediate_ORR) {
8918
orr(vform, rd, rd, imm);
8919
} else if (op == NEONModifiedImmediate_BIC) {
8920
bic(vform, rd, rd, imm);
8921
} else if (op == NEONModifiedImmediate_MOVI) {
8922
movi(vform, rd, imm);
8923
} else if (op == NEONModifiedImmediate_MVNI) {
8924
mvni(vform, rd, imm);
8925
} else {
8926
VisitUnimplemented(instr);
8927
}
8928
}
8929
8930
8931
void Simulator::VisitNEONScalar2RegMisc(const Instruction* instr) {
8932
NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
8933
VectorFormat vf = nfd.GetVectorFormat();
8934
8935
SimVRegister& rd = ReadVRegister(instr->GetRd());
8936
SimVRegister& rn = ReadVRegister(instr->GetRn());
8937
8938
if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
8939
// These instructions all use a two bit size field, except NOT and RBIT,
8940
// which use the field to encode the operation.
8941
switch (instr->Mask(NEONScalar2RegMiscMask)) {
8942
case NEON_CMEQ_zero_scalar:
8943
cmp(vf, rd, rn, 0, eq);
8944
break;
8945
case NEON_CMGE_zero_scalar:
8946
cmp(vf, rd, rn, 0, ge);
8947
break;
8948
case NEON_CMGT_zero_scalar:
8949
cmp(vf, rd, rn, 0, gt);
8950
break;
8951
case NEON_CMLT_zero_scalar:
8952
cmp(vf, rd, rn, 0, lt);
8953
break;
8954
case NEON_CMLE_zero_scalar:
8955
cmp(vf, rd, rn, 0, le);
8956
break;
8957
case NEON_ABS_scalar:
8958
abs(vf, rd, rn);
8959
break;
8960
case NEON_SQABS_scalar:
8961
abs(vf, rd, rn).SignedSaturate(vf);
8962
break;
8963
case NEON_NEG_scalar:
8964
neg(vf, rd, rn);
8965
break;
8966
case NEON_SQNEG_scalar:
8967
neg(vf, rd, rn).SignedSaturate(vf);
8968
break;
8969
case NEON_SUQADD_scalar:
8970
suqadd(vf, rd, rd, rn);
8971
break;
8972
case NEON_USQADD_scalar:
8973
usqadd(vf, rd, rd, rn);
8974
break;
8975
default:
8976
VIXL_UNIMPLEMENTED();
8977
break;
8978
}
8979
} else {
8980
VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
8981
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
8982
8983
// These instructions all use a one bit size field, except SQXTUN, SQXTN
8984
// and UQXTN, which use a two bit size field.
8985
switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
8986
case NEON_FRECPE_scalar:
8987
frecpe(fpf, rd, rn, fpcr_rounding);
8988
break;
8989
case NEON_FRECPX_scalar:
8990
frecpx(fpf, rd, rn);
8991
break;
8992
case NEON_FRSQRTE_scalar:
8993
frsqrte(fpf, rd, rn);
8994
break;
8995
case NEON_FCMGT_zero_scalar:
8996
fcmp_zero(fpf, rd, rn, gt);
8997
break;
8998
case NEON_FCMGE_zero_scalar:
8999
fcmp_zero(fpf, rd, rn, ge);
9000
break;
9001
case NEON_FCMEQ_zero_scalar:
9002
fcmp_zero(fpf, rd, rn, eq);
9003
break;
9004
case NEON_FCMLE_zero_scalar:
9005
fcmp_zero(fpf, rd, rn, le);
9006
break;
9007
case NEON_FCMLT_zero_scalar:
9008
fcmp_zero(fpf, rd, rn, lt);
9009
break;
9010
case NEON_SCVTF_scalar:
9011
scvtf(fpf, rd, rn, 0, fpcr_rounding);
9012
break;
9013
case NEON_UCVTF_scalar:
9014
ucvtf(fpf, rd, rn, 0, fpcr_rounding);
9015
break;
9016
case NEON_FCVTNS_scalar:
9017
fcvts(fpf, rd, rn, FPTieEven);
9018
break;
9019
case NEON_FCVTNU_scalar:
9020
fcvtu(fpf, rd, rn, FPTieEven);
9021
break;
9022
case NEON_FCVTPS_scalar:
9023
fcvts(fpf, rd, rn, FPPositiveInfinity);
9024
break;
9025
case NEON_FCVTPU_scalar:
9026
fcvtu(fpf, rd, rn, FPPositiveInfinity);
9027
break;
9028
case NEON_FCVTMS_scalar:
9029
fcvts(fpf, rd, rn, FPNegativeInfinity);
9030
break;
9031
case NEON_FCVTMU_scalar:
9032
fcvtu(fpf, rd, rn, FPNegativeInfinity);
9033
break;
9034
case NEON_FCVTZS_scalar:
9035
fcvts(fpf, rd, rn, FPZero);
9036
break;
9037
case NEON_FCVTZU_scalar:
9038
fcvtu(fpf, rd, rn, FPZero);
9039
break;
9040
case NEON_FCVTAS_scalar:
9041
fcvts(fpf, rd, rn, FPTieAway);
9042
break;
9043
case NEON_FCVTAU_scalar:
9044
fcvtu(fpf, rd, rn, FPTieAway);
9045
break;
9046
case NEON_FCVTXN_scalar:
9047
// Unlike all of the other FP instructions above, fcvtxn encodes dest
9048
// size S as size<0>=1. There's only one case, so we ignore the form.
9049
VIXL_ASSERT(instr->ExtractBit(22) == 1);
9050
fcvtxn(kFormatS, rd, rn);
9051
break;
9052
default:
9053
switch (instr->Mask(NEONScalar2RegMiscMask)) {
9054
case NEON_SQXTN_scalar:
9055
sqxtn(vf, rd, rn);
9056
break;
9057
case NEON_UQXTN_scalar:
9058
uqxtn(vf, rd, rn);
9059
break;
9060
case NEON_SQXTUN_scalar:
9061
sqxtun(vf, rd, rn);
9062
break;
9063
default:
9064
VIXL_UNIMPLEMENTED();
9065
}
9066
}
9067
}
9068
}
9069
9070
9071
void Simulator::VisitNEONScalar2RegMiscFP16(const Instruction* instr) {
9072
VectorFormat fpf = kFormatH;
9073
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9074
9075
SimVRegister& rd = ReadVRegister(instr->GetRd());
9076
SimVRegister& rn = ReadVRegister(instr->GetRn());
9077
9078
switch (instr->Mask(NEONScalar2RegMiscFP16Mask)) {
9079
case NEON_FRECPE_H_scalar:
9080
frecpe(fpf, rd, rn, fpcr_rounding);
9081
break;
9082
case NEON_FRECPX_H_scalar:
9083
frecpx(fpf, rd, rn);
9084
break;
9085
case NEON_FRSQRTE_H_scalar:
9086
frsqrte(fpf, rd, rn);
9087
break;
9088
case NEON_FCMGT_H_zero_scalar:
9089
fcmp_zero(fpf, rd, rn, gt);
9090
break;
9091
case NEON_FCMGE_H_zero_scalar:
9092
fcmp_zero(fpf, rd, rn, ge);
9093
break;
9094
case NEON_FCMEQ_H_zero_scalar:
9095
fcmp_zero(fpf, rd, rn, eq);
9096
break;
9097
case NEON_FCMLE_H_zero_scalar:
9098
fcmp_zero(fpf, rd, rn, le);
9099
break;
9100
case NEON_FCMLT_H_zero_scalar:
9101
fcmp_zero(fpf, rd, rn, lt);
9102
break;
9103
case NEON_SCVTF_H_scalar:
9104
scvtf(fpf, rd, rn, 0, fpcr_rounding);
9105
break;
9106
case NEON_UCVTF_H_scalar:
9107
ucvtf(fpf, rd, rn, 0, fpcr_rounding);
9108
break;
9109
case NEON_FCVTNS_H_scalar:
9110
fcvts(fpf, rd, rn, FPTieEven);
9111
break;
9112
case NEON_FCVTNU_H_scalar:
9113
fcvtu(fpf, rd, rn, FPTieEven);
9114
break;
9115
case NEON_FCVTPS_H_scalar:
9116
fcvts(fpf, rd, rn, FPPositiveInfinity);
9117
break;
9118
case NEON_FCVTPU_H_scalar:
9119
fcvtu(fpf, rd, rn, FPPositiveInfinity);
9120
break;
9121
case NEON_FCVTMS_H_scalar:
9122
fcvts(fpf, rd, rn, FPNegativeInfinity);
9123
break;
9124
case NEON_FCVTMU_H_scalar:
9125
fcvtu(fpf, rd, rn, FPNegativeInfinity);
9126
break;
9127
case NEON_FCVTZS_H_scalar:
9128
fcvts(fpf, rd, rn, FPZero);
9129
break;
9130
case NEON_FCVTZU_H_scalar:
9131
fcvtu(fpf, rd, rn, FPZero);
9132
break;
9133
case NEON_FCVTAS_H_scalar:
9134
fcvts(fpf, rd, rn, FPTieAway);
9135
break;
9136
case NEON_FCVTAU_H_scalar:
9137
fcvtu(fpf, rd, rn, FPTieAway);
9138
break;
9139
}
9140
}
9141
9142
9143
void Simulator::VisitNEONScalar3Diff(const Instruction* instr) {
9144
NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
9145
VectorFormat vf = nfd.GetVectorFormat();
9146
9147
SimVRegister& rd = ReadVRegister(instr->GetRd());
9148
SimVRegister& rn = ReadVRegister(instr->GetRn());
9149
SimVRegister& rm = ReadVRegister(instr->GetRm());
9150
switch (instr->Mask(NEONScalar3DiffMask)) {
9151
case NEON_SQDMLAL_scalar:
9152
sqdmlal(vf, rd, rn, rm);
9153
break;
9154
case NEON_SQDMLSL_scalar:
9155
sqdmlsl(vf, rd, rn, rm);
9156
break;
9157
case NEON_SQDMULL_scalar:
9158
sqdmull(vf, rd, rn, rm);
9159
break;
9160
default:
9161
VIXL_UNIMPLEMENTED();
9162
}
9163
}
9164
9165
9166
void Simulator::VisitNEONScalar3Same(const Instruction* instr) {
9167
NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
9168
VectorFormat vf = nfd.GetVectorFormat();
9169
9170
SimVRegister& rd = ReadVRegister(instr->GetRd());
9171
SimVRegister& rn = ReadVRegister(instr->GetRn());
9172
SimVRegister& rm = ReadVRegister(instr->GetRm());
9173
9174
if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
9175
vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
9176
switch (instr->Mask(NEONScalar3SameFPMask)) {
9177
case NEON_FMULX_scalar:
9178
fmulx(vf, rd, rn, rm);
9179
break;
9180
case NEON_FACGE_scalar:
9181
fabscmp(vf, rd, rn, rm, ge);
9182
break;
9183
case NEON_FACGT_scalar:
9184
fabscmp(vf, rd, rn, rm, gt);
9185
break;
9186
case NEON_FCMEQ_scalar:
9187
fcmp(vf, rd, rn, rm, eq);
9188
break;
9189
case NEON_FCMGE_scalar:
9190
fcmp(vf, rd, rn, rm, ge);
9191
break;
9192
case NEON_FCMGT_scalar:
9193
fcmp(vf, rd, rn, rm, gt);
9194
break;
9195
case NEON_FRECPS_scalar:
9196
frecps(vf, rd, rn, rm);
9197
break;
9198
case NEON_FRSQRTS_scalar:
9199
frsqrts(vf, rd, rn, rm);
9200
break;
9201
case NEON_FABD_scalar:
9202
fabd(vf, rd, rn, rm);
9203
break;
9204
default:
9205
VIXL_UNIMPLEMENTED();
9206
}
9207
} else {
9208
switch (instr->Mask(NEONScalar3SameMask)) {
9209
case NEON_ADD_scalar:
9210
add(vf, rd, rn, rm);
9211
break;
9212
case NEON_SUB_scalar:
9213
sub(vf, rd, rn, rm);
9214
break;
9215
case NEON_CMEQ_scalar:
9216
cmp(vf, rd, rn, rm, eq);
9217
break;
9218
case NEON_CMGE_scalar:
9219
cmp(vf, rd, rn, rm, ge);
9220
break;
9221
case NEON_CMGT_scalar:
9222
cmp(vf, rd, rn, rm, gt);
9223
break;
9224
case NEON_CMHI_scalar:
9225
cmp(vf, rd, rn, rm, hi);
9226
break;
9227
case NEON_CMHS_scalar:
9228
cmp(vf, rd, rn, rm, hs);
9229
break;
9230
case NEON_CMTST_scalar:
9231
cmptst(vf, rd, rn, rm);
9232
break;
9233
case NEON_USHL_scalar:
9234
ushl(vf, rd, rn, rm);
9235
break;
9236
case NEON_SSHL_scalar:
9237
sshl(vf, rd, rn, rm);
9238
break;
9239
case NEON_SQDMULH_scalar:
9240
sqdmulh(vf, rd, rn, rm);
9241
break;
9242
case NEON_SQRDMULH_scalar:
9243
sqrdmulh(vf, rd, rn, rm);
9244
break;
9245
case NEON_UQADD_scalar:
9246
add(vf, rd, rn, rm).UnsignedSaturate(vf);
9247
break;
9248
case NEON_SQADD_scalar:
9249
add(vf, rd, rn, rm).SignedSaturate(vf);
9250
break;
9251
case NEON_UQSUB_scalar:
9252
sub(vf, rd, rn, rm).UnsignedSaturate(vf);
9253
break;
9254
case NEON_SQSUB_scalar:
9255
sub(vf, rd, rn, rm).SignedSaturate(vf);
9256
break;
9257
case NEON_UQSHL_scalar:
9258
ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
9259
break;
9260
case NEON_SQSHL_scalar:
9261
sshl(vf, rd, rn, rm).SignedSaturate(vf);
9262
break;
9263
case NEON_URSHL_scalar:
9264
ushl(vf, rd, rn, rm).Round(vf);
9265
break;
9266
case NEON_SRSHL_scalar:
9267
sshl(vf, rd, rn, rm).Round(vf);
9268
break;
9269
case NEON_UQRSHL_scalar:
9270
ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
9271
break;
9272
case NEON_SQRSHL_scalar:
9273
sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
9274
break;
9275
default:
9276
VIXL_UNIMPLEMENTED();
9277
}
9278
}
9279
}
9280
9281
void Simulator::VisitNEONScalar3SameFP16(const Instruction* instr) {
9282
SimVRegister& rd = ReadVRegister(instr->GetRd());
9283
SimVRegister& rn = ReadVRegister(instr->GetRn());
9284
SimVRegister& rm = ReadVRegister(instr->GetRm());
9285
9286
switch (instr->Mask(NEONScalar3SameFP16Mask)) {
9287
case NEON_FABD_H_scalar:
9288
fabd(kFormatH, rd, rn, rm);
9289
break;
9290
case NEON_FMULX_H_scalar:
9291
fmulx(kFormatH, rd, rn, rm);
9292
break;
9293
case NEON_FCMEQ_H_scalar:
9294
fcmp(kFormatH, rd, rn, rm, eq);
9295
break;
9296
case NEON_FCMGE_H_scalar:
9297
fcmp(kFormatH, rd, rn, rm, ge);
9298
break;
9299
case NEON_FCMGT_H_scalar:
9300
fcmp(kFormatH, rd, rn, rm, gt);
9301
break;
9302
case NEON_FACGE_H_scalar:
9303
fabscmp(kFormatH, rd, rn, rm, ge);
9304
break;
9305
case NEON_FACGT_H_scalar:
9306
fabscmp(kFormatH, rd, rn, rm, gt);
9307
break;
9308
case NEON_FRECPS_H_scalar:
9309
frecps(kFormatH, rd, rn, rm);
9310
break;
9311
case NEON_FRSQRTS_H_scalar:
9312
frsqrts(kFormatH, rd, rn, rm);
9313
break;
9314
default:
9315
VIXL_UNREACHABLE();
9316
}
9317
}
9318
9319
9320
void Simulator::VisitNEONScalar3SameExtra(const Instruction* instr) {
9321
NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
9322
VectorFormat vf = nfd.GetVectorFormat();
9323
9324
SimVRegister& rd = ReadVRegister(instr->GetRd());
9325
SimVRegister& rn = ReadVRegister(instr->GetRn());
9326
SimVRegister& rm = ReadVRegister(instr->GetRm());
9327
9328
switch (instr->Mask(NEONScalar3SameExtraMask)) {
9329
case NEON_SQRDMLAH_scalar:
9330
sqrdmlah(vf, rd, rn, rm);
9331
break;
9332
case NEON_SQRDMLSH_scalar:
9333
sqrdmlsh(vf, rd, rn, rm);
9334
break;
9335
default:
9336
VIXL_UNIMPLEMENTED();
9337
}
9338
}
9339
9340
void Simulator::VisitNEONScalarByIndexedElement(const Instruction* instr) {
9341
NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
9342
VectorFormat vf = nfd.GetVectorFormat();
9343
VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
9344
9345
SimVRegister& rd = ReadVRegister(instr->GetRd());
9346
SimVRegister& rn = ReadVRegister(instr->GetRn());
9347
ByElementOp Op = NULL;
9348
9349
int rm_reg = instr->GetRm();
9350
int index = (instr->GetNEONH() << 1) | instr->GetNEONL();
9351
if (instr->GetNEONSize() == 1) {
9352
rm_reg &= 0xf;
9353
index = (index << 1) | instr->GetNEONM();
9354
}
9355
9356
switch (instr->Mask(NEONScalarByIndexedElementMask)) {
9357
case NEON_SQDMULL_byelement_scalar:
9358
Op = &Simulator::sqdmull;
9359
break;
9360
case NEON_SQDMLAL_byelement_scalar:
9361
Op = &Simulator::sqdmlal;
9362
break;
9363
case NEON_SQDMLSL_byelement_scalar:
9364
Op = &Simulator::sqdmlsl;
9365
break;
9366
case NEON_SQDMULH_byelement_scalar:
9367
Op = &Simulator::sqdmulh;
9368
vf = vf_r;
9369
break;
9370
case NEON_SQRDMULH_byelement_scalar:
9371
Op = &Simulator::sqrdmulh;
9372
vf = vf_r;
9373
break;
9374
case NEON_SQRDMLAH_byelement_scalar:
9375
Op = &Simulator::sqrdmlah;
9376
vf = vf_r;
9377
break;
9378
case NEON_SQRDMLSH_byelement_scalar:
9379
Op = &Simulator::sqrdmlsh;
9380
vf = vf_r;
9381
break;
9382
default:
9383
vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
9384
index = instr->GetNEONH();
9385
if (instr->GetFPType() == 0) {
9386
index = (index << 2) | (instr->GetNEONL() << 1) | instr->GetNEONM();
9387
rm_reg &= 0xf;
9388
vf = kFormatH;
9389
} else if ((instr->GetFPType() & 1) == 0) {
9390
index = (index << 1) | instr->GetNEONL();
9391
}
9392
switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
9393
case NEON_FMUL_H_byelement_scalar:
9394
case NEON_FMUL_byelement_scalar:
9395
Op = &Simulator::fmul;
9396
break;
9397
case NEON_FMLA_H_byelement_scalar:
9398
case NEON_FMLA_byelement_scalar:
9399
Op = &Simulator::fmla;
9400
break;
9401
case NEON_FMLS_H_byelement_scalar:
9402
case NEON_FMLS_byelement_scalar:
9403
Op = &Simulator::fmls;
9404
break;
9405
case NEON_FMULX_H_byelement_scalar:
9406
case NEON_FMULX_byelement_scalar:
9407
Op = &Simulator::fmulx;
9408
break;
9409
default:
9410
VIXL_UNIMPLEMENTED();
9411
}
9412
}
9413
9414
(this->*Op)(vf, rd, rn, ReadVRegister(rm_reg), index);
9415
}
9416
9417
9418
void Simulator::VisitNEONScalarCopy(const Instruction* instr) {
9419
NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
9420
VectorFormat vf = nfd.GetVectorFormat();
9421
9422
SimVRegister& rd = ReadVRegister(instr->GetRd());
9423
SimVRegister& rn = ReadVRegister(instr->GetRn());
9424
9425
if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
9426
int imm5 = instr->GetImmNEON5();
9427
int tz = CountTrailingZeros(imm5, 32);
9428
int rn_index = ExtractSignedBitfield32(31, tz + 1, imm5);
9429
dup_element(vf, rd, rn, rn_index);
9430
} else {
9431
VIXL_UNIMPLEMENTED();
9432
}
9433
}
9434
9435
9436
void Simulator::VisitNEONScalarPairwise(const Instruction* instr) {
9437
NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarPairwiseFormatMap());
9438
VectorFormat vf = nfd.GetVectorFormat();
9439
9440
SimVRegister& rd = ReadVRegister(instr->GetRd());
9441
SimVRegister& rn = ReadVRegister(instr->GetRn());
9442
switch (instr->Mask(NEONScalarPairwiseMask)) {
9443
case NEON_ADDP_scalar: {
9444
// All pairwise operations except ADDP use bit U to differentiate FP16
9445
// from FP32/FP64 variations.
9446
NEONFormatDecoder nfd_addp(instr, NEONFormatDecoder::FPScalarFormatMap());
9447
addp(nfd_addp.GetVectorFormat(), rd, rn);
9448
break;
9449
}
9450
case NEON_FADDP_h_scalar:
9451
case NEON_FADDP_scalar:
9452
faddp(vf, rd, rn);
9453
break;
9454
case NEON_FMAXP_h_scalar:
9455
case NEON_FMAXP_scalar:
9456
fmaxp(vf, rd, rn);
9457
break;
9458
case NEON_FMAXNMP_h_scalar:
9459
case NEON_FMAXNMP_scalar:
9460
fmaxnmp(vf, rd, rn);
9461
break;
9462
case NEON_FMINP_h_scalar:
9463
case NEON_FMINP_scalar:
9464
fminp(vf, rd, rn);
9465
break;
9466
case NEON_FMINNMP_h_scalar:
9467
case NEON_FMINNMP_scalar:
9468
fminnmp(vf, rd, rn);
9469
break;
9470
default:
9471
VIXL_UNIMPLEMENTED();
9472
}
9473
}
9474
9475
9476
void Simulator::VisitNEONScalarShiftImmediate(const Instruction* instr) {
9477
SimVRegister& rd = ReadVRegister(instr->GetRd());
9478
SimVRegister& rn = ReadVRegister(instr->GetRn());
9479
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9480
9481
static const NEONFormatMap map = {{22, 21, 20, 19},
9482
{NF_UNDEF,
9483
NF_B,
9484
NF_H,
9485
NF_H,
9486
NF_S,
9487
NF_S,
9488
NF_S,
9489
NF_S,
9490
NF_D,
9491
NF_D,
9492
NF_D,
9493
NF_D,
9494
NF_D,
9495
NF_D,
9496
NF_D,
9497
NF_D}};
9498
NEONFormatDecoder nfd(instr, &map);
9499
VectorFormat vf = nfd.GetVectorFormat();
9500
9501
int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
9502
int immh_immb = instr->GetImmNEONImmhImmb();
9503
int right_shift = (16 << highest_set_bit) - immh_immb;
9504
int left_shift = immh_immb - (8 << highest_set_bit);
9505
switch (instr->Mask(NEONScalarShiftImmediateMask)) {
9506
case NEON_SHL_scalar:
9507
shl(vf, rd, rn, left_shift);
9508
break;
9509
case NEON_SLI_scalar:
9510
sli(vf, rd, rn, left_shift);
9511
break;
9512
case NEON_SQSHL_imm_scalar:
9513
sqshl(vf, rd, rn, left_shift);
9514
break;
9515
case NEON_UQSHL_imm_scalar:
9516
uqshl(vf, rd, rn, left_shift);
9517
break;
9518
case NEON_SQSHLU_scalar:
9519
sqshlu(vf, rd, rn, left_shift);
9520
break;
9521
case NEON_SRI_scalar:
9522
sri(vf, rd, rn, right_shift);
9523
break;
9524
case NEON_SSHR_scalar:
9525
sshr(vf, rd, rn, right_shift);
9526
break;
9527
case NEON_USHR_scalar:
9528
ushr(vf, rd, rn, right_shift);
9529
break;
9530
case NEON_SRSHR_scalar:
9531
sshr(vf, rd, rn, right_shift).Round(vf);
9532
break;
9533
case NEON_URSHR_scalar:
9534
ushr(vf, rd, rn, right_shift).Round(vf);
9535
break;
9536
case NEON_SSRA_scalar:
9537
ssra(vf, rd, rn, right_shift);
9538
break;
9539
case NEON_USRA_scalar:
9540
usra(vf, rd, rn, right_shift);
9541
break;
9542
case NEON_SRSRA_scalar:
9543
srsra(vf, rd, rn, right_shift);
9544
break;
9545
case NEON_URSRA_scalar:
9546
ursra(vf, rd, rn, right_shift);
9547
break;
9548
case NEON_UQSHRN_scalar:
9549
uqshrn(vf, rd, rn, right_shift);
9550
break;
9551
case NEON_UQRSHRN_scalar:
9552
uqrshrn(vf, rd, rn, right_shift);
9553
break;
9554
case NEON_SQSHRN_scalar:
9555
sqshrn(vf, rd, rn, right_shift);
9556
break;
9557
case NEON_SQRSHRN_scalar:
9558
sqrshrn(vf, rd, rn, right_shift);
9559
break;
9560
case NEON_SQSHRUN_scalar:
9561
sqshrun(vf, rd, rn, right_shift);
9562
break;
9563
case NEON_SQRSHRUN_scalar:
9564
sqrshrun(vf, rd, rn, right_shift);
9565
break;
9566
case NEON_FCVTZS_imm_scalar:
9567
fcvts(vf, rd, rn, FPZero, right_shift);
9568
break;
9569
case NEON_FCVTZU_imm_scalar:
9570
fcvtu(vf, rd, rn, FPZero, right_shift);
9571
break;
9572
case NEON_SCVTF_imm_scalar:
9573
scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9574
break;
9575
case NEON_UCVTF_imm_scalar:
9576
ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9577
break;
9578
default:
9579
VIXL_UNIMPLEMENTED();
9580
}
9581
}
9582
9583
9584
void Simulator::VisitNEONShiftImmediate(const Instruction* instr) {
9585
SimVRegister& rd = ReadVRegister(instr->GetRd());
9586
SimVRegister& rn = ReadVRegister(instr->GetRn());
9587
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
9588
9589
// 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
9590
// 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
9591
static const NEONFormatMap map = {{22, 21, 20, 19, 30},
9592
{NF_UNDEF, NF_UNDEF, NF_8B, NF_16B,
9593
NF_4H, NF_8H, NF_4H, NF_8H,
9594
NF_2S, NF_4S, NF_2S, NF_4S,
9595
NF_2S, NF_4S, NF_2S, NF_4S,
9596
NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9597
NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9598
NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
9599
NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
9600
NEONFormatDecoder nfd(instr, &map);
9601
VectorFormat vf = nfd.GetVectorFormat();
9602
9603
// 0001->8H, 001x->4S, 01xx->2D, all others undefined.
9604
static const NEONFormatMap map_l =
9605
{{22, 21, 20, 19},
9606
{NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
9607
VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
9608
9609
int highest_set_bit = HighestSetBitPosition(instr->GetImmNEONImmh());
9610
int immh_immb = instr->GetImmNEONImmhImmb();
9611
int right_shift = (16 << highest_set_bit) - immh_immb;
9612
int left_shift = immh_immb - (8 << highest_set_bit);
9613
9614
switch (instr->Mask(NEONShiftImmediateMask)) {
9615
case NEON_SHL:
9616
shl(vf, rd, rn, left_shift);
9617
break;
9618
case NEON_SLI:
9619
sli(vf, rd, rn, left_shift);
9620
break;
9621
case NEON_SQSHLU:
9622
sqshlu(vf, rd, rn, left_shift);
9623
break;
9624
case NEON_SRI:
9625
sri(vf, rd, rn, right_shift);
9626
break;
9627
case NEON_SSHR:
9628
sshr(vf, rd, rn, right_shift);
9629
break;
9630
case NEON_USHR:
9631
ushr(vf, rd, rn, right_shift);
9632
break;
9633
case NEON_SRSHR:
9634
sshr(vf, rd, rn, right_shift).Round(vf);
9635
break;
9636
case NEON_URSHR:
9637
ushr(vf, rd, rn, right_shift).Round(vf);
9638
break;
9639
case NEON_SSRA:
9640
ssra(vf, rd, rn, right_shift);
9641
break;
9642
case NEON_USRA:
9643
usra(vf, rd, rn, right_shift);
9644
break;
9645
case NEON_SRSRA:
9646
srsra(vf, rd, rn, right_shift);
9647
break;
9648
case NEON_URSRA:
9649
ursra(vf, rd, rn, right_shift);
9650
break;
9651
case NEON_SQSHL_imm:
9652
sqshl(vf, rd, rn, left_shift);
9653
break;
9654
case NEON_UQSHL_imm:
9655
uqshl(vf, rd, rn, left_shift);
9656
break;
9657
case NEON_SCVTF_imm:
9658
scvtf(vf, rd, rn, right_shift, fpcr_rounding);
9659
break;
9660
case NEON_UCVTF_imm:
9661
ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
9662
break;
9663
case NEON_FCVTZS_imm:
9664
fcvts(vf, rd, rn, FPZero, right_shift);
9665
break;
9666
case NEON_FCVTZU_imm:
9667
fcvtu(vf, rd, rn, FPZero, right_shift);
9668
break;
9669
case NEON_SSHLL:
9670
vf = vf_l;
9671
if (instr->Mask(NEON_Q)) {
9672
sshll2(vf, rd, rn, left_shift);
9673
} else {
9674
sshll(vf, rd, rn, left_shift);
9675
}
9676
break;
9677
case NEON_USHLL:
9678
vf = vf_l;
9679
if (instr->Mask(NEON_Q)) {
9680
ushll2(vf, rd, rn, left_shift);
9681
} else {
9682
ushll(vf, rd, rn, left_shift);
9683
}
9684
break;
9685
case NEON_SHRN:
9686
if (instr->Mask(NEON_Q)) {
9687
shrn2(vf, rd, rn, right_shift);
9688
} else {
9689
shrn(vf, rd, rn, right_shift);
9690
}
9691
break;
9692
case NEON_RSHRN:
9693
if (instr->Mask(NEON_Q)) {
9694
rshrn2(vf, rd, rn, right_shift);
9695
} else {
9696
rshrn(vf, rd, rn, right_shift);
9697
}
9698
break;
9699
case NEON_UQSHRN:
9700
if (instr->Mask(NEON_Q)) {
9701
uqshrn2(vf, rd, rn, right_shift);
9702
} else {
9703
uqshrn(vf, rd, rn, right_shift);
9704
}
9705
break;
9706
case NEON_UQRSHRN:
9707
if (instr->Mask(NEON_Q)) {
9708
uqrshrn2(vf, rd, rn, right_shift);
9709
} else {
9710
uqrshrn(vf, rd, rn, right_shift);
9711
}
9712
break;
9713
case NEON_SQSHRN:
9714
if (instr->Mask(NEON_Q)) {
9715
sqshrn2(vf, rd, rn, right_shift);
9716
} else {
9717
sqshrn(vf, rd, rn, right_shift);
9718
}
9719
break;
9720
case NEON_SQRSHRN:
9721
if (instr->Mask(NEON_Q)) {
9722
sqrshrn2(vf, rd, rn, right_shift);
9723
} else {
9724
sqrshrn(vf, rd, rn, right_shift);
9725
}
9726
break;
9727
case NEON_SQSHRUN:
9728
if (instr->Mask(NEON_Q)) {
9729
sqshrun2(vf, rd, rn, right_shift);
9730
} else {
9731
sqshrun(vf, rd, rn, right_shift);
9732
}
9733
break;
9734
case NEON_SQRSHRUN:
9735
if (instr->Mask(NEON_Q)) {
9736
sqrshrun2(vf, rd, rn, right_shift);
9737
} else {
9738
sqrshrun(vf, rd, rn, right_shift);
9739
}
9740
break;
9741
default:
9742
VIXL_UNIMPLEMENTED();
9743
}
9744
}
9745
9746
9747
void Simulator::VisitNEONTable(const Instruction* instr) {
9748
NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
9749
VectorFormat vf = nfd.GetVectorFormat();
9750
9751
SimVRegister& rd = ReadVRegister(instr->GetRd());
9752
SimVRegister& rn = ReadVRegister(instr->GetRn());
9753
SimVRegister& rn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfVRegisters);
9754
SimVRegister& rn3 = ReadVRegister((instr->GetRn() + 2) % kNumberOfVRegisters);
9755
SimVRegister& rn4 = ReadVRegister((instr->GetRn() + 3) % kNumberOfVRegisters);
9756
SimVRegister& rm = ReadVRegister(instr->GetRm());
9757
9758
switch (instr->Mask(NEONTableMask)) {
9759
case NEON_TBL_1v:
9760
tbl(vf, rd, rn, rm);
9761
break;
9762
case NEON_TBL_2v:
9763
tbl(vf, rd, rn, rn2, rm);
9764
break;
9765
case NEON_TBL_3v:
9766
tbl(vf, rd, rn, rn2, rn3, rm);
9767
break;
9768
case NEON_TBL_4v:
9769
tbl(vf, rd, rn, rn2, rn3, rn4, rm);
9770
break;
9771
case NEON_TBX_1v:
9772
tbx(vf, rd, rn, rm);
9773
break;
9774
case NEON_TBX_2v:
9775
tbx(vf, rd, rn, rn2, rm);
9776
break;
9777
case NEON_TBX_3v:
9778
tbx(vf, rd, rn, rn2, rn3, rm);
9779
break;
9780
case NEON_TBX_4v:
9781
tbx(vf, rd, rn, rn2, rn3, rn4, rm);
9782
break;
9783
default:
9784
VIXL_UNIMPLEMENTED();
9785
}
9786
}
9787
9788
9789
void Simulator::VisitNEONPerm(const Instruction* instr) {
9790
NEONFormatDecoder nfd(instr);
9791
VectorFormat vf = nfd.GetVectorFormat();
9792
9793
SimVRegister& rd = ReadVRegister(instr->GetRd());
9794
SimVRegister& rn = ReadVRegister(instr->GetRn());
9795
SimVRegister& rm = ReadVRegister(instr->GetRm());
9796
9797
switch (instr->Mask(NEONPermMask)) {
9798
case NEON_TRN1:
9799
trn1(vf, rd, rn, rm);
9800
break;
9801
case NEON_TRN2:
9802
trn2(vf, rd, rn, rm);
9803
break;
9804
case NEON_UZP1:
9805
uzp1(vf, rd, rn, rm);
9806
break;
9807
case NEON_UZP2:
9808
uzp2(vf, rd, rn, rm);
9809
break;
9810
case NEON_ZIP1:
9811
zip1(vf, rd, rn, rm);
9812
break;
9813
case NEON_ZIP2:
9814
zip2(vf, rd, rn, rm);
9815
break;
9816
default:
9817
VIXL_UNIMPLEMENTED();
9818
}
9819
}
9820
9821
void Simulator::VisitSVEAddressGeneration(const Instruction* instr) {
9822
SimVRegister& zd = ReadVRegister(instr->GetRd());
9823
SimVRegister& zn = ReadVRegister(instr->GetRn());
9824
SimVRegister& zm = ReadVRegister(instr->GetRm());
9825
SimVRegister temp;
9826
9827
VectorFormat vform = kFormatVnD;
9828
mov(vform, temp, zm);
9829
9830
switch (instr->Mask(SVEAddressGenerationMask)) {
9831
case ADR_z_az_d_s32_scaled:
9832
sxt(vform, temp, temp, kSRegSize);
9833
break;
9834
case ADR_z_az_d_u32_scaled:
9835
uxt(vform, temp, temp, kSRegSize);
9836
break;
9837
case ADR_z_az_s_same_scaled:
9838
vform = kFormatVnS;
9839
break;
9840
case ADR_z_az_d_same_scaled:
9841
// Nothing to do.
9842
break;
9843
default:
9844
VIXL_UNIMPLEMENTED();
9845
break;
9846
}
9847
9848
int shift_amount = instr->ExtractBits(11, 10);
9849
shl(vform, temp, temp, shift_amount);
9850
add(vform, zd, zn, temp);
9851
}
9852
9853
void Simulator::VisitSVEBitwiseLogicalWithImm_Unpredicated(
9854
const Instruction* instr) {
9855
Instr op = instr->Mask(SVEBitwiseLogicalWithImm_UnpredicatedMask);
9856
switch (op) {
9857
case AND_z_zi:
9858
case EOR_z_zi:
9859
case ORR_z_zi: {
9860
int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9861
uint64_t imm = instr->GetSVEImmLogical();
9862
// Valid immediate is a non-zero bits
9863
VIXL_ASSERT(imm != 0);
9864
SVEBitwiseImmHelper(static_cast<SVEBitwiseLogicalWithImm_UnpredicatedOp>(
9865
op),
9866
SVEFormatFromLaneSizeInBytesLog2(lane_size),
9867
ReadVRegister(instr->GetRd()),
9868
imm);
9869
break;
9870
}
9871
default:
9872
VIXL_UNIMPLEMENTED();
9873
break;
9874
}
9875
}
9876
9877
void Simulator::VisitSVEBroadcastBitmaskImm(const Instruction* instr) {
9878
switch (instr->Mask(SVEBroadcastBitmaskImmMask)) {
9879
case DUPM_z_i: {
9880
/* DUPM uses the same lane size and immediate encoding as bitwise logical
9881
* immediate instructions. */
9882
int lane_size = instr->GetSVEBitwiseImmLaneSizeInBytesLog2();
9883
uint64_t imm = instr->GetSVEImmLogical();
9884
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9885
dup_immediate(vform, ReadVRegister(instr->GetRd()), imm);
9886
break;
9887
}
9888
default:
9889
VIXL_UNIMPLEMENTED();
9890
break;
9891
}
9892
}
9893
9894
void Simulator::VisitSVEBitwiseLogicalUnpredicated(const Instruction* instr) {
9895
SimVRegister& zd = ReadVRegister(instr->GetRd());
9896
SimVRegister& zn = ReadVRegister(instr->GetRn());
9897
SimVRegister& zm = ReadVRegister(instr->GetRm());
9898
Instr op = instr->Mask(SVEBitwiseLogicalUnpredicatedMask);
9899
9900
LogicalOp logical_op = LogicalOpMask;
9901
switch (op) {
9902
case AND_z_zz:
9903
logical_op = AND;
9904
break;
9905
case BIC_z_zz:
9906
logical_op = BIC;
9907
break;
9908
case EOR_z_zz:
9909
logical_op = EOR;
9910
break;
9911
case ORR_z_zz:
9912
logical_op = ORR;
9913
break;
9914
default:
9915
VIXL_UNIMPLEMENTED();
9916
break;
9917
}
9918
// Lane size of registers is irrelevant to the bitwise operations, so perform
9919
// the operation on D-sized lanes.
9920
SVEBitwiseLogicalUnpredicatedHelper(logical_op, kFormatVnD, zd, zn, zm);
9921
}
9922
9923
void Simulator::VisitSVEBitwiseShiftByImm_Predicated(const Instruction* instr) {
9924
SimVRegister& zdn = ReadVRegister(instr->GetRd());
9925
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9926
9927
SimVRegister scratch;
9928
SimVRegister result;
9929
9930
bool for_division = false;
9931
Shift shift_op = NO_SHIFT;
9932
switch (instr->Mask(SVEBitwiseShiftByImm_PredicatedMask)) {
9933
case ASRD_z_p_zi:
9934
shift_op = ASR;
9935
for_division = true;
9936
break;
9937
case ASR_z_p_zi:
9938
shift_op = ASR;
9939
break;
9940
case LSL_z_p_zi:
9941
shift_op = LSL;
9942
break;
9943
case LSR_z_p_zi:
9944
shift_op = LSR;
9945
break;
9946
default:
9947
VIXL_UNIMPLEMENTED();
9948
break;
9949
}
9950
9951
std::pair<int, int> shift_and_lane_size =
9952
instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ true);
9953
unsigned lane_size = shift_and_lane_size.second;
9954
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
9955
int shift_dist = shift_and_lane_size.first;
9956
9957
if ((shift_op == ASR) && for_division) {
9958
asrd(vform, result, zdn, shift_dist);
9959
} else {
9960
if (shift_op == LSL) {
9961
// Shift distance is computed differently for LSL. Convert the result.
9962
shift_dist = (8 << lane_size) - shift_dist;
9963
}
9964
dup_immediate(vform, scratch, shift_dist);
9965
SVEBitwiseShiftHelper(shift_op, vform, result, zdn, scratch, false);
9966
}
9967
mov_merging(vform, zdn, pg, result);
9968
}
9969
9970
void Simulator::VisitSVEBitwiseShiftByVector_Predicated(
9971
const Instruction* instr) {
9972
VectorFormat vform = instr->GetSVEVectorFormat();
9973
SimVRegister& zdn = ReadVRegister(instr->GetRd());
9974
SimVRegister& zm = ReadVRegister(instr->GetRn());
9975
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
9976
SimVRegister result;
9977
9978
// SVE uses the whole (saturated) lane for the shift amount.
9979
bool shift_in_ls_byte = false;
9980
9981
switch (form_hash_) {
9982
case "asrr_z_p_zz"_h:
9983
sshr(vform, result, zm, zdn);
9984
break;
9985
case "asr_z_p_zz"_h:
9986
sshr(vform, result, zdn, zm);
9987
break;
9988
case "lslr_z_p_zz"_h:
9989
sshl(vform, result, zm, zdn, shift_in_ls_byte);
9990
break;
9991
case "lsl_z_p_zz"_h:
9992
sshl(vform, result, zdn, zm, shift_in_ls_byte);
9993
break;
9994
case "lsrr_z_p_zz"_h:
9995
ushr(vform, result, zm, zdn);
9996
break;
9997
case "lsr_z_p_zz"_h:
9998
ushr(vform, result, zdn, zm);
9999
break;
10000
case "sqrshl_z_p_zz"_h:
10001
sshl(vform, result, zdn, zm, shift_in_ls_byte)
10002
.Round(vform)
10003
.SignedSaturate(vform);
10004
break;
10005
case "sqrshlr_z_p_zz"_h:
10006
sshl(vform, result, zm, zdn, shift_in_ls_byte)
10007
.Round(vform)
10008
.SignedSaturate(vform);
10009
break;
10010
case "sqshl_z_p_zz"_h:
10011
sshl(vform, result, zdn, zm, shift_in_ls_byte).SignedSaturate(vform);
10012
break;
10013
case "sqshlr_z_p_zz"_h:
10014
sshl(vform, result, zm, zdn, shift_in_ls_byte).SignedSaturate(vform);
10015
break;
10016
case "srshl_z_p_zz"_h:
10017
sshl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
10018
break;
10019
case "srshlr_z_p_zz"_h:
10020
sshl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
10021
break;
10022
case "uqrshl_z_p_zz"_h:
10023
ushl(vform, result, zdn, zm, shift_in_ls_byte)
10024
.Round(vform)
10025
.UnsignedSaturate(vform);
10026
break;
10027
case "uqrshlr_z_p_zz"_h:
10028
ushl(vform, result, zm, zdn, shift_in_ls_byte)
10029
.Round(vform)
10030
.UnsignedSaturate(vform);
10031
break;
10032
case "uqshl_z_p_zz"_h:
10033
ushl(vform, result, zdn, zm, shift_in_ls_byte).UnsignedSaturate(vform);
10034
break;
10035
case "uqshlr_z_p_zz"_h:
10036
ushl(vform, result, zm, zdn, shift_in_ls_byte).UnsignedSaturate(vform);
10037
break;
10038
case "urshl_z_p_zz"_h:
10039
ushl(vform, result, zdn, zm, shift_in_ls_byte).Round(vform);
10040
break;
10041
case "urshlr_z_p_zz"_h:
10042
ushl(vform, result, zm, zdn, shift_in_ls_byte).Round(vform);
10043
break;
10044
default:
10045
VIXL_UNIMPLEMENTED();
10046
break;
10047
}
10048
mov_merging(vform, zdn, pg, result);
10049
}
10050
10051
void Simulator::VisitSVEBitwiseShiftByWideElements_Predicated(
10052
const Instruction* instr) {
10053
VectorFormat vform = instr->GetSVEVectorFormat();
10054
SimVRegister& zdn = ReadVRegister(instr->GetRd());
10055
SimVRegister& zm = ReadVRegister(instr->GetRn());
10056
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10057
10058
SimVRegister result;
10059
Shift shift_op = ASR;
10060
10061
switch (instr->Mask(SVEBitwiseShiftByWideElements_PredicatedMask)) {
10062
case ASR_z_p_zw:
10063
break;
10064
case LSL_z_p_zw:
10065
shift_op = LSL;
10066
break;
10067
case LSR_z_p_zw:
10068
shift_op = LSR;
10069
break;
10070
default:
10071
VIXL_UNIMPLEMENTED();
10072
break;
10073
}
10074
SVEBitwiseShiftHelper(shift_op,
10075
vform,
10076
result,
10077
zdn,
10078
zm,
10079
/* is_wide_elements = */ true);
10080
mov_merging(vform, zdn, pg, result);
10081
}
10082
10083
void Simulator::VisitSVEBitwiseShiftUnpredicated(const Instruction* instr) {
10084
SimVRegister& zd = ReadVRegister(instr->GetRd());
10085
SimVRegister& zn = ReadVRegister(instr->GetRn());
10086
10087
Shift shift_op = NO_SHIFT;
10088
switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
10089
case ASR_z_zi:
10090
case ASR_z_zw:
10091
shift_op = ASR;
10092
break;
10093
case LSL_z_zi:
10094
case LSL_z_zw:
10095
shift_op = LSL;
10096
break;
10097
case LSR_z_zi:
10098
case LSR_z_zw:
10099
shift_op = LSR;
10100
break;
10101
default:
10102
VIXL_UNIMPLEMENTED();
10103
break;
10104
}
10105
10106
switch (instr->Mask(SVEBitwiseShiftUnpredicatedMask)) {
10107
case ASR_z_zi:
10108
case LSL_z_zi:
10109
case LSR_z_zi: {
10110
SimVRegister scratch;
10111
std::pair<int, int> shift_and_lane_size =
10112
instr->GetSVEImmShiftAndLaneSizeLog2(/* is_predicated = */ false);
10113
unsigned lane_size = shift_and_lane_size.second;
10114
VIXL_ASSERT(lane_size <= kDRegSizeInBytesLog2);
10115
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(lane_size);
10116
int shift_dist = shift_and_lane_size.first;
10117
if (shift_op == LSL) {
10118
// Shift distance is computed differently for LSL. Convert the result.
10119
shift_dist = (8 << lane_size) - shift_dist;
10120
}
10121
dup_immediate(vform, scratch, shift_dist);
10122
SVEBitwiseShiftHelper(shift_op, vform, zd, zn, scratch, false);
10123
break;
10124
}
10125
case ASR_z_zw:
10126
case LSL_z_zw:
10127
case LSR_z_zw:
10128
SVEBitwiseShiftHelper(shift_op,
10129
instr->GetSVEVectorFormat(),
10130
zd,
10131
zn,
10132
ReadVRegister(instr->GetRm()),
10133
true);
10134
break;
10135
default:
10136
VIXL_UNIMPLEMENTED();
10137
break;
10138
}
10139
}
10140
10141
void Simulator::VisitSVEIncDecRegisterByElementCount(const Instruction* instr) {
10142
// Although the instructions have a separate encoding class, the lane size is
10143
// encoded in the same way as most other SVE instructions.
10144
VectorFormat vform = instr->GetSVEVectorFormat();
10145
10146
int pattern = instr->GetImmSVEPredicateConstraint();
10147
int count = GetPredicateConstraintLaneCount(vform, pattern);
10148
int multiplier = instr->ExtractBits(19, 16) + 1;
10149
10150
switch (instr->Mask(SVEIncDecRegisterByElementCountMask)) {
10151
case DECB_r_rs:
10152
case DECD_r_rs:
10153
case DECH_r_rs:
10154
case DECW_r_rs:
10155
count = -count;
10156
break;
10157
case INCB_r_rs:
10158
case INCD_r_rs:
10159
case INCH_r_rs:
10160
case INCW_r_rs:
10161
// Nothing to do.
10162
break;
10163
default:
10164
VIXL_UNIMPLEMENTED();
10165
return;
10166
}
10167
10168
WriteXRegister(instr->GetRd(),
10169
IncDecN(ReadXRegister(instr->GetRd()),
10170
count * multiplier,
10171
kXRegSize));
10172
}
10173
10174
void Simulator::VisitSVEIncDecVectorByElementCount(const Instruction* instr) {
10175
VectorFormat vform = instr->GetSVEVectorFormat();
10176
if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10177
VIXL_UNIMPLEMENTED();
10178
}
10179
10180
int pattern = instr->GetImmSVEPredicateConstraint();
10181
int count = GetPredicateConstraintLaneCount(vform, pattern);
10182
int multiplier = instr->ExtractBits(19, 16) + 1;
10183
10184
switch (instr->Mask(SVEIncDecVectorByElementCountMask)) {
10185
case DECD_z_zs:
10186
case DECH_z_zs:
10187
case DECW_z_zs:
10188
count = -count;
10189
break;
10190
case INCD_z_zs:
10191
case INCH_z_zs:
10192
case INCW_z_zs:
10193
// Nothing to do.
10194
break;
10195
default:
10196
VIXL_UNIMPLEMENTED();
10197
break;
10198
}
10199
10200
SimVRegister& zd = ReadVRegister(instr->GetRd());
10201
SimVRegister scratch;
10202
dup_immediate(vform,
10203
scratch,
10204
IncDecN(0,
10205
count * multiplier,
10206
LaneSizeInBitsFromFormat(vform)));
10207
add(vform, zd, zd, scratch);
10208
}
10209
10210
void Simulator::VisitSVESaturatingIncDecRegisterByElementCount(
10211
const Instruction* instr) {
10212
// Although the instructions have a separate encoding class, the lane size is
10213
// encoded in the same way as most other SVE instructions.
10214
VectorFormat vform = instr->GetSVEVectorFormat();
10215
10216
int pattern = instr->GetImmSVEPredicateConstraint();
10217
int count = GetPredicateConstraintLaneCount(vform, pattern);
10218
int multiplier = instr->ExtractBits(19, 16) + 1;
10219
10220
unsigned width = kXRegSize;
10221
bool is_signed = false;
10222
10223
switch (instr->Mask(SVESaturatingIncDecRegisterByElementCountMask)) {
10224
case SQDECB_r_rs_sx:
10225
case SQDECD_r_rs_sx:
10226
case SQDECH_r_rs_sx:
10227
case SQDECW_r_rs_sx:
10228
width = kWRegSize;
10229
VIXL_FALLTHROUGH();
10230
case SQDECB_r_rs_x:
10231
case SQDECD_r_rs_x:
10232
case SQDECH_r_rs_x:
10233
case SQDECW_r_rs_x:
10234
is_signed = true;
10235
count = -count;
10236
break;
10237
case SQINCB_r_rs_sx:
10238
case SQINCD_r_rs_sx:
10239
case SQINCH_r_rs_sx:
10240
case SQINCW_r_rs_sx:
10241
width = kWRegSize;
10242
VIXL_FALLTHROUGH();
10243
case SQINCB_r_rs_x:
10244
case SQINCD_r_rs_x:
10245
case SQINCH_r_rs_x:
10246
case SQINCW_r_rs_x:
10247
is_signed = true;
10248
break;
10249
case UQDECB_r_rs_uw:
10250
case UQDECD_r_rs_uw:
10251
case UQDECH_r_rs_uw:
10252
case UQDECW_r_rs_uw:
10253
width = kWRegSize;
10254
VIXL_FALLTHROUGH();
10255
case UQDECB_r_rs_x:
10256
case UQDECD_r_rs_x:
10257
case UQDECH_r_rs_x:
10258
case UQDECW_r_rs_x:
10259
count = -count;
10260
break;
10261
case UQINCB_r_rs_uw:
10262
case UQINCD_r_rs_uw:
10263
case UQINCH_r_rs_uw:
10264
case UQINCW_r_rs_uw:
10265
width = kWRegSize;
10266
VIXL_FALLTHROUGH();
10267
case UQINCB_r_rs_x:
10268
case UQINCD_r_rs_x:
10269
case UQINCH_r_rs_x:
10270
case UQINCW_r_rs_x:
10271
// Nothing to do.
10272
break;
10273
default:
10274
VIXL_UNIMPLEMENTED();
10275
break;
10276
}
10277
10278
WriteXRegister(instr->GetRd(),
10279
IncDecN(ReadXRegister(instr->GetRd()),
10280
count * multiplier,
10281
width,
10282
true,
10283
is_signed));
10284
}
10285
10286
void Simulator::VisitSVESaturatingIncDecVectorByElementCount(
10287
const Instruction* instr) {
10288
VectorFormat vform = instr->GetSVEVectorFormat();
10289
if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10290
VIXL_UNIMPLEMENTED();
10291
}
10292
10293
int pattern = instr->GetImmSVEPredicateConstraint();
10294
int count = GetPredicateConstraintLaneCount(vform, pattern);
10295
int multiplier = instr->ExtractBits(19, 16) + 1;
10296
10297
SimVRegister& zd = ReadVRegister(instr->GetRd());
10298
SimVRegister scratch;
10299
dup_immediate(vform,
10300
scratch,
10301
IncDecN(0,
10302
count * multiplier,
10303
LaneSizeInBitsFromFormat(vform)));
10304
10305
switch (instr->Mask(SVESaturatingIncDecVectorByElementCountMask)) {
10306
case SQDECD_z_zs:
10307
case SQDECH_z_zs:
10308
case SQDECW_z_zs:
10309
sub(vform, zd, zd, scratch).SignedSaturate(vform);
10310
break;
10311
case SQINCD_z_zs:
10312
case SQINCH_z_zs:
10313
case SQINCW_z_zs:
10314
add(vform, zd, zd, scratch).SignedSaturate(vform);
10315
break;
10316
case UQDECD_z_zs:
10317
case UQDECH_z_zs:
10318
case UQDECW_z_zs:
10319
sub(vform, zd, zd, scratch).UnsignedSaturate(vform);
10320
break;
10321
case UQINCD_z_zs:
10322
case UQINCH_z_zs:
10323
case UQINCW_z_zs:
10324
add(vform, zd, zd, scratch).UnsignedSaturate(vform);
10325
break;
10326
default:
10327
VIXL_UNIMPLEMENTED();
10328
break;
10329
}
10330
}
10331
10332
void Simulator::VisitSVEElementCount(const Instruction* instr) {
10333
switch (instr->Mask(SVEElementCountMask)) {
10334
case CNTB_r_s:
10335
case CNTD_r_s:
10336
case CNTH_r_s:
10337
case CNTW_r_s:
10338
// All handled below.
10339
break;
10340
default:
10341
VIXL_UNIMPLEMENTED();
10342
break;
10343
}
10344
10345
// Although the instructions are separated, the lane size is encoded in the
10346
// same way as most other SVE instructions.
10347
VectorFormat vform = instr->GetSVEVectorFormat();
10348
10349
int pattern = instr->GetImmSVEPredicateConstraint();
10350
int count = GetPredicateConstraintLaneCount(vform, pattern);
10351
int multiplier = instr->ExtractBits(19, 16) + 1;
10352
WriteXRegister(instr->GetRd(), count * multiplier);
10353
}
10354
10355
void Simulator::VisitSVEFPAccumulatingReduction(const Instruction* instr) {
10356
VectorFormat vform = instr->GetSVEVectorFormat();
10357
SimVRegister& vdn = ReadVRegister(instr->GetRd());
10358
SimVRegister& zm = ReadVRegister(instr->GetRn());
10359
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10360
10361
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10362
10363
switch (instr->Mask(SVEFPAccumulatingReductionMask)) {
10364
case FADDA_v_p_z:
10365
fadda(vform, vdn, pg, zm);
10366
break;
10367
default:
10368
VIXL_UNIMPLEMENTED();
10369
break;
10370
}
10371
}
10372
10373
void Simulator::VisitSVEFPArithmetic_Predicated(const Instruction* instr) {
10374
VectorFormat vform = instr->GetSVEVectorFormat();
10375
SimVRegister& zdn = ReadVRegister(instr->GetRd());
10376
SimVRegister& zm = ReadVRegister(instr->GetRn());
10377
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10378
10379
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10380
10381
SimVRegister result;
10382
switch (instr->Mask(SVEFPArithmetic_PredicatedMask)) {
10383
case FABD_z_p_zz:
10384
fabd(vform, result, zdn, zm);
10385
break;
10386
case FADD_z_p_zz:
10387
fadd(vform, result, zdn, zm);
10388
break;
10389
case FDIVR_z_p_zz:
10390
fdiv(vform, result, zm, zdn);
10391
break;
10392
case FDIV_z_p_zz:
10393
fdiv(vform, result, zdn, zm);
10394
break;
10395
case FMAXNM_z_p_zz:
10396
fmaxnm(vform, result, zdn, zm);
10397
break;
10398
case FMAX_z_p_zz:
10399
fmax(vform, result, zdn, zm);
10400
break;
10401
case FMINNM_z_p_zz:
10402
fminnm(vform, result, zdn, zm);
10403
break;
10404
case FMIN_z_p_zz:
10405
fmin(vform, result, zdn, zm);
10406
break;
10407
case FMULX_z_p_zz:
10408
fmulx(vform, result, zdn, zm);
10409
break;
10410
case FMUL_z_p_zz:
10411
fmul(vform, result, zdn, zm);
10412
break;
10413
case FSCALE_z_p_zz:
10414
fscale(vform, result, zdn, zm);
10415
break;
10416
case FSUBR_z_p_zz:
10417
fsub(vform, result, zm, zdn);
10418
break;
10419
case FSUB_z_p_zz:
10420
fsub(vform, result, zdn, zm);
10421
break;
10422
default:
10423
VIXL_UNIMPLEMENTED();
10424
break;
10425
}
10426
mov_merging(vform, zdn, pg, result);
10427
}
10428
10429
void Simulator::VisitSVEFPArithmeticWithImm_Predicated(
10430
const Instruction* instr) {
10431
VectorFormat vform = instr->GetSVEVectorFormat();
10432
if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10433
VIXL_UNIMPLEMENTED();
10434
}
10435
10436
SimVRegister& zdn = ReadVRegister(instr->GetRd());
10437
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10438
SimVRegister result;
10439
10440
int i1 = instr->ExtractBit(5);
10441
SimVRegister add_sub_imm, min_max_imm, mul_imm;
10442
uint64_t half = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 0.5);
10443
uint64_t one = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 1.0);
10444
uint64_t two = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform), 2.0);
10445
dup_immediate(vform, add_sub_imm, i1 ? one : half);
10446
dup_immediate(vform, min_max_imm, i1 ? one : 0);
10447
dup_immediate(vform, mul_imm, i1 ? two : half);
10448
10449
switch (instr->Mask(SVEFPArithmeticWithImm_PredicatedMask)) {
10450
case FADD_z_p_zs:
10451
fadd(vform, result, zdn, add_sub_imm);
10452
break;
10453
case FMAXNM_z_p_zs:
10454
fmaxnm(vform, result, zdn, min_max_imm);
10455
break;
10456
case FMAX_z_p_zs:
10457
fmax(vform, result, zdn, min_max_imm);
10458
break;
10459
case FMINNM_z_p_zs:
10460
fminnm(vform, result, zdn, min_max_imm);
10461
break;
10462
case FMIN_z_p_zs:
10463
fmin(vform, result, zdn, min_max_imm);
10464
break;
10465
case FMUL_z_p_zs:
10466
fmul(vform, result, zdn, mul_imm);
10467
break;
10468
case FSUBR_z_p_zs:
10469
fsub(vform, result, add_sub_imm, zdn);
10470
break;
10471
case FSUB_z_p_zs:
10472
fsub(vform, result, zdn, add_sub_imm);
10473
break;
10474
default:
10475
VIXL_UNIMPLEMENTED();
10476
break;
10477
}
10478
mov_merging(vform, zdn, pg, result);
10479
}
10480
10481
void Simulator::VisitSVEFPTrigMulAddCoefficient(const Instruction* instr) {
10482
VectorFormat vform = instr->GetSVEVectorFormat();
10483
SimVRegister& zd = ReadVRegister(instr->GetRd());
10484
SimVRegister& zm = ReadVRegister(instr->GetRn());
10485
10486
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10487
10488
switch (instr->Mask(SVEFPTrigMulAddCoefficientMask)) {
10489
case FTMAD_z_zzi:
10490
ftmad(vform, zd, zd, zm, instr->ExtractBits(18, 16));
10491
break;
10492
default:
10493
VIXL_UNIMPLEMENTED();
10494
break;
10495
}
10496
}
10497
10498
void Simulator::VisitSVEFPArithmeticUnpredicated(const Instruction* instr) {
10499
VectorFormat vform = instr->GetSVEVectorFormat();
10500
SimVRegister& zd = ReadVRegister(instr->GetRd());
10501
SimVRegister& zn = ReadVRegister(instr->GetRn());
10502
SimVRegister& zm = ReadVRegister(instr->GetRm());
10503
10504
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10505
10506
switch (instr->Mask(SVEFPArithmeticUnpredicatedMask)) {
10507
case FADD_z_zz:
10508
fadd(vform, zd, zn, zm);
10509
break;
10510
case FMUL_z_zz:
10511
fmul(vform, zd, zn, zm);
10512
break;
10513
case FRECPS_z_zz:
10514
frecps(vform, zd, zn, zm);
10515
break;
10516
case FRSQRTS_z_zz:
10517
frsqrts(vform, zd, zn, zm);
10518
break;
10519
case FSUB_z_zz:
10520
fsub(vform, zd, zn, zm);
10521
break;
10522
case FTSMUL_z_zz:
10523
ftsmul(vform, zd, zn, zm);
10524
break;
10525
default:
10526
VIXL_UNIMPLEMENTED();
10527
break;
10528
}
10529
}
10530
10531
void Simulator::VisitSVEFPCompareVectors(const Instruction* instr) {
10532
SimPRegister& pd = ReadPRegister(instr->GetPd());
10533
SimVRegister& zn = ReadVRegister(instr->GetRn());
10534
SimVRegister& zm = ReadVRegister(instr->GetRm());
10535
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10536
VectorFormat vform = instr->GetSVEVectorFormat();
10537
SimVRegister result;
10538
10539
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10540
10541
switch (instr->Mask(SVEFPCompareVectorsMask)) {
10542
case FACGE_p_p_zz:
10543
fabscmp(vform, result, zn, zm, ge);
10544
break;
10545
case FACGT_p_p_zz:
10546
fabscmp(vform, result, zn, zm, gt);
10547
break;
10548
case FCMEQ_p_p_zz:
10549
fcmp(vform, result, zn, zm, eq);
10550
break;
10551
case FCMGE_p_p_zz:
10552
fcmp(vform, result, zn, zm, ge);
10553
break;
10554
case FCMGT_p_p_zz:
10555
fcmp(vform, result, zn, zm, gt);
10556
break;
10557
case FCMNE_p_p_zz:
10558
fcmp(vform, result, zn, zm, ne);
10559
break;
10560
case FCMUO_p_p_zz:
10561
fcmp(vform, result, zn, zm, uo);
10562
break;
10563
default:
10564
VIXL_UNIMPLEMENTED();
10565
break;
10566
}
10567
10568
ExtractFromSimVRegister(vform, pd, result);
10569
mov_zeroing(pd, pg, pd);
10570
}
10571
10572
void Simulator::VisitSVEFPCompareWithZero(const Instruction* instr) {
10573
SimPRegister& pd = ReadPRegister(instr->GetPd());
10574
SimVRegister& zn = ReadVRegister(instr->GetRn());
10575
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10576
VectorFormat vform = instr->GetSVEVectorFormat();
10577
10578
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10579
10580
SimVRegister result;
10581
SimVRegister zeros;
10582
dup_immediate(kFormatVnD, zeros, 0);
10583
10584
switch (instr->Mask(SVEFPCompareWithZeroMask)) {
10585
case FCMEQ_p_p_z0:
10586
fcmp(vform, result, zn, zeros, eq);
10587
break;
10588
case FCMGE_p_p_z0:
10589
fcmp(vform, result, zn, zeros, ge);
10590
break;
10591
case FCMGT_p_p_z0:
10592
fcmp(vform, result, zn, zeros, gt);
10593
break;
10594
case FCMLE_p_p_z0:
10595
fcmp(vform, result, zn, zeros, le);
10596
break;
10597
case FCMLT_p_p_z0:
10598
fcmp(vform, result, zn, zeros, lt);
10599
break;
10600
case FCMNE_p_p_z0:
10601
fcmp(vform, result, zn, zeros, ne);
10602
break;
10603
default:
10604
VIXL_UNIMPLEMENTED();
10605
break;
10606
}
10607
10608
ExtractFromSimVRegister(vform, pd, result);
10609
mov_zeroing(pd, pg, pd);
10610
}
10611
10612
void Simulator::VisitSVEFPComplexAddition(const Instruction* instr) {
10613
VectorFormat vform = instr->GetSVEVectorFormat();
10614
10615
if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10616
VIXL_UNIMPLEMENTED();
10617
}
10618
10619
SimVRegister& zdn = ReadVRegister(instr->GetRd());
10620
SimVRegister& zm = ReadVRegister(instr->GetRn());
10621
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10622
int rot = instr->ExtractBit(16);
10623
10624
SimVRegister result;
10625
10626
switch (instr->Mask(SVEFPComplexAdditionMask)) {
10627
case FCADD_z_p_zz:
10628
fcadd(vform, result, zdn, zm, rot);
10629
break;
10630
default:
10631
VIXL_UNIMPLEMENTED();
10632
break;
10633
}
10634
mov_merging(vform, zdn, pg, result);
10635
}
10636
10637
void Simulator::VisitSVEFPComplexMulAdd(const Instruction* instr) {
10638
VectorFormat vform = instr->GetSVEVectorFormat();
10639
10640
if (LaneSizeInBitsFromFormat(vform) == kBRegSize) {
10641
VIXL_UNIMPLEMENTED();
10642
}
10643
10644
SimVRegister& zda = ReadVRegister(instr->GetRd());
10645
SimVRegister& zn = ReadVRegister(instr->GetRn());
10646
SimVRegister& zm = ReadVRegister(instr->GetRm());
10647
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10648
int rot = instr->ExtractBits(14, 13);
10649
10650
SimVRegister result;
10651
10652
switch (instr->Mask(SVEFPComplexMulAddMask)) {
10653
case FCMLA_z_p_zzz:
10654
fcmla(vform, result, zn, zm, zda, rot);
10655
break;
10656
default:
10657
VIXL_UNIMPLEMENTED();
10658
break;
10659
}
10660
mov_merging(vform, zda, pg, result);
10661
}
10662
10663
void Simulator::VisitSVEFPComplexMulAddIndex(const Instruction* instr) {
10664
SimVRegister& zda = ReadVRegister(instr->GetRd());
10665
SimVRegister& zn = ReadVRegister(instr->GetRn());
10666
int rot = instr->ExtractBits(11, 10);
10667
unsigned zm_code = instr->GetRm();
10668
int index = -1;
10669
VectorFormat vform, vform_dup;
10670
10671
switch (instr->Mask(SVEFPComplexMulAddIndexMask)) {
10672
case FCMLA_z_zzzi_h:
10673
vform = kFormatVnH;
10674
vform_dup = kFormatVnS;
10675
index = zm_code >> 3;
10676
zm_code &= 0x7;
10677
break;
10678
case FCMLA_z_zzzi_s:
10679
vform = kFormatVnS;
10680
vform_dup = kFormatVnD;
10681
index = zm_code >> 4;
10682
zm_code &= 0xf;
10683
break;
10684
default:
10685
VIXL_UNIMPLEMENTED();
10686
break;
10687
}
10688
10689
if (index >= 0) {
10690
SimVRegister temp;
10691
dup_elements_to_segments(vform_dup, temp, ReadVRegister(zm_code), index);
10692
fcmla(vform, zda, zn, temp, zda, rot);
10693
}
10694
}
10695
10696
typedef LogicVRegister (Simulator::*FastReduceFn)(VectorFormat vform,
10697
LogicVRegister dst,
10698
const LogicVRegister& src);
10699
10700
void Simulator::VisitSVEFPFastReduction(const Instruction* instr) {
10701
VectorFormat vform = instr->GetSVEVectorFormat();
10702
SimVRegister& vd = ReadVRegister(instr->GetRd());
10703
SimVRegister& zn = ReadVRegister(instr->GetRn());
10704
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10705
int lane_size = LaneSizeInBitsFromFormat(vform);
10706
10707
uint64_t inactive_value = 0;
10708
FastReduceFn fn = nullptr;
10709
10710
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10711
10712
switch (instr->Mask(SVEFPFastReductionMask)) {
10713
case FADDV_v_p_z:
10714
fn = &Simulator::faddv;
10715
break;
10716
case FMAXNMV_v_p_z:
10717
inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10718
fn = &Simulator::fmaxnmv;
10719
break;
10720
case FMAXV_v_p_z:
10721
inactive_value = FPToRawbitsWithSize(lane_size, kFP64NegativeInfinity);
10722
fn = &Simulator::fmaxv;
10723
break;
10724
case FMINNMV_v_p_z:
10725
inactive_value = FPToRawbitsWithSize(lane_size, kFP64DefaultNaN);
10726
fn = &Simulator::fminnmv;
10727
break;
10728
case FMINV_v_p_z:
10729
inactive_value = FPToRawbitsWithSize(lane_size, kFP64PositiveInfinity);
10730
fn = &Simulator::fminv;
10731
break;
10732
default:
10733
VIXL_UNIMPLEMENTED();
10734
break;
10735
}
10736
10737
SimVRegister scratch;
10738
dup_immediate(vform, scratch, inactive_value);
10739
mov_merging(vform, scratch, pg, zn);
10740
if (fn != nullptr) (this->*fn)(vform, vd, scratch);
10741
}
10742
10743
void Simulator::VisitSVEFPMulIndex(const Instruction* instr) {
10744
VectorFormat vform = kFormatUndefined;
10745
10746
switch (instr->Mask(SVEFPMulIndexMask)) {
10747
case FMUL_z_zzi_d:
10748
vform = kFormatVnD;
10749
break;
10750
case FMUL_z_zzi_h_i3h:
10751
case FMUL_z_zzi_h:
10752
vform = kFormatVnH;
10753
break;
10754
case FMUL_z_zzi_s:
10755
vform = kFormatVnS;
10756
break;
10757
default:
10758
VIXL_UNIMPLEMENTED();
10759
break;
10760
}
10761
10762
SimVRegister& zd = ReadVRegister(instr->GetRd());
10763
SimVRegister& zn = ReadVRegister(instr->GetRn());
10764
SimVRegister temp;
10765
10766
dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
10767
fmul(vform, zd, zn, temp);
10768
}
10769
10770
void Simulator::VisitSVEFPMulAdd(const Instruction* instr) {
10771
VectorFormat vform = instr->GetSVEVectorFormat();
10772
SimVRegister& zd = ReadVRegister(instr->GetRd());
10773
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10774
SimVRegister result;
10775
10776
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
10777
10778
if (instr->ExtractBit(15) == 0) {
10779
// Floating-point multiply-accumulate writing addend.
10780
SimVRegister& zm = ReadVRegister(instr->GetRm());
10781
SimVRegister& zn = ReadVRegister(instr->GetRn());
10782
10783
switch (instr->Mask(SVEFPMulAddMask)) {
10784
// zda = zda + zn * zm
10785
case FMLA_z_p_zzz:
10786
fmla(vform, result, zd, zn, zm);
10787
break;
10788
// zda = -zda + -zn * zm
10789
case FNMLA_z_p_zzz:
10790
fneg(vform, result, zd);
10791
fmls(vform, result, result, zn, zm);
10792
break;
10793
// zda = zda + -zn * zm
10794
case FMLS_z_p_zzz:
10795
fmls(vform, result, zd, zn, zm);
10796
break;
10797
// zda = -zda + zn * zm
10798
case FNMLS_z_p_zzz:
10799
fneg(vform, result, zd);
10800
fmla(vform, result, result, zn, zm);
10801
break;
10802
default:
10803
VIXL_UNIMPLEMENTED();
10804
break;
10805
}
10806
} else {
10807
// Floating-point multiply-accumulate writing multiplicand.
10808
SimVRegister& za = ReadVRegister(instr->GetRm());
10809
SimVRegister& zm = ReadVRegister(instr->GetRn());
10810
10811
switch (instr->Mask(SVEFPMulAddMask)) {
10812
// zdn = za + zdn * zm
10813
case FMAD_z_p_zzz:
10814
fmla(vform, result, za, zd, zm);
10815
break;
10816
// zdn = -za + -zdn * zm
10817
case FNMAD_z_p_zzz:
10818
fneg(vform, result, za);
10819
fmls(vform, result, result, zd, zm);
10820
break;
10821
// zdn = za + -zdn * zm
10822
case FMSB_z_p_zzz:
10823
fmls(vform, result, za, zd, zm);
10824
break;
10825
// zdn = -za + zdn * zm
10826
case FNMSB_z_p_zzz:
10827
fneg(vform, result, za);
10828
fmla(vform, result, result, zd, zm);
10829
break;
10830
default:
10831
VIXL_UNIMPLEMENTED();
10832
break;
10833
}
10834
}
10835
10836
mov_merging(vform, zd, pg, result);
10837
}
10838
10839
void Simulator::VisitSVEFPMulAddIndex(const Instruction* instr) {
10840
VectorFormat vform = kFormatUndefined;
10841
10842
switch (instr->Mask(SVEFPMulAddIndexMask)) {
10843
case FMLA_z_zzzi_d:
10844
case FMLS_z_zzzi_d:
10845
vform = kFormatVnD;
10846
break;
10847
case FMLA_z_zzzi_s:
10848
case FMLS_z_zzzi_s:
10849
vform = kFormatVnS;
10850
break;
10851
case FMLA_z_zzzi_h:
10852
case FMLS_z_zzzi_h:
10853
case FMLA_z_zzzi_h_i3h:
10854
case FMLS_z_zzzi_h_i3h:
10855
vform = kFormatVnH;
10856
break;
10857
default:
10858
VIXL_UNIMPLEMENTED();
10859
break;
10860
}
10861
10862
SimVRegister& zd = ReadVRegister(instr->GetRd());
10863
SimVRegister& zn = ReadVRegister(instr->GetRn());
10864
SimVRegister temp;
10865
10866
dup_elements_to_segments(vform, temp, instr->GetSVEMulZmAndIndex());
10867
if (instr->ExtractBit(10) == 1) {
10868
fmls(vform, zd, zd, zn, temp);
10869
} else {
10870
fmla(vform, zd, zd, zn, temp);
10871
}
10872
}
10873
10874
void Simulator::VisitSVEFPConvertToInt(const Instruction* instr) {
10875
SimVRegister& zd = ReadVRegister(instr->GetRd());
10876
SimVRegister& zn = ReadVRegister(instr->GetRn());
10877
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10878
int dst_data_size;
10879
int src_data_size;
10880
10881
switch (instr->Mask(SVEFPConvertToIntMask)) {
10882
case FCVTZS_z_p_z_d2w:
10883
case FCVTZU_z_p_z_d2w:
10884
dst_data_size = kSRegSize;
10885
src_data_size = kDRegSize;
10886
break;
10887
case FCVTZS_z_p_z_d2x:
10888
case FCVTZU_z_p_z_d2x:
10889
dst_data_size = kDRegSize;
10890
src_data_size = kDRegSize;
10891
break;
10892
case FCVTZS_z_p_z_fp162h:
10893
case FCVTZU_z_p_z_fp162h:
10894
dst_data_size = kHRegSize;
10895
src_data_size = kHRegSize;
10896
break;
10897
case FCVTZS_z_p_z_fp162w:
10898
case FCVTZU_z_p_z_fp162w:
10899
dst_data_size = kSRegSize;
10900
src_data_size = kHRegSize;
10901
break;
10902
case FCVTZS_z_p_z_fp162x:
10903
case FCVTZU_z_p_z_fp162x:
10904
dst_data_size = kDRegSize;
10905
src_data_size = kHRegSize;
10906
break;
10907
case FCVTZS_z_p_z_s2w:
10908
case FCVTZU_z_p_z_s2w:
10909
dst_data_size = kSRegSize;
10910
src_data_size = kSRegSize;
10911
break;
10912
case FCVTZS_z_p_z_s2x:
10913
case FCVTZU_z_p_z_s2x:
10914
dst_data_size = kDRegSize;
10915
src_data_size = kSRegSize;
10916
break;
10917
default:
10918
VIXL_UNIMPLEMENTED();
10919
dst_data_size = 0;
10920
src_data_size = 0;
10921
break;
10922
}
10923
10924
VectorFormat vform =
10925
SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
10926
10927
if (instr->ExtractBit(16) == 0) {
10928
fcvts(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10929
} else {
10930
fcvtu(vform, dst_data_size, src_data_size, zd, pg, zn, FPZero);
10931
}
10932
}
10933
10934
void Simulator::VisitSVEFPConvertPrecision(const Instruction* instr) {
10935
SimVRegister& zd = ReadVRegister(instr->GetRd());
10936
SimVRegister& zn = ReadVRegister(instr->GetRn());
10937
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10938
VectorFormat dst_data_size = kFormatUndefined;
10939
VectorFormat src_data_size = kFormatUndefined;
10940
10941
switch (instr->Mask(SVEFPConvertPrecisionMask)) {
10942
case FCVT_z_p_z_d2h:
10943
dst_data_size = kFormatVnH;
10944
src_data_size = kFormatVnD;
10945
break;
10946
case FCVT_z_p_z_d2s:
10947
dst_data_size = kFormatVnS;
10948
src_data_size = kFormatVnD;
10949
break;
10950
case FCVT_z_p_z_h2d:
10951
dst_data_size = kFormatVnD;
10952
src_data_size = kFormatVnH;
10953
break;
10954
case FCVT_z_p_z_h2s:
10955
dst_data_size = kFormatVnS;
10956
src_data_size = kFormatVnH;
10957
break;
10958
case FCVT_z_p_z_s2d:
10959
dst_data_size = kFormatVnD;
10960
src_data_size = kFormatVnS;
10961
break;
10962
case FCVT_z_p_z_s2h:
10963
dst_data_size = kFormatVnH;
10964
src_data_size = kFormatVnS;
10965
break;
10966
default:
10967
VIXL_UNIMPLEMENTED();
10968
break;
10969
}
10970
10971
fcvt(dst_data_size, src_data_size, zd, pg, zn);
10972
}
10973
10974
void Simulator::VisitSVEFPUnaryOp(const Instruction* instr) {
10975
SimVRegister& zd = ReadVRegister(instr->GetRd());
10976
SimVRegister& zn = ReadVRegister(instr->GetRn());
10977
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10978
VectorFormat vform = instr->GetSVEVectorFormat();
10979
SimVRegister result;
10980
10981
switch (instr->Mask(SVEFPUnaryOpMask)) {
10982
case FRECPX_z_p_z:
10983
frecpx(vform, result, zn);
10984
break;
10985
case FSQRT_z_p_z:
10986
fsqrt(vform, result, zn);
10987
break;
10988
default:
10989
VIXL_UNIMPLEMENTED();
10990
break;
10991
}
10992
mov_merging(vform, zd, pg, result);
10993
}
10994
10995
void Simulator::VisitSVEFPRoundToIntegralValue(const Instruction* instr) {
10996
SimVRegister& zd = ReadVRegister(instr->GetRd());
10997
SimVRegister& zn = ReadVRegister(instr->GetRn());
10998
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
10999
VectorFormat vform = instr->GetSVEVectorFormat();
11000
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
11001
bool exact_exception = false;
11002
11003
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
11004
11005
switch (instr->Mask(SVEFPRoundToIntegralValueMask)) {
11006
case FRINTA_z_p_z:
11007
fpcr_rounding = FPTieAway;
11008
break;
11009
case FRINTI_z_p_z:
11010
break; // Use FPCR rounding mode.
11011
case FRINTM_z_p_z:
11012
fpcr_rounding = FPNegativeInfinity;
11013
break;
11014
case FRINTN_z_p_z:
11015
fpcr_rounding = FPTieEven;
11016
break;
11017
case FRINTP_z_p_z:
11018
fpcr_rounding = FPPositiveInfinity;
11019
break;
11020
case FRINTX_z_p_z:
11021
exact_exception = true;
11022
break;
11023
case FRINTZ_z_p_z:
11024
fpcr_rounding = FPZero;
11025
break;
11026
default:
11027
VIXL_UNIMPLEMENTED();
11028
break;
11029
}
11030
11031
SimVRegister result;
11032
frint(vform, result, zn, fpcr_rounding, exact_exception, kFrintToInteger);
11033
mov_merging(vform, zd, pg, result);
11034
}
11035
11036
void Simulator::VisitSVEIntConvertToFP(const Instruction* instr) {
11037
SimVRegister& zd = ReadVRegister(instr->GetRd());
11038
SimVRegister& zn = ReadVRegister(instr->GetRn());
11039
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11040
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
11041
int dst_data_size;
11042
int src_data_size;
11043
11044
switch (instr->Mask(SVEIntConvertToFPMask)) {
11045
case SCVTF_z_p_z_h2fp16:
11046
case UCVTF_z_p_z_h2fp16:
11047
dst_data_size = kHRegSize;
11048
src_data_size = kHRegSize;
11049
break;
11050
case SCVTF_z_p_z_w2d:
11051
case UCVTF_z_p_z_w2d:
11052
dst_data_size = kDRegSize;
11053
src_data_size = kSRegSize;
11054
break;
11055
case SCVTF_z_p_z_w2fp16:
11056
case UCVTF_z_p_z_w2fp16:
11057
dst_data_size = kHRegSize;
11058
src_data_size = kSRegSize;
11059
break;
11060
case SCVTF_z_p_z_w2s:
11061
case UCVTF_z_p_z_w2s:
11062
dst_data_size = kSRegSize;
11063
src_data_size = kSRegSize;
11064
break;
11065
case SCVTF_z_p_z_x2d:
11066
case UCVTF_z_p_z_x2d:
11067
dst_data_size = kDRegSize;
11068
src_data_size = kDRegSize;
11069
break;
11070
case SCVTF_z_p_z_x2fp16:
11071
case UCVTF_z_p_z_x2fp16:
11072
dst_data_size = kHRegSize;
11073
src_data_size = kDRegSize;
11074
break;
11075
case SCVTF_z_p_z_x2s:
11076
case UCVTF_z_p_z_x2s:
11077
dst_data_size = kSRegSize;
11078
src_data_size = kDRegSize;
11079
break;
11080
default:
11081
VIXL_UNIMPLEMENTED();
11082
dst_data_size = 0;
11083
src_data_size = 0;
11084
break;
11085
}
11086
11087
VectorFormat vform =
11088
SVEFormatFromLaneSizeInBits(std::max(dst_data_size, src_data_size));
11089
11090
if (instr->ExtractBit(16) == 0) {
11091
scvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
11092
} else {
11093
ucvtf(vform, dst_data_size, src_data_size, zd, pg, zn, fpcr_rounding);
11094
}
11095
}
11096
11097
void Simulator::VisitSVEFPUnaryOpUnpredicated(const Instruction* instr) {
11098
VectorFormat vform = instr->GetSVEVectorFormat();
11099
SimVRegister& zd = ReadVRegister(instr->GetRd());
11100
SimVRegister& zn = ReadVRegister(instr->GetRn());
11101
FPRounding fpcr_rounding = static_cast<FPRounding>(ReadFpcr().GetRMode());
11102
11103
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
11104
11105
switch (instr->Mask(SVEFPUnaryOpUnpredicatedMask)) {
11106
case FRECPE_z_z:
11107
frecpe(vform, zd, zn, fpcr_rounding);
11108
break;
11109
case FRSQRTE_z_z:
11110
frsqrte(vform, zd, zn);
11111
break;
11112
default:
11113
VIXL_UNIMPLEMENTED();
11114
break;
11115
}
11116
}
11117
11118
void Simulator::VisitSVEIncDecByPredicateCount(const Instruction* instr) {
11119
VectorFormat vform = instr->GetSVEVectorFormat();
11120
SimPRegister& pg = ReadPRegister(instr->ExtractBits(8, 5));
11121
11122
int count = CountActiveLanes(vform, pg);
11123
11124
if (instr->ExtractBit(11) == 0) {
11125
SimVRegister& zdn = ReadVRegister(instr->GetRd());
11126
switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
11127
case DECP_z_p_z:
11128
sub_uint(vform, zdn, zdn, count);
11129
break;
11130
case INCP_z_p_z:
11131
add_uint(vform, zdn, zdn, count);
11132
break;
11133
case SQDECP_z_p_z:
11134
sub_uint(vform, zdn, zdn, count).SignedSaturate(vform);
11135
break;
11136
case SQINCP_z_p_z:
11137
add_uint(vform, zdn, zdn, count).SignedSaturate(vform);
11138
break;
11139
case UQDECP_z_p_z:
11140
sub_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
11141
break;
11142
case UQINCP_z_p_z:
11143
add_uint(vform, zdn, zdn, count).UnsignedSaturate(vform);
11144
break;
11145
default:
11146
VIXL_UNIMPLEMENTED();
11147
break;
11148
}
11149
} else {
11150
bool is_saturating = (instr->ExtractBit(18) == 0);
11151
bool decrement =
11152
is_saturating ? instr->ExtractBit(17) : instr->ExtractBit(16);
11153
bool is_signed = (instr->ExtractBit(16) == 0);
11154
bool sf = is_saturating ? (instr->ExtractBit(10) != 0) : true;
11155
unsigned width = sf ? kXRegSize : kWRegSize;
11156
11157
switch (instr->Mask(SVEIncDecByPredicateCountMask)) {
11158
case DECP_r_p_r:
11159
case INCP_r_p_r:
11160
case SQDECP_r_p_r_sx:
11161
case SQDECP_r_p_r_x:
11162
case SQINCP_r_p_r_sx:
11163
case SQINCP_r_p_r_x:
11164
case UQDECP_r_p_r_uw:
11165
case UQDECP_r_p_r_x:
11166
case UQINCP_r_p_r_uw:
11167
case UQINCP_r_p_r_x:
11168
WriteXRegister(instr->GetRd(),
11169
IncDecN(ReadXRegister(instr->GetRd()),
11170
decrement ? -count : count,
11171
width,
11172
is_saturating,
11173
is_signed));
11174
break;
11175
default:
11176
VIXL_UNIMPLEMENTED();
11177
break;
11178
}
11179
}
11180
}
11181
11182
uint64_t Simulator::IncDecN(uint64_t acc,
11183
int64_t delta,
11184
unsigned n,
11185
bool is_saturating,
11186
bool is_signed) {
11187
VIXL_ASSERT(n <= 64);
11188
VIXL_ASSERT(IsIntN(n, delta));
11189
11190
uint64_t sign_mask = UINT64_C(1) << (n - 1);
11191
uint64_t mask = GetUintMask(n);
11192
11193
acc &= mask; // Ignore initial accumulator high bits.
11194
uint64_t result = (acc + delta) & mask;
11195
11196
bool result_negative = ((result & sign_mask) != 0);
11197
11198
if (is_saturating) {
11199
if (is_signed) {
11200
bool acc_negative = ((acc & sign_mask) != 0);
11201
bool delta_negative = delta < 0;
11202
11203
// If the signs of the operands are the same, but different from the
11204
// result, there was an overflow.
11205
if ((acc_negative == delta_negative) &&
11206
(acc_negative != result_negative)) {
11207
if (result_negative) {
11208
// Saturate to [..., INT<n>_MAX].
11209
result_negative = false;
11210
result = mask & ~sign_mask; // E.g. 0x000000007fffffff
11211
} else {
11212
// Saturate to [INT<n>_MIN, ...].
11213
result_negative = true;
11214
result = ~mask | sign_mask; // E.g. 0xffffffff80000000
11215
}
11216
}
11217
} else {
11218
if ((delta < 0) && (result > acc)) {
11219
// Saturate to [0, ...].
11220
result = 0;
11221
} else if ((delta > 0) && (result < acc)) {
11222
// Saturate to [..., UINT<n>_MAX].
11223
result = mask;
11224
}
11225
}
11226
}
11227
11228
// Sign-extend if necessary.
11229
if (result_negative && is_signed) result |= ~mask;
11230
11231
return result;
11232
}
11233
11234
void Simulator::VisitSVEIndexGeneration(const Instruction* instr) {
11235
VectorFormat vform = instr->GetSVEVectorFormat();
11236
SimVRegister& zd = ReadVRegister(instr->GetRd());
11237
switch (instr->Mask(SVEIndexGenerationMask)) {
11238
case INDEX_z_ii:
11239
case INDEX_z_ir:
11240
case INDEX_z_ri:
11241
case INDEX_z_rr: {
11242
uint64_t start = instr->ExtractBit(10) ? ReadXRegister(instr->GetRn())
11243
: instr->ExtractSignedBits(9, 5);
11244
uint64_t step = instr->ExtractBit(11) ? ReadXRegister(instr->GetRm())
11245
: instr->ExtractSignedBits(20, 16);
11246
index(vform, zd, start, step);
11247
break;
11248
}
11249
default:
11250
VIXL_UNIMPLEMENTED();
11251
break;
11252
}
11253
}
11254
11255
void Simulator::VisitSVEIntArithmeticUnpredicated(const Instruction* instr) {
11256
VectorFormat vform = instr->GetSVEVectorFormat();
11257
SimVRegister& zd = ReadVRegister(instr->GetRd());
11258
SimVRegister& zn = ReadVRegister(instr->GetRn());
11259
SimVRegister& zm = ReadVRegister(instr->GetRm());
11260
switch (instr->Mask(SVEIntArithmeticUnpredicatedMask)) {
11261
case ADD_z_zz:
11262
add(vform, zd, zn, zm);
11263
break;
11264
case SQADD_z_zz:
11265
add(vform, zd, zn, zm).SignedSaturate(vform);
11266
break;
11267
case SQSUB_z_zz:
11268
sub(vform, zd, zn, zm).SignedSaturate(vform);
11269
break;
11270
case SUB_z_zz:
11271
sub(vform, zd, zn, zm);
11272
break;
11273
case UQADD_z_zz:
11274
add(vform, zd, zn, zm).UnsignedSaturate(vform);
11275
break;
11276
case UQSUB_z_zz:
11277
sub(vform, zd, zn, zm).UnsignedSaturate(vform);
11278
break;
11279
default:
11280
VIXL_UNIMPLEMENTED();
11281
break;
11282
}
11283
}
11284
11285
void Simulator::VisitSVEIntAddSubtractVectors_Predicated(
11286
const Instruction* instr) {
11287
VectorFormat vform = instr->GetSVEVectorFormat();
11288
SimVRegister& zdn = ReadVRegister(instr->GetRd());
11289
SimVRegister& zm = ReadVRegister(instr->GetRn());
11290
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11291
SimVRegister result;
11292
11293
switch (instr->Mask(SVEIntAddSubtractVectors_PredicatedMask)) {
11294
case ADD_z_p_zz:
11295
add(vform, result, zdn, zm);
11296
break;
11297
case SUBR_z_p_zz:
11298
sub(vform, result, zm, zdn);
11299
break;
11300
case SUB_z_p_zz:
11301
sub(vform, result, zdn, zm);
11302
break;
11303
default:
11304
VIXL_UNIMPLEMENTED();
11305
break;
11306
}
11307
mov_merging(vform, zdn, pg, result);
11308
}
11309
11310
void Simulator::VisitSVEBitwiseLogical_Predicated(const Instruction* instr) {
11311
VectorFormat vform = instr->GetSVEVectorFormat();
11312
SimVRegister& zdn = ReadVRegister(instr->GetRd());
11313
SimVRegister& zm = ReadVRegister(instr->GetRn());
11314
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11315
SimVRegister result;
11316
11317
switch (instr->Mask(SVEBitwiseLogical_PredicatedMask)) {
11318
case AND_z_p_zz:
11319
SVEBitwiseLogicalUnpredicatedHelper(AND, vform, result, zdn, zm);
11320
break;
11321
case BIC_z_p_zz:
11322
SVEBitwiseLogicalUnpredicatedHelper(BIC, vform, result, zdn, zm);
11323
break;
11324
case EOR_z_p_zz:
11325
SVEBitwiseLogicalUnpredicatedHelper(EOR, vform, result, zdn, zm);
11326
break;
11327
case ORR_z_p_zz:
11328
SVEBitwiseLogicalUnpredicatedHelper(ORR, vform, result, zdn, zm);
11329
break;
11330
default:
11331
VIXL_UNIMPLEMENTED();
11332
break;
11333
}
11334
mov_merging(vform, zdn, pg, result);
11335
}
11336
11337
void Simulator::VisitSVEIntMulVectors_Predicated(const Instruction* instr) {
11338
VectorFormat vform = instr->GetSVEVectorFormat();
11339
SimVRegister& zdn = ReadVRegister(instr->GetRd());
11340
SimVRegister& zm = ReadVRegister(instr->GetRn());
11341
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11342
SimVRegister result;
11343
11344
switch (instr->Mask(SVEIntMulVectors_PredicatedMask)) {
11345
case MUL_z_p_zz:
11346
mul(vform, result, zdn, zm);
11347
break;
11348
case SMULH_z_p_zz:
11349
smulh(vform, result, zdn, zm);
11350
break;
11351
case UMULH_z_p_zz:
11352
umulh(vform, result, zdn, zm);
11353
break;
11354
default:
11355
VIXL_UNIMPLEMENTED();
11356
break;
11357
}
11358
mov_merging(vform, zdn, pg, result);
11359
}
11360
11361
void Simulator::VisitSVEIntMinMaxDifference_Predicated(
11362
const Instruction* instr) {
11363
VectorFormat vform = instr->GetSVEVectorFormat();
11364
SimVRegister& zdn = ReadVRegister(instr->GetRd());
11365
SimVRegister& zm = ReadVRegister(instr->GetRn());
11366
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11367
SimVRegister result;
11368
11369
switch (instr->Mask(SVEIntMinMaxDifference_PredicatedMask)) {
11370
case SABD_z_p_zz:
11371
absdiff(vform, result, zdn, zm, true);
11372
break;
11373
case SMAX_z_p_zz:
11374
smax(vform, result, zdn, zm);
11375
break;
11376
case SMIN_z_p_zz:
11377
smin(vform, result, zdn, zm);
11378
break;
11379
case UABD_z_p_zz:
11380
absdiff(vform, result, zdn, zm, false);
11381
break;
11382
case UMAX_z_p_zz:
11383
umax(vform, result, zdn, zm);
11384
break;
11385
case UMIN_z_p_zz:
11386
umin(vform, result, zdn, zm);
11387
break;
11388
default:
11389
VIXL_UNIMPLEMENTED();
11390
break;
11391
}
11392
mov_merging(vform, zdn, pg, result);
11393
}
11394
11395
void Simulator::VisitSVEIntMulImm_Unpredicated(const Instruction* instr) {
11396
VectorFormat vform = instr->GetSVEVectorFormat();
11397
SimVRegister& zd = ReadVRegister(instr->GetRd());
11398
SimVRegister scratch;
11399
11400
switch (instr->Mask(SVEIntMulImm_UnpredicatedMask)) {
11401
case MUL_z_zi:
11402
dup_immediate(vform, scratch, instr->GetImmSVEIntWideSigned());
11403
mul(vform, zd, zd, scratch);
11404
break;
11405
default:
11406
VIXL_UNIMPLEMENTED();
11407
break;
11408
}
11409
}
11410
11411
void Simulator::VisitSVEIntDivideVectors_Predicated(const Instruction* instr) {
11412
VectorFormat vform = instr->GetSVEVectorFormat();
11413
SimVRegister& zdn = ReadVRegister(instr->GetRd());
11414
SimVRegister& zm = ReadVRegister(instr->GetRn());
11415
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11416
SimVRegister result;
11417
11418
VIXL_ASSERT((vform == kFormatVnS) || (vform == kFormatVnD));
11419
11420
switch (instr->Mask(SVEIntDivideVectors_PredicatedMask)) {
11421
case SDIVR_z_p_zz:
11422
sdiv(vform, result, zm, zdn);
11423
break;
11424
case SDIV_z_p_zz:
11425
sdiv(vform, result, zdn, zm);
11426
break;
11427
case UDIVR_z_p_zz:
11428
udiv(vform, result, zm, zdn);
11429
break;
11430
case UDIV_z_p_zz:
11431
udiv(vform, result, zdn, zm);
11432
break;
11433
default:
11434
VIXL_UNIMPLEMENTED();
11435
break;
11436
}
11437
mov_merging(vform, zdn, pg, result);
11438
}
11439
11440
void Simulator::VisitSVEIntMinMaxImm_Unpredicated(const Instruction* instr) {
11441
VectorFormat vform = instr->GetSVEVectorFormat();
11442
SimVRegister& zd = ReadVRegister(instr->GetRd());
11443
SimVRegister scratch;
11444
11445
uint64_t unsigned_imm = instr->GetImmSVEIntWideUnsigned();
11446
int64_t signed_imm = instr->GetImmSVEIntWideSigned();
11447
11448
switch (instr->Mask(SVEIntMinMaxImm_UnpredicatedMask)) {
11449
case SMAX_z_zi:
11450
dup_immediate(vform, scratch, signed_imm);
11451
smax(vform, zd, zd, scratch);
11452
break;
11453
case SMIN_z_zi:
11454
dup_immediate(vform, scratch, signed_imm);
11455
smin(vform, zd, zd, scratch);
11456
break;
11457
case UMAX_z_zi:
11458
dup_immediate(vform, scratch, unsigned_imm);
11459
umax(vform, zd, zd, scratch);
11460
break;
11461
case UMIN_z_zi:
11462
dup_immediate(vform, scratch, unsigned_imm);
11463
umin(vform, zd, zd, scratch);
11464
break;
11465
default:
11466
VIXL_UNIMPLEMENTED();
11467
break;
11468
}
11469
}
11470
11471
void Simulator::VisitSVEIntCompareScalarCountAndLimit(
11472
const Instruction* instr) {
11473
unsigned rn_code = instr->GetRn();
11474
unsigned rm_code = instr->GetRm();
11475
SimPRegister& pd = ReadPRegister(instr->GetPd());
11476
VectorFormat vform = instr->GetSVEVectorFormat();
11477
11478
bool is_64_bit = instr->ExtractBit(12) == 1;
11479
int rsize = is_64_bit ? kXRegSize : kWRegSize;
11480
uint64_t mask = is_64_bit ? kXRegMask : kWRegMask;
11481
11482
uint64_t usrc1 = ReadXRegister(rn_code);
11483
int64_t ssrc2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
11484
uint64_t usrc2 = ssrc2 & mask;
11485
11486
bool reverse = (form_hash_ == "whilege_p_p_rr"_h) ||
11487
(form_hash_ == "whilegt_p_p_rr"_h) ||
11488
(form_hash_ == "whilehi_p_p_rr"_h) ||
11489
(form_hash_ == "whilehs_p_p_rr"_h);
11490
11491
int lane_count = LaneCountFromFormat(vform);
11492
bool last = true;
11493
for (int i = 0; i < lane_count; i++) {
11494
usrc1 &= mask;
11495
int64_t ssrc1 = ExtractSignedBitfield64(rsize - 1, 0, usrc1);
11496
11497
bool cond = false;
11498
switch (form_hash_) {
11499
case "whilele_p_p_rr"_h:
11500
cond = ssrc1 <= ssrc2;
11501
break;
11502
case "whilelo_p_p_rr"_h:
11503
cond = usrc1 < usrc2;
11504
break;
11505
case "whilels_p_p_rr"_h:
11506
cond = usrc1 <= usrc2;
11507
break;
11508
case "whilelt_p_p_rr"_h:
11509
cond = ssrc1 < ssrc2;
11510
break;
11511
case "whilege_p_p_rr"_h:
11512
cond = ssrc1 >= ssrc2;
11513
break;
11514
case "whilegt_p_p_rr"_h:
11515
cond = ssrc1 > ssrc2;
11516
break;
11517
case "whilehi_p_p_rr"_h:
11518
cond = usrc1 > usrc2;
11519
break;
11520
case "whilehs_p_p_rr"_h:
11521
cond = usrc1 >= usrc2;
11522
break;
11523
default:
11524
VIXL_UNIMPLEMENTED();
11525
break;
11526
}
11527
last = last && cond;
11528
LogicPRegister dst(pd);
11529
int lane = reverse ? ((lane_count - 1) - i) : i;
11530
dst.SetActive(vform, lane, last);
11531
usrc1 += reverse ? -1 : 1;
11532
}
11533
11534
PredTest(vform, GetPTrue(), pd);
11535
LogSystemRegister(NZCV);
11536
}
11537
11538
void Simulator::VisitSVEConditionallyTerminateScalars(
11539
const Instruction* instr) {
11540
unsigned rn_code = instr->GetRn();
11541
unsigned rm_code = instr->GetRm();
11542
bool is_64_bit = instr->ExtractBit(22) == 1;
11543
uint64_t src1 = is_64_bit ? ReadXRegister(rn_code) : ReadWRegister(rn_code);
11544
uint64_t src2 = is_64_bit ? ReadXRegister(rm_code) : ReadWRegister(rm_code);
11545
bool term = false;
11546
switch (instr->Mask(SVEConditionallyTerminateScalarsMask)) {
11547
case CTERMEQ_rr:
11548
term = src1 == src2;
11549
break;
11550
case CTERMNE_rr:
11551
term = src1 != src2;
11552
break;
11553
default:
11554
VIXL_UNIMPLEMENTED();
11555
break;
11556
}
11557
ReadNzcv().SetN(term ? 1 : 0);
11558
ReadNzcv().SetV(term ? 0 : !ReadC());
11559
LogSystemRegister(NZCV);
11560
}
11561
11562
void Simulator::VisitSVEIntCompareSignedImm(const Instruction* instr) {
11563
bool commute_inputs = false;
11564
Condition cond = al;
11565
switch (instr->Mask(SVEIntCompareSignedImmMask)) {
11566
case CMPEQ_p_p_zi:
11567
cond = eq;
11568
break;
11569
case CMPGE_p_p_zi:
11570
cond = ge;
11571
break;
11572
case CMPGT_p_p_zi:
11573
cond = gt;
11574
break;
11575
case CMPLE_p_p_zi:
11576
cond = ge;
11577
commute_inputs = true;
11578
break;
11579
case CMPLT_p_p_zi:
11580
cond = gt;
11581
commute_inputs = true;
11582
break;
11583
case CMPNE_p_p_zi:
11584
cond = ne;
11585
break;
11586
default:
11587
VIXL_UNIMPLEMENTED();
11588
break;
11589
}
11590
11591
VectorFormat vform = instr->GetSVEVectorFormat();
11592
SimVRegister src2;
11593
dup_immediate(vform,
11594
src2,
11595
ExtractSignedBitfield64(4, 0, instr->ExtractBits(20, 16)));
11596
SVEIntCompareVectorsHelper(cond,
11597
vform,
11598
ReadPRegister(instr->GetPd()),
11599
ReadPRegister(instr->GetPgLow8()),
11600
commute_inputs ? src2
11601
: ReadVRegister(instr->GetRn()),
11602
commute_inputs ? ReadVRegister(instr->GetRn())
11603
: src2);
11604
}
11605
11606
void Simulator::VisitSVEIntCompareUnsignedImm(const Instruction* instr) {
11607
bool commute_inputs = false;
11608
Condition cond = al;
11609
switch (instr->Mask(SVEIntCompareUnsignedImmMask)) {
11610
case CMPHI_p_p_zi:
11611
cond = hi;
11612
break;
11613
case CMPHS_p_p_zi:
11614
cond = hs;
11615
break;
11616
case CMPLO_p_p_zi:
11617
cond = hi;
11618
commute_inputs = true;
11619
break;
11620
case CMPLS_p_p_zi:
11621
cond = hs;
11622
commute_inputs = true;
11623
break;
11624
default:
11625
VIXL_UNIMPLEMENTED();
11626
break;
11627
}
11628
11629
VectorFormat vform = instr->GetSVEVectorFormat();
11630
SimVRegister src2;
11631
dup_immediate(vform, src2, instr->ExtractBits(20, 14));
11632
SVEIntCompareVectorsHelper(cond,
11633
vform,
11634
ReadPRegister(instr->GetPd()),
11635
ReadPRegister(instr->GetPgLow8()),
11636
commute_inputs ? src2
11637
: ReadVRegister(instr->GetRn()),
11638
commute_inputs ? ReadVRegister(instr->GetRn())
11639
: src2);
11640
}
11641
11642
void Simulator::VisitSVEIntCompareVectors(const Instruction* instr) {
11643
Instr op = instr->Mask(SVEIntCompareVectorsMask);
11644
bool is_wide_elements = false;
11645
switch (op) {
11646
case CMPEQ_p_p_zw:
11647
case CMPGE_p_p_zw:
11648
case CMPGT_p_p_zw:
11649
case CMPHI_p_p_zw:
11650
case CMPHS_p_p_zw:
11651
case CMPLE_p_p_zw:
11652
case CMPLO_p_p_zw:
11653
case CMPLS_p_p_zw:
11654
case CMPLT_p_p_zw:
11655
case CMPNE_p_p_zw:
11656
is_wide_elements = true;
11657
break;
11658
}
11659
11660
Condition cond;
11661
switch (op) {
11662
case CMPEQ_p_p_zw:
11663
case CMPEQ_p_p_zz:
11664
cond = eq;
11665
break;
11666
case CMPGE_p_p_zw:
11667
case CMPGE_p_p_zz:
11668
cond = ge;
11669
break;
11670
case CMPGT_p_p_zw:
11671
case CMPGT_p_p_zz:
11672
cond = gt;
11673
break;
11674
case CMPHI_p_p_zw:
11675
case CMPHI_p_p_zz:
11676
cond = hi;
11677
break;
11678
case CMPHS_p_p_zw:
11679
case CMPHS_p_p_zz:
11680
cond = hs;
11681
break;
11682
case CMPNE_p_p_zw:
11683
case CMPNE_p_p_zz:
11684
cond = ne;
11685
break;
11686
case CMPLE_p_p_zw:
11687
cond = le;
11688
break;
11689
case CMPLO_p_p_zw:
11690
cond = lo;
11691
break;
11692
case CMPLS_p_p_zw:
11693
cond = ls;
11694
break;
11695
case CMPLT_p_p_zw:
11696
cond = lt;
11697
break;
11698
default:
11699
VIXL_UNIMPLEMENTED();
11700
cond = al;
11701
break;
11702
}
11703
11704
SVEIntCompareVectorsHelper(cond,
11705
instr->GetSVEVectorFormat(),
11706
ReadPRegister(instr->GetPd()),
11707
ReadPRegister(instr->GetPgLow8()),
11708
ReadVRegister(instr->GetRn()),
11709
ReadVRegister(instr->GetRm()),
11710
is_wide_elements);
11711
}
11712
11713
void Simulator::VisitSVEFPExponentialAccelerator(const Instruction* instr) {
11714
VectorFormat vform = instr->GetSVEVectorFormat();
11715
SimVRegister& zd = ReadVRegister(instr->GetRd());
11716
SimVRegister& zn = ReadVRegister(instr->GetRn());
11717
11718
VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11719
(vform == kFormatVnD));
11720
11721
switch (instr->Mask(SVEFPExponentialAcceleratorMask)) {
11722
case FEXPA_z_z:
11723
fexpa(vform, zd, zn);
11724
break;
11725
default:
11726
VIXL_UNIMPLEMENTED();
11727
break;
11728
}
11729
}
11730
11731
void Simulator::VisitSVEFPTrigSelectCoefficient(const Instruction* instr) {
11732
VectorFormat vform = instr->GetSVEVectorFormat();
11733
SimVRegister& zd = ReadVRegister(instr->GetRd());
11734
SimVRegister& zn = ReadVRegister(instr->GetRn());
11735
SimVRegister& zm = ReadVRegister(instr->GetRm());
11736
11737
VIXL_ASSERT((vform == kFormatVnH) || (vform == kFormatVnS) ||
11738
(vform == kFormatVnD));
11739
11740
switch (instr->Mask(SVEFPTrigSelectCoefficientMask)) {
11741
case FTSSEL_z_zz:
11742
ftssel(vform, zd, zn, zm);
11743
break;
11744
default:
11745
VIXL_UNIMPLEMENTED();
11746
break;
11747
}
11748
}
11749
11750
void Simulator::VisitSVEConstructivePrefix_Unpredicated(
11751
const Instruction* instr) {
11752
SimVRegister& zd = ReadVRegister(instr->GetRd());
11753
SimVRegister& zn = ReadVRegister(instr->GetRn());
11754
11755
switch (instr->Mask(SVEConstructivePrefix_UnpredicatedMask)) {
11756
case MOVPRFX_z_z:
11757
mov(kFormatVnD, zd, zn); // The lane size is arbitrary.
11758
break;
11759
default:
11760
VIXL_UNIMPLEMENTED();
11761
break;
11762
}
11763
}
11764
11765
void Simulator::VisitSVEIntMulAddPredicated(const Instruction* instr) {
11766
VectorFormat vform = instr->GetSVEVectorFormat();
11767
11768
SimVRegister& zd = ReadVRegister(instr->GetRd());
11769
SimVRegister& zm = ReadVRegister(instr->GetRm());
11770
11771
SimVRegister result;
11772
switch (instr->Mask(SVEIntMulAddPredicatedMask)) {
11773
case MLA_z_p_zzz:
11774
mla(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
11775
break;
11776
case MLS_z_p_zzz:
11777
mls(vform, result, zd, ReadVRegister(instr->GetRn()), zm);
11778
break;
11779
case MAD_z_p_zzz:
11780
// 'za' is encoded in 'Rn'.
11781
mla(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
11782
break;
11783
case MSB_z_p_zzz: {
11784
// 'za' is encoded in 'Rn'.
11785
mls(vform, result, ReadVRegister(instr->GetRn()), zd, zm);
11786
break;
11787
}
11788
default:
11789
VIXL_UNIMPLEMENTED();
11790
break;
11791
}
11792
mov_merging(vform, zd, ReadPRegister(instr->GetPgLow8()), result);
11793
}
11794
11795
void Simulator::VisitSVEIntMulAddUnpredicated(const Instruction* instr) {
11796
VectorFormat vform = instr->GetSVEVectorFormat();
11797
SimVRegister& zda = ReadVRegister(instr->GetRd());
11798
SimVRegister& zn = ReadVRegister(instr->GetRn());
11799
SimVRegister& zm = ReadVRegister(instr->GetRm());
11800
11801
switch (form_hash_) {
11802
case "sdot_z_zzz"_h:
11803
sdot(vform, zda, zn, zm);
11804
break;
11805
case "udot_z_zzz"_h:
11806
udot(vform, zda, zn, zm);
11807
break;
11808
case "usdot_z_zzz_s"_h:
11809
usdot(vform, zda, zn, zm);
11810
break;
11811
default:
11812
VIXL_UNIMPLEMENTED();
11813
break;
11814
}
11815
}
11816
11817
void Simulator::VisitSVEMovprfx(const Instruction* instr) {
11818
VectorFormat vform = instr->GetSVEVectorFormat();
11819
SimVRegister& zn = ReadVRegister(instr->GetRn());
11820
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11821
SimVRegister& zd = ReadVRegister(instr->GetRd());
11822
11823
switch (instr->Mask(SVEMovprfxMask)) {
11824
case MOVPRFX_z_p_z:
11825
if (instr->ExtractBit(16)) {
11826
mov_merging(vform, zd, pg, zn);
11827
} else {
11828
mov_zeroing(vform, zd, pg, zn);
11829
}
11830
break;
11831
default:
11832
VIXL_UNIMPLEMENTED();
11833
break;
11834
}
11835
}
11836
11837
void Simulator::VisitSVEIntReduction(const Instruction* instr) {
11838
VectorFormat vform = instr->GetSVEVectorFormat();
11839
SimVRegister& vd = ReadVRegister(instr->GetRd());
11840
SimVRegister& zn = ReadVRegister(instr->GetRn());
11841
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11842
11843
if (instr->Mask(SVEIntReductionLogicalFMask) == SVEIntReductionLogicalFixed) {
11844
switch (instr->Mask(SVEIntReductionLogicalMask)) {
11845
case ANDV_r_p_z:
11846
andv(vform, vd, pg, zn);
11847
break;
11848
case EORV_r_p_z:
11849
eorv(vform, vd, pg, zn);
11850
break;
11851
case ORV_r_p_z:
11852
orv(vform, vd, pg, zn);
11853
break;
11854
default:
11855
VIXL_UNIMPLEMENTED();
11856
break;
11857
}
11858
} else {
11859
switch (instr->Mask(SVEIntReductionMask)) {
11860
case SADDV_r_p_z:
11861
saddv(vform, vd, pg, zn);
11862
break;
11863
case SMAXV_r_p_z:
11864
smaxv(vform, vd, pg, zn);
11865
break;
11866
case SMINV_r_p_z:
11867
sminv(vform, vd, pg, zn);
11868
break;
11869
case UADDV_r_p_z:
11870
uaddv(vform, vd, pg, zn);
11871
break;
11872
case UMAXV_r_p_z:
11873
umaxv(vform, vd, pg, zn);
11874
break;
11875
case UMINV_r_p_z:
11876
uminv(vform, vd, pg, zn);
11877
break;
11878
default:
11879
VIXL_UNIMPLEMENTED();
11880
break;
11881
}
11882
}
11883
}
11884
11885
void Simulator::VisitSVEIntUnaryArithmeticPredicated(const Instruction* instr) {
11886
VectorFormat vform = instr->GetSVEVectorFormat();
11887
SimVRegister& zn = ReadVRegister(instr->GetRn());
11888
11889
SimVRegister result;
11890
switch (instr->Mask(SVEIntUnaryArithmeticPredicatedMask)) {
11891
case ABS_z_p_z:
11892
abs(vform, result, zn);
11893
break;
11894
case CLS_z_p_z:
11895
cls(vform, result, zn);
11896
break;
11897
case CLZ_z_p_z:
11898
clz(vform, result, zn);
11899
break;
11900
case CNOT_z_p_z:
11901
cnot(vform, result, zn);
11902
break;
11903
case CNT_z_p_z:
11904
cnt(vform, result, zn);
11905
break;
11906
case FABS_z_p_z:
11907
fabs_(vform, result, zn);
11908
break;
11909
case FNEG_z_p_z:
11910
fneg(vform, result, zn);
11911
break;
11912
case NEG_z_p_z:
11913
neg(vform, result, zn);
11914
break;
11915
case NOT_z_p_z:
11916
not_(vform, result, zn);
11917
break;
11918
case SXTB_z_p_z:
11919
case SXTH_z_p_z:
11920
case SXTW_z_p_z:
11921
sxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
11922
break;
11923
case UXTB_z_p_z:
11924
case UXTH_z_p_z:
11925
case UXTW_z_p_z:
11926
uxt(vform, result, zn, (kBitsPerByte << instr->ExtractBits(18, 17)));
11927
break;
11928
default:
11929
VIXL_UNIMPLEMENTED();
11930
break;
11931
}
11932
11933
SimVRegister& zd = ReadVRegister(instr->GetRd());
11934
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
11935
mov_merging(vform, zd, pg, result);
11936
}
11937
11938
void Simulator::VisitSVECopyFPImm_Predicated(const Instruction* instr) {
11939
// There is only one instruction in this group.
11940
VIXL_ASSERT(instr->Mask(SVECopyFPImm_PredicatedMask) == FCPY_z_p_i);
11941
11942
VectorFormat vform = instr->GetSVEVectorFormat();
11943
SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
11944
SimVRegister& zd = ReadVRegister(instr->GetRd());
11945
11946
if (vform == kFormatVnB) VIXL_UNIMPLEMENTED();
11947
11948
SimVRegister result;
11949
switch (instr->Mask(SVECopyFPImm_PredicatedMask)) {
11950
case FCPY_z_p_i: {
11951
int imm8 = instr->ExtractBits(12, 5);
11952
uint64_t value = FPToRawbitsWithSize(LaneSizeInBitsFromFormat(vform),
11953
Instruction::Imm8ToFP64(imm8));
11954
dup_immediate(vform, result, value);
11955
break;
11956
}
11957
default:
11958
VIXL_UNIMPLEMENTED();
11959
break;
11960
}
11961
mov_merging(vform, zd, pg, result);
11962
}
11963
11964
void Simulator::VisitSVEIntAddSubtractImm_Unpredicated(
11965
const Instruction* instr) {
11966
VectorFormat vform = instr->GetSVEVectorFormat();
11967
SimVRegister& zd = ReadVRegister(instr->GetRd());
11968
SimVRegister scratch;
11969
11970
uint64_t imm = instr->GetImmSVEIntWideUnsigned();
11971
imm <<= instr->ExtractBit(13) * 8;
11972
11973
switch (instr->Mask(SVEIntAddSubtractImm_UnpredicatedMask)) {
11974
case ADD_z_zi:
11975
add_uint(vform, zd, zd, imm);
11976
break;
11977
case SQADD_z_zi:
11978
add_uint(vform, zd, zd, imm).SignedSaturate(vform);
11979
break;
11980
case SQSUB_z_zi:
11981
sub_uint(vform, zd, zd, imm).SignedSaturate(vform);
11982
break;
11983
case SUBR_z_zi:
11984
dup_immediate(vform, scratch, imm);
11985
sub(vform, zd, scratch, zd);
11986
break;
11987
case SUB_z_zi:
11988
sub_uint(vform, zd, zd, imm);
11989
break;
11990
case UQADD_z_zi:
11991
add_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11992
break;
11993
case UQSUB_z_zi:
11994
sub_uint(vform, zd, zd, imm).UnsignedSaturate(vform);
11995
break;
11996
default:
11997
break;
11998
}
11999
}
12000
12001
void Simulator::VisitSVEBroadcastIntImm_Unpredicated(const Instruction* instr) {
12002
SimVRegister& zd = ReadVRegister(instr->GetRd());
12003
12004
VectorFormat format = instr->GetSVEVectorFormat();
12005
int64_t imm = instr->GetImmSVEIntWideSigned();
12006
int shift = instr->ExtractBit(13) * 8;
12007
imm *= 1 << shift;
12008
12009
switch (instr->Mask(SVEBroadcastIntImm_UnpredicatedMask)) {
12010
case DUP_z_i:
12011
// The encoding of byte-sized lanes with lsl #8 is undefined.
12012
if ((format == kFormatVnB) && (shift == 8)) {
12013
VIXL_UNIMPLEMENTED();
12014
} else {
12015
dup_immediate(format, zd, imm);
12016
}
12017
break;
12018
default:
12019
VIXL_UNIMPLEMENTED();
12020
break;
12021
}
12022
}
12023
12024
void Simulator::VisitSVEBroadcastFPImm_Unpredicated(const Instruction* instr) {
12025
VectorFormat vform = instr->GetSVEVectorFormat();
12026
SimVRegister& zd = ReadVRegister(instr->GetRd());
12027
12028
switch (instr->Mask(SVEBroadcastFPImm_UnpredicatedMask)) {
12029
case FDUP_z_i:
12030
switch (vform) {
12031
case kFormatVnH:
12032
dup_immediate(vform, zd, Float16ToRawbits(instr->GetSVEImmFP16()));
12033
break;
12034
case kFormatVnS:
12035
dup_immediate(vform, zd, FloatToRawbits(instr->GetSVEImmFP32()));
12036
break;
12037
case kFormatVnD:
12038
dup_immediate(vform, zd, DoubleToRawbits(instr->GetSVEImmFP64()));
12039
break;
12040
default:
12041
VIXL_UNIMPLEMENTED();
12042
}
12043
break;
12044
default:
12045
VIXL_UNIMPLEMENTED();
12046
break;
12047
}
12048
}
12049
12050
void Simulator::VisitSVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets(
12051
const Instruction* instr) {
12052
switch (instr->Mask(
12053
SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsetsMask)) {
12054
case LD1H_z_p_bz_s_x32_scaled:
12055
case LD1SH_z_p_bz_s_x32_scaled:
12056
case LDFF1H_z_p_bz_s_x32_scaled:
12057
case LDFF1SH_z_p_bz_s_x32_scaled:
12058
break;
12059
default:
12060
VIXL_UNIMPLEMENTED();
12061
break;
12062
}
12063
12064
SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
12065
SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
12066
}
12067
12068
void Simulator::VisitSVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets(
12069
const Instruction* instr) {
12070
switch (instr->Mask(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsetsMask)) {
12071
case LD1B_z_p_bz_s_x32_unscaled:
12072
case LD1H_z_p_bz_s_x32_unscaled:
12073
case LD1SB_z_p_bz_s_x32_unscaled:
12074
case LD1SH_z_p_bz_s_x32_unscaled:
12075
case LD1W_z_p_bz_s_x32_unscaled:
12076
case LDFF1B_z_p_bz_s_x32_unscaled:
12077
case LDFF1H_z_p_bz_s_x32_unscaled:
12078
case LDFF1SB_z_p_bz_s_x32_unscaled:
12079
case LDFF1SH_z_p_bz_s_x32_unscaled:
12080
case LDFF1W_z_p_bz_s_x32_unscaled:
12081
break;
12082
default:
12083
VIXL_UNIMPLEMENTED();
12084
break;
12085
}
12086
12087
SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
12088
SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
12089
}
12090
12091
void Simulator::VisitSVE32BitGatherLoad_VectorPlusImm(
12092
const Instruction* instr) {
12093
switch (instr->Mask(SVE32BitGatherLoad_VectorPlusImmMask)) {
12094
case LD1B_z_p_ai_s:
12095
VIXL_UNIMPLEMENTED();
12096
break;
12097
case LD1H_z_p_ai_s:
12098
VIXL_UNIMPLEMENTED();
12099
break;
12100
case LD1SB_z_p_ai_s:
12101
VIXL_UNIMPLEMENTED();
12102
break;
12103
case LD1SH_z_p_ai_s:
12104
VIXL_UNIMPLEMENTED();
12105
break;
12106
case LD1W_z_p_ai_s:
12107
VIXL_UNIMPLEMENTED();
12108
break;
12109
case LDFF1B_z_p_ai_s:
12110
VIXL_UNIMPLEMENTED();
12111
break;
12112
case LDFF1H_z_p_ai_s:
12113
VIXL_UNIMPLEMENTED();
12114
break;
12115
case LDFF1SB_z_p_ai_s:
12116
VIXL_UNIMPLEMENTED();
12117
break;
12118
case LDFF1SH_z_p_ai_s:
12119
VIXL_UNIMPLEMENTED();
12120
break;
12121
case LDFF1W_z_p_ai_s:
12122
VIXL_UNIMPLEMENTED();
12123
break;
12124
default:
12125
VIXL_UNIMPLEMENTED();
12126
break;
12127
}
12128
}
12129
12130
void Simulator::VisitSVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets(
12131
const Instruction* instr) {
12132
switch (
12133
instr->Mask(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsetsMask)) {
12134
case LD1W_z_p_bz_s_x32_scaled:
12135
case LDFF1W_z_p_bz_s_x32_scaled:
12136
break;
12137
default:
12138
VIXL_UNIMPLEMENTED();
12139
break;
12140
}
12141
12142
SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
12143
SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnS, mod);
12144
}
12145
12146
void Simulator::VisitSVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets(
12147
const Instruction* instr) {
12148
switch (
12149
instr->Mask(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsetsMask)) {
12150
// Ignore prefetch hint instructions.
12151
case PRFB_i_p_bz_s_x32_scaled:
12152
case PRFD_i_p_bz_s_x32_scaled:
12153
case PRFH_i_p_bz_s_x32_scaled:
12154
case PRFW_i_p_bz_s_x32_scaled:
12155
break;
12156
default:
12157
VIXL_UNIMPLEMENTED();
12158
break;
12159
}
12160
}
12161
12162
void Simulator::VisitSVE32BitGatherPrefetch_VectorPlusImm(
12163
const Instruction* instr) {
12164
switch (instr->Mask(SVE32BitGatherPrefetch_VectorPlusImmMask)) {
12165
// Ignore prefetch hint instructions.
12166
case PRFB_i_p_ai_s:
12167
case PRFD_i_p_ai_s:
12168
case PRFH_i_p_ai_s:
12169
case PRFW_i_p_ai_s:
12170
break;
12171
default:
12172
VIXL_UNIMPLEMENTED();
12173
break;
12174
}
12175
}
12176
12177
void Simulator::VisitSVEContiguousPrefetch_ScalarPlusImm(
12178
const Instruction* instr) {
12179
switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusImmMask)) {
12180
// Ignore prefetch hint instructions.
12181
case PRFB_i_p_bi_s:
12182
case PRFD_i_p_bi_s:
12183
case PRFH_i_p_bi_s:
12184
case PRFW_i_p_bi_s:
12185
break;
12186
default:
12187
VIXL_UNIMPLEMENTED();
12188
break;
12189
}
12190
}
12191
12192
void Simulator::VisitSVEContiguousPrefetch_ScalarPlusScalar(
12193
const Instruction* instr) {
12194
switch (instr->Mask(SVEContiguousPrefetch_ScalarPlusScalarMask)) {
12195
// Ignore prefetch hint instructions.
12196
case PRFB_i_p_br_s:
12197
case PRFD_i_p_br_s:
12198
case PRFH_i_p_br_s:
12199
case PRFW_i_p_br_s:
12200
if (instr->GetRm() == kZeroRegCode) {
12201
VIXL_UNIMPLEMENTED();
12202
}
12203
break;
12204
default:
12205
VIXL_UNIMPLEMENTED();
12206
break;
12207
}
12208
}
12209
12210
void Simulator::VisitSVELoadAndBroadcastElement(const Instruction* instr) {
12211
bool is_signed;
12212
switch (instr->Mask(SVELoadAndBroadcastElementMask)) {
12213
case LD1RB_z_p_bi_u8:
12214
case LD1RB_z_p_bi_u16:
12215
case LD1RB_z_p_bi_u32:
12216
case LD1RB_z_p_bi_u64:
12217
case LD1RH_z_p_bi_u16:
12218
case LD1RH_z_p_bi_u32:
12219
case LD1RH_z_p_bi_u64:
12220
case LD1RW_z_p_bi_u32:
12221
case LD1RW_z_p_bi_u64:
12222
case LD1RD_z_p_bi_u64:
12223
is_signed = false;
12224
break;
12225
case LD1RSB_z_p_bi_s16:
12226
case LD1RSB_z_p_bi_s32:
12227
case LD1RSB_z_p_bi_s64:
12228
case LD1RSH_z_p_bi_s32:
12229
case LD1RSH_z_p_bi_s64:
12230
case LD1RSW_z_p_bi_s64:
12231
is_signed = true;
12232
break;
12233
default:
12234
// This encoding group is complete, so no other values should be possible.
12235
VIXL_UNREACHABLE();
12236
is_signed = false;
12237
break;
12238
}
12239
12240
int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12241
int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed, 13);
12242
VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12243
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12244
uint64_t offset = instr->ExtractBits(21, 16) << msize_in_bytes_log2;
12245
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset;
12246
VectorFormat unpack_vform =
12247
SVEFormatFromLaneSizeInBytesLog2(msize_in_bytes_log2);
12248
SimVRegister temp;
12249
if (!ld1r(vform, unpack_vform, temp, base, is_signed)) return;
12250
mov_zeroing(vform,
12251
ReadVRegister(instr->GetRt()),
12252
ReadPRegister(instr->GetPgLow8()),
12253
temp);
12254
}
12255
12256
void Simulator::VisitSVELoadPredicateRegister(const Instruction* instr) {
12257
switch (instr->Mask(SVELoadPredicateRegisterMask)) {
12258
case LDR_p_bi: {
12259
SimPRegister& pt = ReadPRegister(instr->GetPt());
12260
int pl = GetPredicateLengthInBytes();
12261
int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12262
uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12263
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12264
uint64_t address = base + multiplier * pl;
12265
for (int i = 0; i < pl; i++) {
12266
VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address + i));
12267
pt.Insert(i, value);
12268
}
12269
LogPRead(instr->GetPt(), address);
12270
break;
12271
}
12272
default:
12273
VIXL_UNIMPLEMENTED();
12274
break;
12275
}
12276
}
12277
12278
void Simulator::VisitSVELoadVectorRegister(const Instruction* instr) {
12279
switch (instr->Mask(SVELoadVectorRegisterMask)) {
12280
case LDR_z_bi: {
12281
SimVRegister& zt = ReadVRegister(instr->GetRt());
12282
int vl = GetVectorLengthInBytes();
12283
int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
12284
uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
12285
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12286
uint64_t address = base + multiplier * vl;
12287
for (int i = 0; i < vl; i++) {
12288
VIXL_DEFINE_OR_RETURN(value, MemRead<uint8_t>(address + i));
12289
zt.Insert(i, value);
12290
}
12291
LogZRead(instr->GetRt(), address);
12292
break;
12293
}
12294
default:
12295
VIXL_UNIMPLEMENTED();
12296
break;
12297
}
12298
}
12299
12300
void Simulator::VisitSVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets(
12301
const Instruction* instr) {
12302
switch (instr->Mask(
12303
SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsetsMask)) {
12304
case LD1D_z_p_bz_d_x32_scaled:
12305
case LD1H_z_p_bz_d_x32_scaled:
12306
case LD1SH_z_p_bz_d_x32_scaled:
12307
case LD1SW_z_p_bz_d_x32_scaled:
12308
case LD1W_z_p_bz_d_x32_scaled:
12309
case LDFF1H_z_p_bz_d_x32_scaled:
12310
case LDFF1W_z_p_bz_d_x32_scaled:
12311
case LDFF1D_z_p_bz_d_x32_scaled:
12312
case LDFF1SH_z_p_bz_d_x32_scaled:
12313
case LDFF1SW_z_p_bz_d_x32_scaled:
12314
break;
12315
default:
12316
VIXL_UNIMPLEMENTED();
12317
break;
12318
}
12319
12320
SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
12321
SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
12322
}
12323
12324
void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitScaledOffsets(
12325
const Instruction* instr) {
12326
switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsetsMask)) {
12327
case LD1D_z_p_bz_d_64_scaled:
12328
case LD1H_z_p_bz_d_64_scaled:
12329
case LD1SH_z_p_bz_d_64_scaled:
12330
case LD1SW_z_p_bz_d_64_scaled:
12331
case LD1W_z_p_bz_d_64_scaled:
12332
case LDFF1H_z_p_bz_d_64_scaled:
12333
case LDFF1W_z_p_bz_d_64_scaled:
12334
case LDFF1D_z_p_bz_d_64_scaled:
12335
case LDFF1SH_z_p_bz_d_64_scaled:
12336
case LDFF1SW_z_p_bz_d_64_scaled:
12337
break;
12338
default:
12339
VIXL_UNIMPLEMENTED();
12340
break;
12341
}
12342
12343
SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, SVE_LSL);
12344
}
12345
12346
void Simulator::VisitSVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets(
12347
const Instruction* instr) {
12348
switch (instr->Mask(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsetsMask)) {
12349
case LD1B_z_p_bz_d_64_unscaled:
12350
case LD1D_z_p_bz_d_64_unscaled:
12351
case LD1H_z_p_bz_d_64_unscaled:
12352
case LD1SB_z_p_bz_d_64_unscaled:
12353
case LD1SH_z_p_bz_d_64_unscaled:
12354
case LD1SW_z_p_bz_d_64_unscaled:
12355
case LD1W_z_p_bz_d_64_unscaled:
12356
case LDFF1B_z_p_bz_d_64_unscaled:
12357
case LDFF1D_z_p_bz_d_64_unscaled:
12358
case LDFF1H_z_p_bz_d_64_unscaled:
12359
case LDFF1SB_z_p_bz_d_64_unscaled:
12360
case LDFF1SH_z_p_bz_d_64_unscaled:
12361
case LDFF1SW_z_p_bz_d_64_unscaled:
12362
case LDFF1W_z_p_bz_d_64_unscaled:
12363
break;
12364
default:
12365
VIXL_UNIMPLEMENTED();
12366
break;
12367
}
12368
12369
SVEGatherLoadScalarPlusVectorHelper(instr,
12370
kFormatVnD,
12371
NO_SVE_OFFSET_MODIFIER);
12372
}
12373
12374
void Simulator::VisitSVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets(
12375
const Instruction* instr) {
12376
switch (instr->Mask(
12377
SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
12378
case LD1B_z_p_bz_d_x32_unscaled:
12379
case LD1D_z_p_bz_d_x32_unscaled:
12380
case LD1H_z_p_bz_d_x32_unscaled:
12381
case LD1SB_z_p_bz_d_x32_unscaled:
12382
case LD1SH_z_p_bz_d_x32_unscaled:
12383
case LD1SW_z_p_bz_d_x32_unscaled:
12384
case LD1W_z_p_bz_d_x32_unscaled:
12385
case LDFF1B_z_p_bz_d_x32_unscaled:
12386
case LDFF1H_z_p_bz_d_x32_unscaled:
12387
case LDFF1W_z_p_bz_d_x32_unscaled:
12388
case LDFF1D_z_p_bz_d_x32_unscaled:
12389
case LDFF1SB_z_p_bz_d_x32_unscaled:
12390
case LDFF1SH_z_p_bz_d_x32_unscaled:
12391
case LDFF1SW_z_p_bz_d_x32_unscaled:
12392
break;
12393
default:
12394
VIXL_UNIMPLEMENTED();
12395
break;
12396
}
12397
12398
SVEOffsetModifier mod = (instr->ExtractBit(22) == 1) ? SVE_SXTW : SVE_UXTW;
12399
SVEGatherLoadScalarPlusVectorHelper(instr, kFormatVnD, mod);
12400
}
12401
12402
void Simulator::VisitSVE64BitGatherLoad_VectorPlusImm(
12403
const Instruction* instr) {
12404
switch (instr->Mask(SVE64BitGatherLoad_VectorPlusImmMask)) {
12405
case LD1B_z_p_ai_d:
12406
case LD1D_z_p_ai_d:
12407
case LD1H_z_p_ai_d:
12408
case LD1SB_z_p_ai_d:
12409
case LD1SH_z_p_ai_d:
12410
case LD1SW_z_p_ai_d:
12411
case LD1W_z_p_ai_d:
12412
case LDFF1B_z_p_ai_d:
12413
case LDFF1D_z_p_ai_d:
12414
case LDFF1H_z_p_ai_d:
12415
case LDFF1SB_z_p_ai_d:
12416
case LDFF1SH_z_p_ai_d:
12417
case LDFF1SW_z_p_ai_d:
12418
case LDFF1W_z_p_ai_d:
12419
break;
12420
default:
12421
VIXL_UNIMPLEMENTED();
12422
break;
12423
}
12424
bool is_signed = instr->ExtractBit(14) == 0;
12425
bool is_ff = instr->ExtractBit(13) == 1;
12426
// Note that these instructions don't use the Dtype encoding.
12427
int msize_in_bytes_log2 = instr->ExtractBits(24, 23);
12428
uint64_t imm = instr->ExtractBits(20, 16) << msize_in_bytes_log2;
12429
LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
12430
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12431
if (is_ff) {
12432
VIXL_UNIMPLEMENTED();
12433
} else {
12434
SVEStructuredLoadHelper(kFormatVnD,
12435
ReadPRegister(instr->GetPgLow8()),
12436
instr->GetRt(),
12437
addr,
12438
is_signed);
12439
}
12440
}
12441
12442
void Simulator::VisitSVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets(
12443
const Instruction* instr) {
12444
switch (
12445
instr->Mask(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsetsMask)) {
12446
// Ignore prefetch hint instructions.
12447
case PRFB_i_p_bz_d_64_scaled:
12448
case PRFD_i_p_bz_d_64_scaled:
12449
case PRFH_i_p_bz_d_64_scaled:
12450
case PRFW_i_p_bz_d_64_scaled:
12451
break;
12452
default:
12453
VIXL_UNIMPLEMENTED();
12454
break;
12455
}
12456
}
12457
12458
void Simulator::
12459
VisitSVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets(
12460
const Instruction* instr) {
12461
switch (instr->Mask(
12462
SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
12463
// Ignore prefetch hint instructions.
12464
case PRFB_i_p_bz_d_x32_scaled:
12465
case PRFD_i_p_bz_d_x32_scaled:
12466
case PRFH_i_p_bz_d_x32_scaled:
12467
case PRFW_i_p_bz_d_x32_scaled:
12468
break;
12469
default:
12470
VIXL_UNIMPLEMENTED();
12471
break;
12472
}
12473
}
12474
12475
void Simulator::VisitSVE64BitGatherPrefetch_VectorPlusImm(
12476
const Instruction* instr) {
12477
switch (instr->Mask(SVE64BitGatherPrefetch_VectorPlusImmMask)) {
12478
// Ignore prefetch hint instructions.
12479
case PRFB_i_p_ai_d:
12480
case PRFD_i_p_ai_d:
12481
case PRFH_i_p_ai_d:
12482
case PRFW_i_p_ai_d:
12483
break;
12484
default:
12485
VIXL_UNIMPLEMENTED();
12486
break;
12487
}
12488
}
12489
12490
void Simulator::VisitSVEContiguousFirstFaultLoad_ScalarPlusScalar(
12491
const Instruction* instr) {
12492
bool is_signed;
12493
switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
12494
case LDFF1B_z_p_br_u8:
12495
case LDFF1B_z_p_br_u16:
12496
case LDFF1B_z_p_br_u32:
12497
case LDFF1B_z_p_br_u64:
12498
case LDFF1H_z_p_br_u16:
12499
case LDFF1H_z_p_br_u32:
12500
case LDFF1H_z_p_br_u64:
12501
case LDFF1W_z_p_br_u32:
12502
case LDFF1W_z_p_br_u64:
12503
case LDFF1D_z_p_br_u64:
12504
is_signed = false;
12505
break;
12506
case LDFF1SB_z_p_br_s16:
12507
case LDFF1SB_z_p_br_s32:
12508
case LDFF1SB_z_p_br_s64:
12509
case LDFF1SH_z_p_br_s32:
12510
case LDFF1SH_z_p_br_s64:
12511
case LDFF1SW_z_p_br_s64:
12512
is_signed = true;
12513
break;
12514
default:
12515
// This encoding group is complete, so no other values should be possible.
12516
VIXL_UNREACHABLE();
12517
is_signed = false;
12518
break;
12519
}
12520
12521
int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12522
int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12523
VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12524
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12525
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12526
uint64_t offset = ReadXRegister(instr->GetRm());
12527
offset <<= msize_in_bytes_log2;
12528
LogicSVEAddressVector addr(base + offset);
12529
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12530
SVEFaultTolerantLoadHelper(vform,
12531
ReadPRegister(instr->GetPgLow8()),
12532
instr->GetRt(),
12533
addr,
12534
kSVEFirstFaultLoad,
12535
is_signed);
12536
}
12537
12538
void Simulator::VisitSVEContiguousNonFaultLoad_ScalarPlusImm(
12539
const Instruction* instr) {
12540
bool is_signed = false;
12541
switch (instr->Mask(SVEContiguousNonFaultLoad_ScalarPlusImmMask)) {
12542
case LDNF1B_z_p_bi_u16:
12543
case LDNF1B_z_p_bi_u32:
12544
case LDNF1B_z_p_bi_u64:
12545
case LDNF1B_z_p_bi_u8:
12546
case LDNF1D_z_p_bi_u64:
12547
case LDNF1H_z_p_bi_u16:
12548
case LDNF1H_z_p_bi_u32:
12549
case LDNF1H_z_p_bi_u64:
12550
case LDNF1W_z_p_bi_u32:
12551
case LDNF1W_z_p_bi_u64:
12552
break;
12553
case LDNF1SB_z_p_bi_s16:
12554
case LDNF1SB_z_p_bi_s32:
12555
case LDNF1SB_z_p_bi_s64:
12556
case LDNF1SH_z_p_bi_s32:
12557
case LDNF1SH_z_p_bi_s64:
12558
case LDNF1SW_z_p_bi_s64:
12559
is_signed = true;
12560
break;
12561
default:
12562
VIXL_UNIMPLEMENTED();
12563
break;
12564
}
12565
int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
12566
int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
12567
VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
12568
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
12569
int vl = GetVectorLengthInBytes();
12570
int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
12571
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12572
uint64_t offset =
12573
(instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
12574
LogicSVEAddressVector addr(base + offset);
12575
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12576
SVEFaultTolerantLoadHelper(vform,
12577
ReadPRegister(instr->GetPgLow8()),
12578
instr->GetRt(),
12579
addr,
12580
kSVENonFaultLoad,
12581
is_signed);
12582
}
12583
12584
void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusImm(
12585
const Instruction* instr) {
12586
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12587
VectorFormat vform = kFormatUndefined;
12588
12589
switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusImmMask)) {
12590
case LDNT1B_z_p_bi_contiguous:
12591
vform = kFormatVnB;
12592
break;
12593
case LDNT1D_z_p_bi_contiguous:
12594
vform = kFormatVnD;
12595
break;
12596
case LDNT1H_z_p_bi_contiguous:
12597
vform = kFormatVnH;
12598
break;
12599
case LDNT1W_z_p_bi_contiguous:
12600
vform = kFormatVnS;
12601
break;
12602
default:
12603
VIXL_UNIMPLEMENTED();
12604
break;
12605
}
12606
int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12607
int vl = GetVectorLengthInBytes();
12608
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12609
uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
12610
LogicSVEAddressVector addr(base + offset);
12611
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12612
SVEStructuredLoadHelper(vform,
12613
pg,
12614
instr->GetRt(),
12615
addr,
12616
/* is_signed = */ false);
12617
}
12618
12619
void Simulator::VisitSVEContiguousNonTemporalLoad_ScalarPlusScalar(
12620
const Instruction* instr) {
12621
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12622
VectorFormat vform = kFormatUndefined;
12623
12624
switch (instr->Mask(SVEContiguousNonTemporalLoad_ScalarPlusScalarMask)) {
12625
case LDNT1B_z_p_br_contiguous:
12626
vform = kFormatVnB;
12627
break;
12628
case LDNT1D_z_p_br_contiguous:
12629
vform = kFormatVnD;
12630
break;
12631
case LDNT1H_z_p_br_contiguous:
12632
vform = kFormatVnH;
12633
break;
12634
case LDNT1W_z_p_br_contiguous:
12635
vform = kFormatVnS;
12636
break;
12637
default:
12638
VIXL_UNIMPLEMENTED();
12639
break;
12640
}
12641
int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
12642
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12643
uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
12644
LogicSVEAddressVector addr(base + offset);
12645
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12646
SVEStructuredLoadHelper(vform,
12647
pg,
12648
instr->GetRt(),
12649
addr,
12650
/* is_signed = */ false);
12651
}
12652
12653
void Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusImm(
12654
const Instruction* instr) {
12655
SimVRegister& zt = ReadVRegister(instr->GetRt());
12656
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12657
12658
uint64_t dwords = 2;
12659
VectorFormat vform_dst = kFormatVnQ;
12660
if ((form_hash_ == "ld1rob_z_p_bi_u8"_h) ||
12661
(form_hash_ == "ld1roh_z_p_bi_u16"_h) ||
12662
(form_hash_ == "ld1row_z_p_bi_u32"_h) ||
12663
(form_hash_ == "ld1rod_z_p_bi_u64"_h)) {
12664
dwords = 4;
12665
vform_dst = kFormatVnO;
12666
}
12667
12668
uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12669
uint64_t offset =
12670
instr->ExtractSignedBits(19, 16) * dwords * kDRegSizeInBytes;
12671
int msz = instr->ExtractBits(24, 23);
12672
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12673
12674
for (unsigned i = 0; i < dwords; i++) {
12675
if (!ld1(kFormatVnD, zt, i, addr + offset + (i * kDRegSizeInBytes))) return;
12676
}
12677
mov_zeroing(vform, zt, pg, zt);
12678
dup_element(vform_dst, zt, zt, 0);
12679
}
12680
12681
void Simulator::VisitSVELoadAndBroadcastQOWord_ScalarPlusScalar(
12682
const Instruction* instr) {
12683
SimVRegister& zt = ReadVRegister(instr->GetRt());
12684
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
12685
12686
uint64_t bytes = 16;
12687
VectorFormat vform_dst = kFormatVnQ;
12688
if ((form_hash_ == "ld1rob_z_p_br_contiguous"_h) ||
12689
(form_hash_ == "ld1roh_z_p_br_contiguous"_h) ||
12690
(form_hash_ == "ld1row_z_p_br_contiguous"_h) ||
12691
(form_hash_ == "ld1rod_z_p_br_contiguous"_h)) {
12692
bytes = 32;
12693
vform_dst = kFormatVnO;
12694
}
12695
12696
uint64_t addr = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12697
uint64_t offset = ReadXRegister(instr->GetRm());
12698
int msz = instr->ExtractBits(24, 23);
12699
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12700
offset <<= msz;
12701
for (unsigned i = 0; i < bytes; i++) {
12702
if (!ld1(kFormatVnB, zt, i, addr + offset + i)) return;
12703
}
12704
mov_zeroing(vform, zt, pg, zt);
12705
dup_element(vform_dst, zt, zt, 0);
12706
}
12707
12708
void Simulator::VisitSVELoadMultipleStructures_ScalarPlusImm(
12709
const Instruction* instr) {
12710
switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusImmMask)) {
12711
case LD2B_z_p_bi_contiguous:
12712
case LD2D_z_p_bi_contiguous:
12713
case LD2H_z_p_bi_contiguous:
12714
case LD2W_z_p_bi_contiguous:
12715
case LD3B_z_p_bi_contiguous:
12716
case LD3D_z_p_bi_contiguous:
12717
case LD3H_z_p_bi_contiguous:
12718
case LD3W_z_p_bi_contiguous:
12719
case LD4B_z_p_bi_contiguous:
12720
case LD4D_z_p_bi_contiguous:
12721
case LD4H_z_p_bi_contiguous:
12722
case LD4W_z_p_bi_contiguous: {
12723
int vl = GetVectorLengthInBytes();
12724
int msz = instr->ExtractBits(24, 23);
12725
int reg_count = instr->ExtractBits(22, 21) + 1;
12726
uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
12727
LogicSVEAddressVector addr(
12728
ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12729
addr.SetMsizeInBytesLog2(msz);
12730
addr.SetRegCount(reg_count);
12731
SVEStructuredLoadHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
12732
ReadPRegister(instr->GetPgLow8()),
12733
instr->GetRt(),
12734
addr);
12735
break;
12736
}
12737
default:
12738
VIXL_UNIMPLEMENTED();
12739
break;
12740
}
12741
}
12742
12743
void Simulator::VisitSVELoadMultipleStructures_ScalarPlusScalar(
12744
const Instruction* instr) {
12745
switch (instr->Mask(SVELoadMultipleStructures_ScalarPlusScalarMask)) {
12746
case LD2B_z_p_br_contiguous:
12747
case LD2D_z_p_br_contiguous:
12748
case LD2H_z_p_br_contiguous:
12749
case LD2W_z_p_br_contiguous:
12750
case LD3B_z_p_br_contiguous:
12751
case LD3D_z_p_br_contiguous:
12752
case LD3H_z_p_br_contiguous:
12753
case LD3W_z_p_br_contiguous:
12754
case LD4B_z_p_br_contiguous:
12755
case LD4D_z_p_br_contiguous:
12756
case LD4H_z_p_br_contiguous:
12757
case LD4W_z_p_br_contiguous: {
12758
int msz = instr->ExtractBits(24, 23);
12759
uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
12760
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
12761
LogicSVEAddressVector addr(
12762
ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
12763
addr.SetMsizeInBytesLog2(msz);
12764
addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
12765
SVEStructuredLoadHelper(vform,
12766
ReadPRegister(instr->GetPgLow8()),
12767
instr->GetRt(),
12768
addr,
12769
false);
12770
break;
12771
}
12772
default:
12773
VIXL_UNIMPLEMENTED();
12774
break;
12775
}
12776
}
12777
12778
void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitScaledOffsets(
12779
const Instruction* instr) {
12780
switch (instr->Mask(SVE32BitScatterStore_ScalarPlus32BitScaledOffsetsMask)) {
12781
case ST1H_z_p_bz_s_x32_scaled:
12782
case ST1W_z_p_bz_s_x32_scaled: {
12783
unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12784
VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12785
int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12786
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12787
SVEOffsetModifier mod =
12788
(instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12789
LogicSVEAddressVector addr(base,
12790
&ReadVRegister(instr->GetRm()),
12791
kFormatVnS,
12792
mod,
12793
scale);
12794
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12795
SVEStructuredStoreHelper(kFormatVnS,
12796
ReadPRegister(instr->GetPgLow8()),
12797
instr->GetRt(),
12798
addr);
12799
break;
12800
}
12801
default:
12802
VIXL_UNIMPLEMENTED();
12803
break;
12804
}
12805
}
12806
12807
void Simulator::VisitSVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets(
12808
const Instruction* instr) {
12809
switch (
12810
instr->Mask(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsetsMask)) {
12811
case ST1B_z_p_bz_s_x32_unscaled:
12812
case ST1H_z_p_bz_s_x32_unscaled:
12813
case ST1W_z_p_bz_s_x32_unscaled: {
12814
unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12815
VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12816
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12817
SVEOffsetModifier mod =
12818
(instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12819
LogicSVEAddressVector addr(base,
12820
&ReadVRegister(instr->GetRm()),
12821
kFormatVnS,
12822
mod);
12823
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12824
SVEStructuredStoreHelper(kFormatVnS,
12825
ReadPRegister(instr->GetPgLow8()),
12826
instr->GetRt(),
12827
addr);
12828
break;
12829
}
12830
default:
12831
VIXL_UNIMPLEMENTED();
12832
break;
12833
}
12834
}
12835
12836
void Simulator::VisitSVE32BitScatterStore_VectorPlusImm(
12837
const Instruction* instr) {
12838
int msz = 0;
12839
switch (instr->Mask(SVE32BitScatterStore_VectorPlusImmMask)) {
12840
case ST1B_z_p_ai_s:
12841
msz = 0;
12842
break;
12843
case ST1H_z_p_ai_s:
12844
msz = 1;
12845
break;
12846
case ST1W_z_p_ai_s:
12847
msz = 2;
12848
break;
12849
default:
12850
VIXL_UNIMPLEMENTED();
12851
break;
12852
}
12853
uint64_t imm = instr->ExtractBits(20, 16) << msz;
12854
LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnS);
12855
addr.SetMsizeInBytesLog2(msz);
12856
SVEStructuredStoreHelper(kFormatVnS,
12857
ReadPRegister(instr->GetPgLow8()),
12858
instr->GetRt(),
12859
addr);
12860
}
12861
12862
void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitScaledOffsets(
12863
const Instruction* instr) {
12864
switch (instr->Mask(SVE64BitScatterStore_ScalarPlus64BitScaledOffsetsMask)) {
12865
case ST1D_z_p_bz_d_64_scaled:
12866
case ST1H_z_p_bz_d_64_scaled:
12867
case ST1W_z_p_bz_d_64_scaled: {
12868
unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12869
VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12870
int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12871
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12872
LogicSVEAddressVector addr(base,
12873
&ReadVRegister(instr->GetRm()),
12874
kFormatVnD,
12875
SVE_LSL,
12876
scale);
12877
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12878
SVEStructuredStoreHelper(kFormatVnD,
12879
ReadPRegister(instr->GetPgLow8()),
12880
instr->GetRt(),
12881
addr);
12882
break;
12883
}
12884
default:
12885
VIXL_UNIMPLEMENTED();
12886
break;
12887
}
12888
}
12889
12890
void Simulator::VisitSVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets(
12891
const Instruction* instr) {
12892
switch (
12893
instr->Mask(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsetsMask)) {
12894
case ST1B_z_p_bz_d_64_unscaled:
12895
case ST1D_z_p_bz_d_64_unscaled:
12896
case ST1H_z_p_bz_d_64_unscaled:
12897
case ST1W_z_p_bz_d_64_unscaled: {
12898
unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12899
VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12900
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12901
LogicSVEAddressVector addr(base,
12902
&ReadVRegister(instr->GetRm()),
12903
kFormatVnD,
12904
NO_SVE_OFFSET_MODIFIER);
12905
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12906
SVEStructuredStoreHelper(kFormatVnD,
12907
ReadPRegister(instr->GetPgLow8()),
12908
instr->GetRt(),
12909
addr);
12910
break;
12911
}
12912
default:
12913
VIXL_UNIMPLEMENTED();
12914
break;
12915
}
12916
}
12917
12918
void Simulator::VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets(
12919
const Instruction* instr) {
12920
switch (instr->Mask(
12921
SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsetsMask)) {
12922
case ST1D_z_p_bz_d_x32_scaled:
12923
case ST1H_z_p_bz_d_x32_scaled:
12924
case ST1W_z_p_bz_d_x32_scaled: {
12925
unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12926
VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12927
int scale = instr->ExtractBit(21) * msize_in_bytes_log2;
12928
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12929
SVEOffsetModifier mod =
12930
(instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12931
LogicSVEAddressVector addr(base,
12932
&ReadVRegister(instr->GetRm()),
12933
kFormatVnD,
12934
mod,
12935
scale);
12936
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12937
SVEStructuredStoreHelper(kFormatVnD,
12938
ReadPRegister(instr->GetPgLow8()),
12939
instr->GetRt(),
12940
addr);
12941
break;
12942
}
12943
default:
12944
VIXL_UNIMPLEMENTED();
12945
break;
12946
}
12947
}
12948
12949
void Simulator::
12950
VisitSVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets(
12951
const Instruction* instr) {
12952
switch (instr->Mask(
12953
SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsetsMask)) {
12954
case ST1B_z_p_bz_d_x32_unscaled:
12955
case ST1D_z_p_bz_d_x32_unscaled:
12956
case ST1H_z_p_bz_d_x32_unscaled:
12957
case ST1W_z_p_bz_d_x32_unscaled: {
12958
unsigned msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
12959
VIXL_ASSERT(kDRegSizeInBytesLog2 >= msize_in_bytes_log2);
12960
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
12961
SVEOffsetModifier mod =
12962
(instr->ExtractBit(14) == 1) ? SVE_SXTW : SVE_UXTW;
12963
LogicSVEAddressVector addr(base,
12964
&ReadVRegister(instr->GetRm()),
12965
kFormatVnD,
12966
mod);
12967
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
12968
SVEStructuredStoreHelper(kFormatVnD,
12969
ReadPRegister(instr->GetPgLow8()),
12970
instr->GetRt(),
12971
addr);
12972
break;
12973
}
12974
default:
12975
VIXL_UNIMPLEMENTED();
12976
break;
12977
}
12978
}
12979
12980
void Simulator::VisitSVE64BitScatterStore_VectorPlusImm(
12981
const Instruction* instr) {
12982
int msz = 0;
12983
switch (instr->Mask(SVE64BitScatterStore_VectorPlusImmMask)) {
12984
case ST1B_z_p_ai_d:
12985
msz = 0;
12986
break;
12987
case ST1D_z_p_ai_d:
12988
msz = 3;
12989
break;
12990
case ST1H_z_p_ai_d:
12991
msz = 1;
12992
break;
12993
case ST1W_z_p_ai_d:
12994
msz = 2;
12995
break;
12996
default:
12997
VIXL_UNIMPLEMENTED();
12998
break;
12999
}
13000
uint64_t imm = instr->ExtractBits(20, 16) << msz;
13001
LogicSVEAddressVector addr(imm, &ReadVRegister(instr->GetRn()), kFormatVnD);
13002
addr.SetMsizeInBytesLog2(msz);
13003
SVEStructuredStoreHelper(kFormatVnD,
13004
ReadPRegister(instr->GetPgLow8()),
13005
instr->GetRt(),
13006
addr);
13007
}
13008
13009
void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusImm(
13010
const Instruction* instr) {
13011
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13012
VectorFormat vform = kFormatUndefined;
13013
13014
switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusImmMask)) {
13015
case STNT1B_z_p_bi_contiguous:
13016
vform = kFormatVnB;
13017
break;
13018
case STNT1D_z_p_bi_contiguous:
13019
vform = kFormatVnD;
13020
break;
13021
case STNT1H_z_p_bi_contiguous:
13022
vform = kFormatVnH;
13023
break;
13024
case STNT1W_z_p_bi_contiguous:
13025
vform = kFormatVnS;
13026
break;
13027
default:
13028
VIXL_UNIMPLEMENTED();
13029
break;
13030
}
13031
int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
13032
int vl = GetVectorLengthInBytes();
13033
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
13034
uint64_t offset = instr->ExtractSignedBits(19, 16) * vl;
13035
LogicSVEAddressVector addr(base + offset);
13036
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13037
SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
13038
}
13039
13040
void Simulator::VisitSVEContiguousNonTemporalStore_ScalarPlusScalar(
13041
const Instruction* instr) {
13042
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13043
VectorFormat vform = kFormatUndefined;
13044
13045
switch (instr->Mask(SVEContiguousNonTemporalStore_ScalarPlusScalarMask)) {
13046
case STNT1B_z_p_br_contiguous:
13047
vform = kFormatVnB;
13048
break;
13049
case STNT1D_z_p_br_contiguous:
13050
vform = kFormatVnD;
13051
break;
13052
case STNT1H_z_p_br_contiguous:
13053
vform = kFormatVnH;
13054
break;
13055
case STNT1W_z_p_br_contiguous:
13056
vform = kFormatVnS;
13057
break;
13058
default:
13059
VIXL_UNIMPLEMENTED();
13060
break;
13061
}
13062
int msize_in_bytes_log2 = LaneSizeInBytesLog2FromFormat(vform);
13063
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
13064
uint64_t offset = ReadXRegister(instr->GetRm()) << msize_in_bytes_log2;
13065
LogicSVEAddressVector addr(base + offset);
13066
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13067
SVEStructuredStoreHelper(vform, pg, instr->GetRt(), addr);
13068
}
13069
13070
void Simulator::VisitSVEContiguousStore_ScalarPlusImm(
13071
const Instruction* instr) {
13072
switch (instr->Mask(SVEContiguousStore_ScalarPlusImmMask)) {
13073
case ST1B_z_p_bi:
13074
case ST1D_z_p_bi:
13075
case ST1H_z_p_bi:
13076
case ST1W_z_p_bi: {
13077
int vl = GetVectorLengthInBytes();
13078
int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(false);
13079
int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(false);
13080
VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
13081
int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
13082
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
13083
uint64_t offset =
13084
(instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
13085
VectorFormat vform =
13086
SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
13087
LogicSVEAddressVector addr(base + offset);
13088
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
13089
SVEStructuredStoreHelper(vform,
13090
ReadPRegister(instr->GetPgLow8()),
13091
instr->GetRt(),
13092
addr);
13093
break;
13094
}
13095
default:
13096
VIXL_UNIMPLEMENTED();
13097
break;
13098
}
13099
}
13100
13101
void Simulator::VisitSVEContiguousStore_ScalarPlusScalar(
13102
const Instruction* instr) {
13103
switch (instr->Mask(SVEContiguousStore_ScalarPlusScalarMask)) {
13104
case ST1B_z_p_br:
13105
case ST1D_z_p_br:
13106
case ST1H_z_p_br:
13107
case ST1W_z_p_br: {
13108
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
13109
uint64_t offset = ReadXRegister(instr->GetRm());
13110
offset <<= instr->ExtractBits(24, 23);
13111
VectorFormat vform =
13112
SVEFormatFromLaneSizeInBytesLog2(instr->ExtractBits(22, 21));
13113
LogicSVEAddressVector addr(base + offset);
13114
addr.SetMsizeInBytesLog2(instr->ExtractBits(24, 23));
13115
SVEStructuredStoreHelper(vform,
13116
ReadPRegister(instr->GetPgLow8()),
13117
instr->GetRt(),
13118
addr);
13119
break;
13120
}
13121
default:
13122
VIXL_UNIMPLEMENTED();
13123
break;
13124
}
13125
}
13126
13127
void Simulator::VisitSVECopySIMDFPScalarRegisterToVector_Predicated(
13128
const Instruction* instr) {
13129
VectorFormat vform = instr->GetSVEVectorFormat();
13130
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13131
SimVRegister z_result;
13132
13133
switch (instr->Mask(SVECopySIMDFPScalarRegisterToVector_PredicatedMask)) {
13134
case CPY_z_p_v:
13135
dup_element(vform, z_result, ReadVRegister(instr->GetRn()), 0);
13136
mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
13137
break;
13138
default:
13139
VIXL_UNIMPLEMENTED();
13140
break;
13141
}
13142
}
13143
13144
void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusImm(
13145
const Instruction* instr) {
13146
switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusImmMask)) {
13147
case ST2B_z_p_bi_contiguous:
13148
case ST2D_z_p_bi_contiguous:
13149
case ST2H_z_p_bi_contiguous:
13150
case ST2W_z_p_bi_contiguous:
13151
case ST3B_z_p_bi_contiguous:
13152
case ST3D_z_p_bi_contiguous:
13153
case ST3H_z_p_bi_contiguous:
13154
case ST3W_z_p_bi_contiguous:
13155
case ST4B_z_p_bi_contiguous:
13156
case ST4D_z_p_bi_contiguous:
13157
case ST4H_z_p_bi_contiguous:
13158
case ST4W_z_p_bi_contiguous: {
13159
int vl = GetVectorLengthInBytes();
13160
int msz = instr->ExtractBits(24, 23);
13161
int reg_count = instr->ExtractBits(22, 21) + 1;
13162
uint64_t offset = instr->ExtractSignedBits(19, 16) * vl * reg_count;
13163
LogicSVEAddressVector addr(
13164
ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
13165
addr.SetMsizeInBytesLog2(msz);
13166
addr.SetRegCount(reg_count);
13167
SVEStructuredStoreHelper(SVEFormatFromLaneSizeInBytesLog2(msz),
13168
ReadPRegister(instr->GetPgLow8()),
13169
instr->GetRt(),
13170
addr);
13171
break;
13172
}
13173
default:
13174
VIXL_UNIMPLEMENTED();
13175
break;
13176
}
13177
}
13178
13179
void Simulator::VisitSVEStoreMultipleStructures_ScalarPlusScalar(
13180
const Instruction* instr) {
13181
switch (instr->Mask(SVEStoreMultipleStructures_ScalarPlusScalarMask)) {
13182
case ST2B_z_p_br_contiguous:
13183
case ST2D_z_p_br_contiguous:
13184
case ST2H_z_p_br_contiguous:
13185
case ST2W_z_p_br_contiguous:
13186
case ST3B_z_p_br_contiguous:
13187
case ST3D_z_p_br_contiguous:
13188
case ST3H_z_p_br_contiguous:
13189
case ST3W_z_p_br_contiguous:
13190
case ST4B_z_p_br_contiguous:
13191
case ST4D_z_p_br_contiguous:
13192
case ST4H_z_p_br_contiguous:
13193
case ST4W_z_p_br_contiguous: {
13194
int msz = instr->ExtractBits(24, 23);
13195
uint64_t offset = ReadXRegister(instr->GetRm()) * (1 << msz);
13196
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(msz);
13197
LogicSVEAddressVector addr(
13198
ReadXRegister(instr->GetRn(), Reg31IsStackPointer) + offset);
13199
addr.SetMsizeInBytesLog2(msz);
13200
addr.SetRegCount(instr->ExtractBits(22, 21) + 1);
13201
SVEStructuredStoreHelper(vform,
13202
ReadPRegister(instr->GetPgLow8()),
13203
instr->GetRt(),
13204
addr);
13205
break;
13206
}
13207
default:
13208
VIXL_UNIMPLEMENTED();
13209
break;
13210
}
13211
}
13212
13213
void Simulator::VisitSVEStorePredicateRegister(const Instruction* instr) {
13214
switch (instr->Mask(SVEStorePredicateRegisterMask)) {
13215
case STR_p_bi: {
13216
SimPRegister& pt = ReadPRegister(instr->GetPt());
13217
int pl = GetPredicateLengthInBytes();
13218
int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
13219
uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
13220
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
13221
uint64_t address = base + multiplier * pl;
13222
for (int i = 0; i < pl; i++) {
13223
if (!MemWrite(address + i, pt.GetLane<uint8_t>(i))) return;
13224
}
13225
LogPWrite(instr->GetPt(), address);
13226
break;
13227
}
13228
default:
13229
VIXL_UNIMPLEMENTED();
13230
break;
13231
}
13232
}
13233
13234
void Simulator::VisitSVEStoreVectorRegister(const Instruction* instr) {
13235
switch (instr->Mask(SVEStoreVectorRegisterMask)) {
13236
case STR_z_bi: {
13237
SimVRegister& zt = ReadVRegister(instr->GetRt());
13238
int vl = GetVectorLengthInBytes();
13239
int imm9 = (instr->ExtractBits(21, 16) << 3) | instr->ExtractBits(12, 10);
13240
uint64_t multiplier = ExtractSignedBitfield64(8, 0, imm9);
13241
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
13242
uint64_t address = base + multiplier * vl;
13243
for (int i = 0; i < vl; i++) {
13244
if (!MemWrite(address + i, zt.GetLane<uint8_t>(i))) return;
13245
}
13246
LogZWrite(instr->GetRt(), address);
13247
break;
13248
}
13249
default:
13250
VIXL_UNIMPLEMENTED();
13251
break;
13252
}
13253
}
13254
13255
void Simulator::VisitSVEMulIndex(const Instruction* instr) {
13256
VectorFormat vform = instr->GetSVEVectorFormat();
13257
SimVRegister& zda = ReadVRegister(instr->GetRd());
13258
SimVRegister& zn = ReadVRegister(instr->GetRn());
13259
std::pair<int, int> zm_and_index = instr->GetSVEMulZmAndIndex();
13260
SimVRegister zm = ReadVRegister(zm_and_index.first);
13261
int index = zm_and_index.second;
13262
13263
SimVRegister temp;
13264
dup_elements_to_segments(vform, temp, zm, index);
13265
13266
switch (form_hash_) {
13267
case "sdot_z_zzzi_d"_h:
13268
case "sdot_z_zzzi_s"_h:
13269
sdot(vform, zda, zn, temp);
13270
break;
13271
case "udot_z_zzzi_d"_h:
13272
case "udot_z_zzzi_s"_h:
13273
udot(vform, zda, zn, temp);
13274
break;
13275
case "sudot_z_zzzi_s"_h:
13276
usdot(vform, zda, temp, zn);
13277
break;
13278
case "usdot_z_zzzi_s"_h:
13279
usdot(vform, zda, zn, temp);
13280
break;
13281
default:
13282
VIXL_UNIMPLEMENTED();
13283
break;
13284
}
13285
}
13286
13287
void Simulator::SimulateMatrixMul(const Instruction* instr) {
13288
VectorFormat vform = kFormatVnS;
13289
SimVRegister& dn = ReadVRegister(instr->GetRd());
13290
SimVRegister& n = ReadVRegister(instr->GetRn());
13291
SimVRegister& m = ReadVRegister(instr->GetRm());
13292
13293
bool n_signed = false;
13294
bool m_signed = false;
13295
switch (form_hash_) {
13296
case "smmla_asimdsame2_g"_h:
13297
vform = kFormat4S;
13298
VIXL_FALLTHROUGH();
13299
case "smmla_z_zzz"_h:
13300
n_signed = m_signed = true;
13301
break;
13302
case "ummla_asimdsame2_g"_h:
13303
vform = kFormat4S;
13304
VIXL_FALLTHROUGH();
13305
case "ummla_z_zzz"_h:
13306
// Nothing to do.
13307
break;
13308
case "usmmla_asimdsame2_g"_h:
13309
vform = kFormat4S;
13310
VIXL_FALLTHROUGH();
13311
case "usmmla_z_zzz"_h:
13312
m_signed = true;
13313
break;
13314
default:
13315
VIXL_UNIMPLEMENTED();
13316
break;
13317
}
13318
matmul(vform, dn, n, m, n_signed, m_signed);
13319
}
13320
13321
void Simulator::SimulateSVEFPMatrixMul(const Instruction* instr) {
13322
VectorFormat vform = instr->GetSVEVectorFormat();
13323
SimVRegister& zdn = ReadVRegister(instr->GetRd());
13324
SimVRegister& zn = ReadVRegister(instr->GetRn());
13325
SimVRegister& zm = ReadVRegister(instr->GetRm());
13326
13327
switch (form_hash_) {
13328
case "fmmla_z_zzz_s"_h:
13329
case "fmmla_z_zzz_d"_h:
13330
fmatmul(vform, zdn, zn, zm);
13331
break;
13332
default:
13333
VIXL_UNIMPLEMENTED();
13334
break;
13335
}
13336
}
13337
13338
void Simulator::VisitSVEPartitionBreakCondition(const Instruction* instr) {
13339
SimPRegister& pd = ReadPRegister(instr->GetPd());
13340
SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13341
SimPRegister& pn = ReadPRegister(instr->GetPn());
13342
SimPRegister result;
13343
13344
switch (instr->Mask(SVEPartitionBreakConditionMask)) {
13345
case BRKAS_p_p_p_z:
13346
case BRKA_p_p_p:
13347
brka(result, pg, pn);
13348
break;
13349
case BRKBS_p_p_p_z:
13350
case BRKB_p_p_p:
13351
brkb(result, pg, pn);
13352
break;
13353
default:
13354
VIXL_UNIMPLEMENTED();
13355
break;
13356
}
13357
13358
if (instr->ExtractBit(4) == 1) {
13359
mov_merging(pd, pg, result);
13360
} else {
13361
mov_zeroing(pd, pg, result);
13362
}
13363
13364
// Set flag if needed.
13365
if (instr->ExtractBit(22) == 1) {
13366
PredTest(kFormatVnB, pg, pd);
13367
}
13368
}
13369
13370
void Simulator::VisitSVEPropagateBreakToNextPartition(
13371
const Instruction* instr) {
13372
SimPRegister& pdm = ReadPRegister(instr->GetPd());
13373
SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13374
SimPRegister& pn = ReadPRegister(instr->GetPn());
13375
13376
switch (instr->Mask(SVEPropagateBreakToNextPartitionMask)) {
13377
case BRKNS_p_p_pp:
13378
case BRKN_p_p_pp:
13379
brkn(pdm, pg, pn);
13380
break;
13381
default:
13382
VIXL_UNIMPLEMENTED();
13383
break;
13384
}
13385
13386
// Set flag if needed.
13387
if (instr->ExtractBit(22) == 1) {
13388
// Note that this ignores `pg`.
13389
PredTest(kFormatVnB, GetPTrue(), pdm);
13390
}
13391
}
13392
13393
void Simulator::VisitSVEUnpackPredicateElements(const Instruction* instr) {
13394
SimPRegister& pd = ReadPRegister(instr->GetPd());
13395
SimPRegister& pn = ReadPRegister(instr->GetPn());
13396
13397
SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
13398
SimVRegister zero;
13399
dup_immediate(kFormatVnB, zero, 0);
13400
13401
switch (instr->Mask(SVEUnpackPredicateElementsMask)) {
13402
case PUNPKHI_p_p:
13403
zip2(kFormatVnB, temp, temp, zero);
13404
break;
13405
case PUNPKLO_p_p:
13406
zip1(kFormatVnB, temp, temp, zero);
13407
break;
13408
default:
13409
VIXL_UNIMPLEMENTED();
13410
break;
13411
}
13412
Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
13413
}
13414
13415
void Simulator::VisitSVEPermutePredicateElements(const Instruction* instr) {
13416
VectorFormat vform = instr->GetSVEVectorFormat();
13417
SimPRegister& pd = ReadPRegister(instr->GetPd());
13418
SimPRegister& pn = ReadPRegister(instr->GetPn());
13419
SimPRegister& pm = ReadPRegister(instr->GetPm());
13420
13421
SimVRegister temp0 = Simulator::ExpandToSimVRegister(pn);
13422
SimVRegister temp1 = Simulator::ExpandToSimVRegister(pm);
13423
13424
switch (instr->Mask(SVEPermutePredicateElementsMask)) {
13425
case TRN1_p_pp:
13426
trn1(vform, temp0, temp0, temp1);
13427
break;
13428
case TRN2_p_pp:
13429
trn2(vform, temp0, temp0, temp1);
13430
break;
13431
case UZP1_p_pp:
13432
uzp1(vform, temp0, temp0, temp1);
13433
break;
13434
case UZP2_p_pp:
13435
uzp2(vform, temp0, temp0, temp1);
13436
break;
13437
case ZIP1_p_pp:
13438
zip1(vform, temp0, temp0, temp1);
13439
break;
13440
case ZIP2_p_pp:
13441
zip2(vform, temp0, temp0, temp1);
13442
break;
13443
default:
13444
VIXL_UNIMPLEMENTED();
13445
break;
13446
}
13447
Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp0);
13448
}
13449
13450
void Simulator::VisitSVEReversePredicateElements(const Instruction* instr) {
13451
switch (instr->Mask(SVEReversePredicateElementsMask)) {
13452
case REV_p_p: {
13453
VectorFormat vform = instr->GetSVEVectorFormat();
13454
SimPRegister& pn = ReadPRegister(instr->GetPn());
13455
SimPRegister& pd = ReadPRegister(instr->GetPd());
13456
SimVRegister temp = Simulator::ExpandToSimVRegister(pn);
13457
rev(vform, temp, temp);
13458
Simulator::ExtractFromSimVRegister(kFormatVnB, pd, temp);
13459
break;
13460
}
13461
default:
13462
VIXL_UNIMPLEMENTED();
13463
break;
13464
}
13465
}
13466
13467
void Simulator::VisitSVEPermuteVectorExtract(const Instruction* instr) {
13468
SimVRegister& zdn = ReadVRegister(instr->GetRd());
13469
// Second source register "Zm" is encoded where "Zn" would usually be.
13470
SimVRegister& zm = ReadVRegister(instr->GetRn());
13471
13472
int index = instr->GetSVEExtractImmediate();
13473
int vl = GetVectorLengthInBytes();
13474
index = (index >= vl) ? 0 : index;
13475
13476
switch (instr->Mask(SVEPermuteVectorExtractMask)) {
13477
case EXT_z_zi_des:
13478
ext(kFormatVnB, zdn, zdn, zm, index);
13479
break;
13480
default:
13481
VIXL_UNIMPLEMENTED();
13482
break;
13483
}
13484
}
13485
13486
void Simulator::VisitSVEPermuteVectorInterleaving(const Instruction* instr) {
13487
VectorFormat vform = instr->GetSVEVectorFormat();
13488
SimVRegister& zd = ReadVRegister(instr->GetRd());
13489
SimVRegister& zn = ReadVRegister(instr->GetRn());
13490
SimVRegister& zm = ReadVRegister(instr->GetRm());
13491
13492
switch (instr->Mask(SVEPermuteVectorInterleavingMask)) {
13493
case TRN1_z_zz:
13494
trn1(vform, zd, zn, zm);
13495
break;
13496
case TRN2_z_zz:
13497
trn2(vform, zd, zn, zm);
13498
break;
13499
case UZP1_z_zz:
13500
uzp1(vform, zd, zn, zm);
13501
break;
13502
case UZP2_z_zz:
13503
uzp2(vform, zd, zn, zm);
13504
break;
13505
case ZIP1_z_zz:
13506
zip1(vform, zd, zn, zm);
13507
break;
13508
case ZIP2_z_zz:
13509
zip2(vform, zd, zn, zm);
13510
break;
13511
default:
13512
VIXL_UNIMPLEMENTED();
13513
break;
13514
}
13515
}
13516
13517
void Simulator::VisitSVEConditionallyBroadcastElementToVector(
13518
const Instruction* instr) {
13519
VectorFormat vform = instr->GetSVEVectorFormat();
13520
SimVRegister& zdn = ReadVRegister(instr->GetRd());
13521
SimVRegister& zm = ReadVRegister(instr->GetRn());
13522
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13523
13524
int active_offset = -1;
13525
switch (instr->Mask(SVEConditionallyBroadcastElementToVectorMask)) {
13526
case CLASTA_z_p_zz:
13527
active_offset = 1;
13528
break;
13529
case CLASTB_z_p_zz:
13530
active_offset = 0;
13531
break;
13532
default:
13533
VIXL_UNIMPLEMENTED();
13534
break;
13535
}
13536
13537
if (active_offset >= 0) {
13538
std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13539
if (value.first) {
13540
dup_immediate(vform, zdn, value.second);
13541
} else {
13542
// Trigger a line of trace for the operation, even though it doesn't
13543
// change the register value.
13544
mov(vform, zdn, zdn);
13545
}
13546
}
13547
}
13548
13549
void Simulator::VisitSVEConditionallyExtractElementToSIMDFPScalar(
13550
const Instruction* instr) {
13551
VectorFormat vform = instr->GetSVEVectorFormat();
13552
SimVRegister& vdn = ReadVRegister(instr->GetRd());
13553
SimVRegister& zm = ReadVRegister(instr->GetRn());
13554
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13555
13556
int active_offset = -1;
13557
switch (instr->Mask(SVEConditionallyExtractElementToSIMDFPScalarMask)) {
13558
case CLASTA_v_p_z:
13559
active_offset = 1;
13560
break;
13561
case CLASTB_v_p_z:
13562
active_offset = 0;
13563
break;
13564
default:
13565
VIXL_UNIMPLEMENTED();
13566
break;
13567
}
13568
13569
if (active_offset >= 0) {
13570
LogicVRegister dst(vdn);
13571
uint64_t src1_value = dst.Uint(vform, 0);
13572
std::pair<bool, uint64_t> src2_value = clast(vform, pg, zm, active_offset);
13573
dup_immediate(vform, vdn, 0);
13574
dst.SetUint(vform, 0, src2_value.first ? src2_value.second : src1_value);
13575
}
13576
}
13577
13578
void Simulator::VisitSVEConditionallyExtractElementToGeneralRegister(
13579
const Instruction* instr) {
13580
VectorFormat vform = instr->GetSVEVectorFormat();
13581
SimVRegister& zm = ReadVRegister(instr->GetRn());
13582
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13583
13584
int active_offset = -1;
13585
switch (instr->Mask(SVEConditionallyExtractElementToGeneralRegisterMask)) {
13586
case CLASTA_r_p_z:
13587
active_offset = 1;
13588
break;
13589
case CLASTB_r_p_z:
13590
active_offset = 0;
13591
break;
13592
default:
13593
VIXL_UNIMPLEMENTED();
13594
break;
13595
}
13596
13597
if (active_offset >= 0) {
13598
std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13599
uint64_t masked_src = ReadXRegister(instr->GetRd()) &
13600
GetUintMask(LaneSizeInBitsFromFormat(vform));
13601
WriteXRegister(instr->GetRd(), value.first ? value.second : masked_src);
13602
}
13603
}
13604
13605
void Simulator::VisitSVEExtractElementToSIMDFPScalarRegister(
13606
const Instruction* instr) {
13607
VectorFormat vform = instr->GetSVEVectorFormat();
13608
SimVRegister& vdn = ReadVRegister(instr->GetRd());
13609
SimVRegister& zm = ReadVRegister(instr->GetRn());
13610
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13611
13612
int active_offset = -1;
13613
switch (instr->Mask(SVEExtractElementToSIMDFPScalarRegisterMask)) {
13614
case LASTA_v_p_z:
13615
active_offset = 1;
13616
break;
13617
case LASTB_v_p_z:
13618
active_offset = 0;
13619
break;
13620
default:
13621
VIXL_UNIMPLEMENTED();
13622
break;
13623
}
13624
13625
if (active_offset >= 0) {
13626
LogicVRegister dst(vdn);
13627
std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13628
dup_immediate(vform, vdn, 0);
13629
dst.SetUint(vform, 0, value.second);
13630
}
13631
}
13632
13633
void Simulator::VisitSVEExtractElementToGeneralRegister(
13634
const Instruction* instr) {
13635
VectorFormat vform = instr->GetSVEVectorFormat();
13636
SimVRegister& zm = ReadVRegister(instr->GetRn());
13637
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13638
13639
int active_offset = -1;
13640
switch (instr->Mask(SVEExtractElementToGeneralRegisterMask)) {
13641
case LASTA_r_p_z:
13642
active_offset = 1;
13643
break;
13644
case LASTB_r_p_z:
13645
active_offset = 0;
13646
break;
13647
default:
13648
VIXL_UNIMPLEMENTED();
13649
break;
13650
}
13651
13652
if (active_offset >= 0) {
13653
std::pair<bool, uint64_t> value = clast(vform, pg, zm, active_offset);
13654
WriteXRegister(instr->GetRd(), value.second);
13655
}
13656
}
13657
13658
void Simulator::VisitSVECompressActiveElements(const Instruction* instr) {
13659
VectorFormat vform = instr->GetSVEVectorFormat();
13660
SimVRegister& zd = ReadVRegister(instr->GetRd());
13661
SimVRegister& zn = ReadVRegister(instr->GetRn());
13662
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13663
13664
switch (instr->Mask(SVECompressActiveElementsMask)) {
13665
case COMPACT_z_p_z:
13666
compact(vform, zd, pg, zn);
13667
break;
13668
default:
13669
VIXL_UNIMPLEMENTED();
13670
break;
13671
}
13672
}
13673
13674
void Simulator::VisitSVECopyGeneralRegisterToVector_Predicated(
13675
const Instruction* instr) {
13676
VectorFormat vform = instr->GetSVEVectorFormat();
13677
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13678
SimVRegister z_result;
13679
13680
switch (instr->Mask(SVECopyGeneralRegisterToVector_PredicatedMask)) {
13681
case CPY_z_p_r:
13682
dup_immediate(vform,
13683
z_result,
13684
ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13685
mov_merging(vform, ReadVRegister(instr->GetRd()), pg, z_result);
13686
break;
13687
default:
13688
VIXL_UNIMPLEMENTED();
13689
break;
13690
}
13691
}
13692
13693
void Simulator::VisitSVECopyIntImm_Predicated(const Instruction* instr) {
13694
VectorFormat vform = instr->GetSVEVectorFormat();
13695
SimPRegister& pg = ReadPRegister(instr->ExtractBits(19, 16));
13696
SimVRegister& zd = ReadVRegister(instr->GetRd());
13697
13698
SimVRegister result;
13699
switch (instr->Mask(SVECopyIntImm_PredicatedMask)) {
13700
case CPY_z_p_i: {
13701
// Use unsigned arithmetic to avoid undefined behaviour during the shift.
13702
uint64_t imm8 = instr->GetImmSVEIntWideSigned();
13703
dup_immediate(vform, result, imm8 << (instr->ExtractBit(13) * 8));
13704
break;
13705
}
13706
default:
13707
VIXL_UNIMPLEMENTED();
13708
break;
13709
}
13710
13711
if (instr->ExtractBit(14) != 0) {
13712
mov_merging(vform, zd, pg, result);
13713
} else {
13714
mov_zeroing(vform, zd, pg, result);
13715
}
13716
}
13717
13718
void Simulator::VisitSVEReverseWithinElements(const Instruction* instr) {
13719
SimVRegister& zd = ReadVRegister(instr->GetRd());
13720
SimVRegister& zn = ReadVRegister(instr->GetRn());
13721
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13722
SimVRegister result;
13723
13724
// In NEON, the chunk size in which elements are REVersed is in the
13725
// instruction mnemonic, and the element size attached to the register.
13726
// SVE reverses the semantics; the mapping to logic functions below is to
13727
// account for this.
13728
VectorFormat chunk_form = instr->GetSVEVectorFormat();
13729
VectorFormat element_form = kFormatUndefined;
13730
13731
switch (instr->Mask(SVEReverseWithinElementsMask)) {
13732
case RBIT_z_p_z:
13733
rbit(chunk_form, result, zn);
13734
break;
13735
case REVB_z_z:
13736
VIXL_ASSERT((chunk_form == kFormatVnH) || (chunk_form == kFormatVnS) ||
13737
(chunk_form == kFormatVnD));
13738
element_form = kFormatVnB;
13739
break;
13740
case REVH_z_z:
13741
VIXL_ASSERT((chunk_form == kFormatVnS) || (chunk_form == kFormatVnD));
13742
element_form = kFormatVnH;
13743
break;
13744
case REVW_z_z:
13745
VIXL_ASSERT(chunk_form == kFormatVnD);
13746
element_form = kFormatVnS;
13747
break;
13748
default:
13749
VIXL_UNIMPLEMENTED();
13750
break;
13751
}
13752
13753
if (instr->Mask(SVEReverseWithinElementsMask) != RBIT_z_p_z) {
13754
VIXL_ASSERT(element_form != kFormatUndefined);
13755
switch (chunk_form) {
13756
case kFormatVnH:
13757
rev16(element_form, result, zn);
13758
break;
13759
case kFormatVnS:
13760
rev32(element_form, result, zn);
13761
break;
13762
case kFormatVnD:
13763
rev64(element_form, result, zn);
13764
break;
13765
default:
13766
VIXL_UNIMPLEMENTED();
13767
}
13768
}
13769
13770
mov_merging(chunk_form, zd, pg, result);
13771
}
13772
13773
void Simulator::VisitSVEVectorSplice(const Instruction* instr) {
13774
VectorFormat vform = instr->GetSVEVectorFormat();
13775
SimVRegister& zd = ReadVRegister(instr->GetRd());
13776
SimVRegister& zn = ReadVRegister(instr->GetRn());
13777
SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
13778
SimPRegister& pg = ReadPRegister(instr->GetPgLow8());
13779
13780
switch (form_hash_) {
13781
case "splice_z_p_zz_des"_h:
13782
splice(vform, zd, pg, zd, zn);
13783
break;
13784
case "splice_z_p_zz_con"_h:
13785
splice(vform, zd, pg, zn, zn2);
13786
break;
13787
default:
13788
VIXL_UNIMPLEMENTED();
13789
break;
13790
}
13791
}
13792
13793
void Simulator::VisitSVEBroadcastGeneralRegister(const Instruction* instr) {
13794
SimVRegister& zd = ReadVRegister(instr->GetRd());
13795
switch (instr->Mask(SVEBroadcastGeneralRegisterMask)) {
13796
case DUP_z_r:
13797
dup_immediate(instr->GetSVEVectorFormat(),
13798
zd,
13799
ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
13800
break;
13801
default:
13802
VIXL_UNIMPLEMENTED();
13803
break;
13804
}
13805
}
13806
13807
void Simulator::VisitSVEInsertSIMDFPScalarRegister(const Instruction* instr) {
13808
SimVRegister& zd = ReadVRegister(instr->GetRd());
13809
VectorFormat vform = instr->GetSVEVectorFormat();
13810
switch (instr->Mask(SVEInsertSIMDFPScalarRegisterMask)) {
13811
case INSR_z_v:
13812
insr(vform, zd, ReadDRegisterBits(instr->GetRn()));
13813
break;
13814
default:
13815
VIXL_UNIMPLEMENTED();
13816
break;
13817
}
13818
}
13819
13820
void Simulator::VisitSVEInsertGeneralRegister(const Instruction* instr) {
13821
SimVRegister& zd = ReadVRegister(instr->GetRd());
13822
VectorFormat vform = instr->GetSVEVectorFormat();
13823
switch (instr->Mask(SVEInsertGeneralRegisterMask)) {
13824
case INSR_z_r:
13825
insr(vform, zd, ReadXRegister(instr->GetRn()));
13826
break;
13827
default:
13828
VIXL_UNIMPLEMENTED();
13829
break;
13830
}
13831
}
13832
13833
void Simulator::VisitSVEBroadcastIndexElement(const Instruction* instr) {
13834
SimVRegister& zd = ReadVRegister(instr->GetRd());
13835
switch (instr->Mask(SVEBroadcastIndexElementMask)) {
13836
case DUP_z_zi: {
13837
std::pair<int, int> index_and_lane_size =
13838
instr->GetSVEPermuteIndexAndLaneSizeLog2();
13839
int index = index_and_lane_size.first;
13840
int lane_size_in_bytes_log_2 = index_and_lane_size.second;
13841
VectorFormat vform =
13842
SVEFormatFromLaneSizeInBytesLog2(lane_size_in_bytes_log_2);
13843
if ((index < 0) || (index >= LaneCountFromFormat(vform))) {
13844
// Out of bounds, set the destination register to zero.
13845
dup_immediate(kFormatVnD, zd, 0);
13846
} else {
13847
dup_element(vform, zd, ReadVRegister(instr->GetRn()), index);
13848
}
13849
return;
13850
}
13851
default:
13852
VIXL_UNIMPLEMENTED();
13853
break;
13854
}
13855
}
13856
13857
void Simulator::VisitSVEReverseVectorElements(const Instruction* instr) {
13858
SimVRegister& zd = ReadVRegister(instr->GetRd());
13859
VectorFormat vform = instr->GetSVEVectorFormat();
13860
switch (instr->Mask(SVEReverseVectorElementsMask)) {
13861
case REV_z_z:
13862
rev(vform, zd, ReadVRegister(instr->GetRn()));
13863
break;
13864
default:
13865
VIXL_UNIMPLEMENTED();
13866
break;
13867
}
13868
}
13869
13870
void Simulator::VisitSVEUnpackVectorElements(const Instruction* instr) {
13871
SimVRegister& zd = ReadVRegister(instr->GetRd());
13872
VectorFormat vform = instr->GetSVEVectorFormat();
13873
switch (instr->Mask(SVEUnpackVectorElementsMask)) {
13874
case SUNPKHI_z_z:
13875
unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kSignedExtend);
13876
break;
13877
case SUNPKLO_z_z:
13878
unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kSignedExtend);
13879
break;
13880
case UUNPKHI_z_z:
13881
unpk(vform, zd, ReadVRegister(instr->GetRn()), kHiHalf, kUnsignedExtend);
13882
break;
13883
case UUNPKLO_z_z:
13884
unpk(vform, zd, ReadVRegister(instr->GetRn()), kLoHalf, kUnsignedExtend);
13885
break;
13886
default:
13887
VIXL_UNIMPLEMENTED();
13888
break;
13889
}
13890
}
13891
13892
void Simulator::VisitSVETableLookup(const Instruction* instr) {
13893
VectorFormat vform = instr->GetSVEVectorFormat();
13894
SimVRegister& zd = ReadVRegister(instr->GetRd());
13895
SimVRegister& zn = ReadVRegister(instr->GetRn());
13896
SimVRegister& zn2 = ReadVRegister((instr->GetRn() + 1) % kNumberOfZRegisters);
13897
SimVRegister& zm = ReadVRegister(instr->GetRm());
13898
13899
switch (form_hash_) {
13900
case "tbl_z_zz_1"_h:
13901
tbl(vform, zd, zn, zm);
13902
break;
13903
case "tbl_z_zz_2"_h:
13904
tbl(vform, zd, zn, zn2, zm);
13905
break;
13906
case "tbx_z_zz"_h:
13907
tbx(vform, zd, zn, zm);
13908
break;
13909
default:
13910
VIXL_UNIMPLEMENTED();
13911
break;
13912
}
13913
}
13914
13915
void Simulator::VisitSVEPredicateCount(const Instruction* instr) {
13916
VectorFormat vform = instr->GetSVEVectorFormat();
13917
SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13918
SimPRegister& pn = ReadPRegister(instr->GetPn());
13919
13920
switch (instr->Mask(SVEPredicateCountMask)) {
13921
case CNTP_r_p_p: {
13922
WriteXRegister(instr->GetRd(), CountActiveAndTrueLanes(vform, pg, pn));
13923
break;
13924
}
13925
default:
13926
VIXL_UNIMPLEMENTED();
13927
break;
13928
}
13929
}
13930
13931
void Simulator::VisitSVEPredicateLogical(const Instruction* instr) {
13932
Instr op = instr->Mask(SVEPredicateLogicalMask);
13933
SimPRegister& pd = ReadPRegister(instr->GetPd());
13934
SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
13935
SimPRegister& pn = ReadPRegister(instr->GetPn());
13936
SimPRegister& pm = ReadPRegister(instr->GetPm());
13937
SimPRegister result;
13938
switch (op) {
13939
case ANDS_p_p_pp_z:
13940
case AND_p_p_pp_z:
13941
case BICS_p_p_pp_z:
13942
case BIC_p_p_pp_z:
13943
case EORS_p_p_pp_z:
13944
case EOR_p_p_pp_z:
13945
case NANDS_p_p_pp_z:
13946
case NAND_p_p_pp_z:
13947
case NORS_p_p_pp_z:
13948
case NOR_p_p_pp_z:
13949
case ORNS_p_p_pp_z:
13950
case ORN_p_p_pp_z:
13951
case ORRS_p_p_pp_z:
13952
case ORR_p_p_pp_z:
13953
SVEPredicateLogicalHelper(static_cast<SVEPredicateLogicalOp>(op),
13954
result,
13955
pn,
13956
pm);
13957
break;
13958
case SEL_p_p_pp:
13959
sel(pd, pg, pn, pm);
13960
return;
13961
default:
13962
VIXL_UNIMPLEMENTED();
13963
break;
13964
}
13965
13966
mov_zeroing(pd, pg, result);
13967
if (instr->Mask(SVEPredicateLogicalSetFlagsBit) != 0) {
13968
PredTest(kFormatVnB, pg, pd);
13969
}
13970
}
13971
13972
void Simulator::VisitSVEPredicateFirstActive(const Instruction* instr) {
13973
LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
13974
LogicPRegister pdn = ReadPRegister(instr->GetPd());
13975
switch (instr->Mask(SVEPredicateFirstActiveMask)) {
13976
case PFIRST_p_p_p:
13977
pfirst(pdn, pg, pdn);
13978
// TODO: Is this broken when pg == pdn?
13979
PredTest(kFormatVnB, pg, pdn);
13980
break;
13981
default:
13982
VIXL_UNIMPLEMENTED();
13983
break;
13984
}
13985
}
13986
13987
void Simulator::VisitSVEPredicateInitialize(const Instruction* instr) {
13988
// This group only contains PTRUE{S}, and there are no unallocated encodings.
13989
VIXL_STATIC_ASSERT(
13990
SVEPredicateInitializeMask ==
13991
(SVEPredicateInitializeFMask | SVEPredicateInitializeSetFlagsBit));
13992
VIXL_ASSERT((instr->Mask(SVEPredicateInitializeMask) == PTRUE_p_s) ||
13993
(instr->Mask(SVEPredicateInitializeMask) == PTRUES_p_s));
13994
13995
LogicPRegister pdn = ReadPRegister(instr->GetPd());
13996
VectorFormat vform = instr->GetSVEVectorFormat();
13997
13998
ptrue(vform, pdn, instr->GetImmSVEPredicateConstraint());
13999
if (instr->ExtractBit(16)) PredTest(vform, pdn, pdn);
14000
}
14001
14002
void Simulator::VisitSVEPredicateNextActive(const Instruction* instr) {
14003
// This group only contains PNEXT, and there are no unallocated encodings.
14004
VIXL_STATIC_ASSERT(SVEPredicateNextActiveFMask == SVEPredicateNextActiveMask);
14005
VIXL_ASSERT(instr->Mask(SVEPredicateNextActiveMask) == PNEXT_p_p_p);
14006
14007
LogicPRegister pg = ReadPRegister(instr->ExtractBits(8, 5));
14008
LogicPRegister pdn = ReadPRegister(instr->GetPd());
14009
VectorFormat vform = instr->GetSVEVectorFormat();
14010
14011
pnext(vform, pdn, pg, pdn);
14012
// TODO: Is this broken when pg == pdn?
14013
PredTest(vform, pg, pdn);
14014
}
14015
14016
void Simulator::VisitSVEPredicateReadFromFFR_Predicated(
14017
const Instruction* instr) {
14018
LogicPRegister pd(ReadPRegister(instr->GetPd()));
14019
LogicPRegister pg(ReadPRegister(instr->GetPn()));
14020
FlagsUpdate flags = LeaveFlags;
14021
switch (instr->Mask(SVEPredicateReadFromFFR_PredicatedMask)) {
14022
case RDFFR_p_p_f:
14023
// Do nothing.
14024
break;
14025
case RDFFRS_p_p_f:
14026
flags = SetFlags;
14027
break;
14028
default:
14029
VIXL_UNIMPLEMENTED();
14030
break;
14031
}
14032
14033
LogicPRegister ffr(ReadFFR());
14034
mov_zeroing(pd, pg, ffr);
14035
14036
if (flags == SetFlags) {
14037
PredTest(kFormatVnB, pg, pd);
14038
}
14039
}
14040
14041
void Simulator::VisitSVEPredicateReadFromFFR_Unpredicated(
14042
const Instruction* instr) {
14043
LogicPRegister pd(ReadPRegister(instr->GetPd()));
14044
LogicPRegister ffr(ReadFFR());
14045
switch (instr->Mask(SVEPredicateReadFromFFR_UnpredicatedMask)) {
14046
case RDFFR_p_f:
14047
mov(pd, ffr);
14048
break;
14049
default:
14050
VIXL_UNIMPLEMENTED();
14051
break;
14052
}
14053
}
14054
14055
void Simulator::VisitSVEPredicateTest(const Instruction* instr) {
14056
switch (instr->Mask(SVEPredicateTestMask)) {
14057
case PTEST_p_p:
14058
PredTest(kFormatVnB,
14059
ReadPRegister(instr->ExtractBits(13, 10)),
14060
ReadPRegister(instr->GetPn()));
14061
break;
14062
default:
14063
VIXL_UNIMPLEMENTED();
14064
break;
14065
}
14066
}
14067
14068
void Simulator::VisitSVEPredicateZero(const Instruction* instr) {
14069
switch (instr->Mask(SVEPredicateZeroMask)) {
14070
case PFALSE_p:
14071
pfalse(ReadPRegister(instr->GetPd()));
14072
break;
14073
default:
14074
VIXL_UNIMPLEMENTED();
14075
break;
14076
}
14077
}
14078
14079
void Simulator::VisitSVEPropagateBreak(const Instruction* instr) {
14080
SimPRegister& pd = ReadPRegister(instr->GetPd());
14081
SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
14082
SimPRegister& pn = ReadPRegister(instr->GetPn());
14083
SimPRegister& pm = ReadPRegister(instr->GetPm());
14084
14085
bool set_flags = false;
14086
switch (instr->Mask(SVEPropagateBreakMask)) {
14087
case BRKPAS_p_p_pp:
14088
set_flags = true;
14089
VIXL_FALLTHROUGH();
14090
case BRKPA_p_p_pp:
14091
brkpa(pd, pg, pn, pm);
14092
break;
14093
case BRKPBS_p_p_pp:
14094
set_flags = true;
14095
VIXL_FALLTHROUGH();
14096
case BRKPB_p_p_pp:
14097
brkpb(pd, pg, pn, pm);
14098
break;
14099
default:
14100
VIXL_UNIMPLEMENTED();
14101
break;
14102
}
14103
14104
if (set_flags) {
14105
PredTest(kFormatVnB, pg, pd);
14106
}
14107
}
14108
14109
void Simulator::VisitSVEStackFrameAdjustment(const Instruction* instr) {
14110
uint64_t length = 0;
14111
switch (instr->Mask(SVEStackFrameAdjustmentMask)) {
14112
case ADDPL_r_ri:
14113
length = GetPredicateLengthInBytes();
14114
break;
14115
case ADDVL_r_ri:
14116
length = GetVectorLengthInBytes();
14117
break;
14118
default:
14119
VIXL_UNIMPLEMENTED();
14120
}
14121
uint64_t base = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
14122
WriteXRegister(instr->GetRd(),
14123
base + (length * instr->GetImmSVEVLScale()),
14124
LogRegWrites,
14125
Reg31IsStackPointer);
14126
}
14127
14128
void Simulator::VisitSVEStackFrameSize(const Instruction* instr) {
14129
int64_t scale = instr->GetImmSVEVLScale();
14130
14131
switch (instr->Mask(SVEStackFrameSizeMask)) {
14132
case RDVL_r_i:
14133
WriteXRegister(instr->GetRd(), GetVectorLengthInBytes() * scale);
14134
break;
14135
default:
14136
VIXL_UNIMPLEMENTED();
14137
}
14138
}
14139
14140
void Simulator::VisitSVEVectorSelect(const Instruction* instr) {
14141
// The only instruction in this group is `sel`, and there are no unused
14142
// encodings.
14143
VIXL_ASSERT(instr->Mask(SVEVectorSelectMask) == SEL_z_p_zz);
14144
14145
VectorFormat vform = instr->GetSVEVectorFormat();
14146
SimVRegister& zd = ReadVRegister(instr->GetRd());
14147
SimPRegister& pg = ReadPRegister(instr->ExtractBits(13, 10));
14148
SimVRegister& zn = ReadVRegister(instr->GetRn());
14149
SimVRegister& zm = ReadVRegister(instr->GetRm());
14150
14151
sel(vform, zd, pg, zn, zm);
14152
}
14153
14154
void Simulator::VisitSVEFFRInitialise(const Instruction* instr) {
14155
switch (instr->Mask(SVEFFRInitialiseMask)) {
14156
case SETFFR_f: {
14157
LogicPRegister ffr(ReadFFR());
14158
ffr.SetAllBits();
14159
break;
14160
}
14161
default:
14162
VIXL_UNIMPLEMENTED();
14163
break;
14164
}
14165
}
14166
14167
void Simulator::VisitSVEFFRWriteFromPredicate(const Instruction* instr) {
14168
switch (instr->Mask(SVEFFRWriteFromPredicateMask)) {
14169
case WRFFR_f_p: {
14170
SimPRegister pn(ReadPRegister(instr->GetPn()));
14171
bool last_active = true;
14172
for (unsigned i = 0; i < pn.GetSizeInBits(); i++) {
14173
bool active = pn.GetBit(i);
14174
if (active && !last_active) {
14175
// `pn` is non-monotonic. This is UNPREDICTABLE.
14176
VIXL_ABORT();
14177
}
14178
last_active = active;
14179
}
14180
mov(ReadFFR(), pn);
14181
break;
14182
}
14183
default:
14184
VIXL_UNIMPLEMENTED();
14185
break;
14186
}
14187
}
14188
14189
void Simulator::VisitSVEContiguousLoad_ScalarPlusImm(const Instruction* instr) {
14190
bool is_signed;
14191
switch (instr->Mask(SVEContiguousLoad_ScalarPlusImmMask)) {
14192
case LD1B_z_p_bi_u8:
14193
case LD1B_z_p_bi_u16:
14194
case LD1B_z_p_bi_u32:
14195
case LD1B_z_p_bi_u64:
14196
case LD1H_z_p_bi_u16:
14197
case LD1H_z_p_bi_u32:
14198
case LD1H_z_p_bi_u64:
14199
case LD1W_z_p_bi_u32:
14200
case LD1W_z_p_bi_u64:
14201
case LD1D_z_p_bi_u64:
14202
is_signed = false;
14203
break;
14204
case LD1SB_z_p_bi_s16:
14205
case LD1SB_z_p_bi_s32:
14206
case LD1SB_z_p_bi_s64:
14207
case LD1SH_z_p_bi_s32:
14208
case LD1SH_z_p_bi_s64:
14209
case LD1SW_z_p_bi_s64:
14210
is_signed = true;
14211
break;
14212
default:
14213
// This encoding group is complete, so no other values should be possible.
14214
VIXL_UNREACHABLE();
14215
is_signed = false;
14216
break;
14217
}
14218
14219
int vl = GetVectorLengthInBytes();
14220
int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
14221
int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
14222
VIXL_ASSERT(esize_in_bytes_log2 >= msize_in_bytes_log2);
14223
int vl_divisor_log2 = esize_in_bytes_log2 - msize_in_bytes_log2;
14224
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
14225
uint64_t offset =
14226
(instr->ExtractSignedBits(19, 16) * vl) / (1 << vl_divisor_log2);
14227
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
14228
LogicSVEAddressVector addr(base + offset);
14229
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
14230
SVEStructuredLoadHelper(vform,
14231
ReadPRegister(instr->GetPgLow8()),
14232
instr->GetRt(),
14233
addr,
14234
is_signed);
14235
}
14236
14237
void Simulator::VisitSVEContiguousLoad_ScalarPlusScalar(
14238
const Instruction* instr) {
14239
bool is_signed;
14240
switch (instr->Mask(SVEContiguousLoad_ScalarPlusScalarMask)) {
14241
case LD1B_z_p_br_u8:
14242
case LD1B_z_p_br_u16:
14243
case LD1B_z_p_br_u32:
14244
case LD1B_z_p_br_u64:
14245
case LD1H_z_p_br_u16:
14246
case LD1H_z_p_br_u32:
14247
case LD1H_z_p_br_u64:
14248
case LD1W_z_p_br_u32:
14249
case LD1W_z_p_br_u64:
14250
case LD1D_z_p_br_u64:
14251
is_signed = false;
14252
break;
14253
case LD1SB_z_p_br_s16:
14254
case LD1SB_z_p_br_s32:
14255
case LD1SB_z_p_br_s64:
14256
case LD1SH_z_p_br_s32:
14257
case LD1SH_z_p_br_s64:
14258
case LD1SW_z_p_br_s64:
14259
is_signed = true;
14260
break;
14261
default:
14262
// This encoding group is complete, so no other values should be possible.
14263
VIXL_UNREACHABLE();
14264
is_signed = false;
14265
break;
14266
}
14267
14268
int msize_in_bytes_log2 = instr->GetSVEMsizeFromDtype(is_signed);
14269
int esize_in_bytes_log2 = instr->GetSVEEsizeFromDtype(is_signed);
14270
VIXL_ASSERT(msize_in_bytes_log2 <= esize_in_bytes_log2);
14271
VectorFormat vform = SVEFormatFromLaneSizeInBytesLog2(esize_in_bytes_log2);
14272
uint64_t base = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
14273
uint64_t offset = ReadXRegister(instr->GetRm());
14274
offset <<= msize_in_bytes_log2;
14275
LogicSVEAddressVector addr(base + offset);
14276
addr.SetMsizeInBytesLog2(msize_in_bytes_log2);
14277
SVEStructuredLoadHelper(vform,
14278
ReadPRegister(instr->GetPgLow8()),
14279
instr->GetRt(),
14280
addr,
14281
is_signed);
14282
}
14283
14284
void Simulator::DoUnreachable(const Instruction* instr) {
14285
VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14286
(instr->GetImmException() == kUnreachableOpcode));
14287
14288
fprintf(stream_,
14289
"Hit UNREACHABLE marker at pc=%p.\n",
14290
reinterpret_cast<const void*>(instr));
14291
abort();
14292
}
14293
14294
void Simulator::Simulate_XdSP_XnSP_Xm(const Instruction* instr) {
14295
VIXL_ASSERT(form_hash_ == Hash("irg_64i_dp_2src"));
14296
uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
14297
uint64_t rm = ReadXRegister(instr->GetRm());
14298
uint64_t tag = GenerateRandomTag(rm & 0xffff);
14299
uint64_t new_val = GetAddressWithAllocationTag(rn, tag);
14300
WriteXRegister(instr->GetRd(), new_val, LogRegWrites, Reg31IsStackPointer);
14301
}
14302
14303
void Simulator::SimulateMTEAddSubTag(const Instruction* instr) {
14304
uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
14305
uint64_t rn_tag = GetAllocationTagFromAddress(rn);
14306
uint64_t tag_offset = instr->ExtractBits(13, 10);
14307
// TODO: implement GCR_EL1.Exclude to provide a tag exclusion list.
14308
uint64_t new_tag = ChooseNonExcludedTag(rn_tag, tag_offset);
14309
14310
uint64_t offset = instr->ExtractBits(21, 16) * kMTETagGranuleInBytes;
14311
int carry = 0;
14312
if (form_hash_ == Hash("subg_64_addsub_immtags")) {
14313
offset = ~offset;
14314
carry = 1;
14315
} else {
14316
VIXL_ASSERT(form_hash_ == Hash("addg_64_addsub_immtags"));
14317
}
14318
uint64_t new_val =
14319
AddWithCarry(kXRegSize, /* set_flags = */ false, rn, offset, carry);
14320
new_val = GetAddressWithAllocationTag(new_val, new_tag);
14321
WriteXRegister(instr->GetRd(), new_val, LogRegWrites, Reg31IsStackPointer);
14322
}
14323
14324
void Simulator::SimulateMTETagMaskInsert(const Instruction* instr) {
14325
VIXL_ASSERT(form_hash_ == Hash("gmi_64g_dp_2src"));
14326
uint64_t mask = ReadXRegister(instr->GetRm());
14327
uint64_t tag = GetAllocationTagFromAddress(
14328
ReadXRegister(instr->GetRn(), Reg31IsStackPointer));
14329
uint64_t mask_bit = 1 << tag;
14330
WriteXRegister(instr->GetRd(), mask | mask_bit);
14331
}
14332
14333
void Simulator::SimulateMTESubPointer(const Instruction* instr) {
14334
uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
14335
uint64_t rm = ReadXRegister(instr->GetRm(), Reg31IsStackPointer);
14336
14337
VIXL_ASSERT((form_hash_ == Hash("subps_64s_dp_2src")) ||
14338
(form_hash_ == Hash("subp_64s_dp_2src")));
14339
bool set_flags = (form_hash_ == Hash("subps_64s_dp_2src"));
14340
14341
rn = ExtractSignedBitfield64(55, 0, rn);
14342
rm = ExtractSignedBitfield64(55, 0, rm);
14343
uint64_t new_val = AddWithCarry(kXRegSize, set_flags, rn, ~rm, 1);
14344
WriteXRegister(instr->GetRd(), new_val);
14345
}
14346
14347
void Simulator::SimulateMTEStoreTagPair(const Instruction* instr) {
14348
uint64_t rn = ReadXRegister(instr->GetRn(), Reg31IsStackPointer);
14349
uint64_t rt = ReadXRegister(instr->GetRt());
14350
uint64_t rt2 = ReadXRegister(instr->GetRt2());
14351
int offset = instr->GetImmLSPair() * static_cast<int>(kMTETagGranuleInBytes);
14352
14353
AddrMode addr_mode = Offset;
14354
switch (form_hash_) {
14355
case Hash("stgp_64_ldstpair_off"):
14356
// Default is the offset mode.
14357
break;
14358
case Hash("stgp_64_ldstpair_post"):
14359
addr_mode = PostIndex;
14360
break;
14361
case Hash("stgp_64_ldstpair_pre"):
14362
addr_mode = PreIndex;
14363
break;
14364
default:
14365
VIXL_UNIMPLEMENTED();
14366
}
14367
14368
uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addr_mode);
14369
if (!IsAligned(address, kMTETagGranuleInBytes)) {
14370
VIXL_ALIGNMENT_EXCEPTION();
14371
}
14372
14373
int tag = GetAllocationTagFromAddress(rn);
14374
meta_data_.SetMTETag(address, tag);
14375
14376
if (!MemWrite<uint64_t>(address, rt)) return;
14377
if (!MemWrite<uint64_t>(address + kXRegSizeInBytes, rt2)) return;
14378
}
14379
14380
void Simulator::SimulateMTEStoreTag(const Instruction* instr) {
14381
uint64_t rt = ReadXRegister(instr->GetRt(), Reg31IsStackPointer);
14382
int offset = instr->GetImmLS() * static_cast<int>(kMTETagGranuleInBytes);
14383
14384
AddrMode addr_mode = Offset;
14385
switch (form_hash_) {
14386
case Hash("st2g_64soffset_ldsttags"):
14387
case Hash("stg_64soffset_ldsttags"):
14388
case Hash("stz2g_64soffset_ldsttags"):
14389
case Hash("stzg_64soffset_ldsttags"):
14390
// Default is the offset mode.
14391
break;
14392
case Hash("st2g_64spost_ldsttags"):
14393
case Hash("stg_64spost_ldsttags"):
14394
case Hash("stz2g_64spost_ldsttags"):
14395
case Hash("stzg_64spost_ldsttags"):
14396
addr_mode = PostIndex;
14397
break;
14398
case Hash("st2g_64spre_ldsttags"):
14399
case Hash("stg_64spre_ldsttags"):
14400
case Hash("stz2g_64spre_ldsttags"):
14401
case Hash("stzg_64spre_ldsttags"):
14402
addr_mode = PreIndex;
14403
break;
14404
default:
14405
VIXL_UNIMPLEMENTED();
14406
}
14407
14408
bool is_pair = false;
14409
switch (form_hash_) {
14410
case Hash("st2g_64soffset_ldsttags"):
14411
case Hash("st2g_64spost_ldsttags"):
14412
case Hash("st2g_64spre_ldsttags"):
14413
case Hash("stz2g_64soffset_ldsttags"):
14414
case Hash("stz2g_64spost_ldsttags"):
14415
case Hash("stz2g_64spre_ldsttags"):
14416
is_pair = true;
14417
break;
14418
default:
14419
break;
14420
}
14421
14422
bool is_zeroing = false;
14423
switch (form_hash_) {
14424
case Hash("stz2g_64soffset_ldsttags"):
14425
case Hash("stz2g_64spost_ldsttags"):
14426
case Hash("stz2g_64spre_ldsttags"):
14427
case Hash("stzg_64soffset_ldsttags"):
14428
case Hash("stzg_64spost_ldsttags"):
14429
case Hash("stzg_64spre_ldsttags"):
14430
is_zeroing = true;
14431
break;
14432
default:
14433
break;
14434
}
14435
14436
uintptr_t address = AddressModeHelper(instr->GetRn(), offset, addr_mode);
14437
14438
if (is_zeroing) {
14439
if (!IsAligned(reinterpret_cast<uintptr_t>(address),
14440
kMTETagGranuleInBytes)) {
14441
VIXL_ALIGNMENT_EXCEPTION();
14442
}
14443
VIXL_STATIC_ASSERT(kMTETagGranuleInBytes >= sizeof(uint64_t));
14444
VIXL_STATIC_ASSERT(kMTETagGranuleInBytes % sizeof(uint64_t) == 0);
14445
14446
size_t fill_size = kMTETagGranuleInBytes;
14447
if (is_pair) {
14448
fill_size += kMTETagGranuleInBytes;
14449
}
14450
14451
size_t fill_offset = 0;
14452
while (fill_offset < fill_size) {
14453
if (!MemWrite<uint64_t>(address + fill_offset, 0)) return;
14454
fill_offset += sizeof(uint64_t);
14455
}
14456
}
14457
14458
int tag = GetAllocationTagFromAddress(rt);
14459
meta_data_.SetMTETag(address, tag, instr);
14460
if (is_pair) {
14461
meta_data_.SetMTETag(address + kMTETagGranuleInBytes, tag, instr);
14462
}
14463
}
14464
14465
void Simulator::SimulateMTELoadTag(const Instruction* instr) {
14466
uint64_t rt = ReadXRegister(instr->GetRt());
14467
int offset = instr->GetImmLS() * static_cast<int>(kMTETagGranuleInBytes);
14468
14469
switch (form_hash_) {
14470
case Hash("ldg_64loffset_ldsttags"):
14471
break;
14472
default:
14473
VIXL_UNIMPLEMENTED();
14474
}
14475
14476
uintptr_t address = AddressModeHelper(instr->GetRn(), offset, Offset);
14477
address = AlignDown(address, kMTETagGranuleInBytes);
14478
uint64_t tag = meta_data_.GetMTETag(address, instr);
14479
WriteXRegister(instr->GetRt(), GetAddressWithAllocationTag(rt, tag));
14480
}
14481
14482
void Simulator::SimulateCpyFP(const Instruction* instr) {
14483
MOPSPHelper<"cpy"_h>(instr);
14484
LogSystemRegister(NZCV);
14485
}
14486
14487
void Simulator::SimulateCpyP(const Instruction* instr) {
14488
MOPSPHelper<"cpy"_h>(instr);
14489
14490
int d = instr->GetRd();
14491
int n = instr->GetRn();
14492
int s = instr->GetRs();
14493
14494
// Determine copy direction. For cases in which direction is implementation
14495
// defined, use forward.
14496
bool is_backwards = false;
14497
uint64_t xs = ReadXRegister(s);
14498
uint64_t xd = ReadXRegister(d);
14499
uint64_t xn = ReadXRegister(n);
14500
14501
// Ignore the top byte of addresses for comparisons. We can use xn as is,
14502
// as it should have zero in bits 63:55.
14503
uint64_t xs_tbi = ExtractUnsignedBitfield64(55, 0, xs);
14504
uint64_t xd_tbi = ExtractUnsignedBitfield64(55, 0, xd);
14505
VIXL_ASSERT(ExtractUnsignedBitfield64(63, 55, xn) == 0);
14506
if ((xs_tbi < xd_tbi) && ((xs_tbi + xn) > xd_tbi)) {
14507
is_backwards = true;
14508
WriteXRegister(s, xs + xn);
14509
WriteXRegister(d, xd + xn);
14510
}
14511
14512
ReadNzcv().SetN(is_backwards ? 1 : 0);
14513
LogSystemRegister(NZCV);
14514
}
14515
14516
void Simulator::SimulateCpyM(const Instruction* instr) {
14517
VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"cpy"_h>());
14518
VIXL_ASSERT(instr->IsMOPSMainOf(GetLastExecutedInstruction(), "cpy"_h));
14519
14520
int d = instr->GetRd();
14521
int n = instr->GetRn();
14522
int s = instr->GetRs();
14523
14524
uint64_t xd = ReadXRegister(d);
14525
uint64_t xn = ReadXRegister(n);
14526
uint64_t xs = ReadXRegister(s);
14527
bool is_backwards = ReadN();
14528
14529
int step = 1;
14530
if (is_backwards) {
14531
step = -1;
14532
xs--;
14533
xd--;
14534
}
14535
14536
while (xn--) {
14537
VIXL_DEFINE_OR_RETURN(temp, MemRead<uint8_t>(xs));
14538
if (!MemWrite<uint8_t>(xd, temp)) return;
14539
LogMemTransfer(xd, xs, temp);
14540
xs += step;
14541
xd += step;
14542
}
14543
14544
if (is_backwards) {
14545
xs++;
14546
xd++;
14547
}
14548
14549
WriteXRegister(d, xd);
14550
WriteXRegister(n, 0);
14551
WriteXRegister(s, xs);
14552
}
14553
14554
void Simulator::SimulateCpyE(const Instruction* instr) {
14555
USE(instr);
14556
VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"cpy"_h>());
14557
VIXL_ASSERT(instr->IsMOPSEpilogueOf(GetLastExecutedInstruction(), "cpy"_h));
14558
// This implementation does nothing in the epilogue; all copying is completed
14559
// in the "main" part.
14560
}
14561
14562
void Simulator::SimulateSetP(const Instruction* instr) {
14563
MOPSPHelper<"set"_h>(instr);
14564
LogSystemRegister(NZCV);
14565
}
14566
14567
void Simulator::SimulateSetM(const Instruction* instr) {
14568
VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"set"_h>());
14569
VIXL_ASSERT(instr->IsMOPSMainOf(GetLastExecutedInstruction(), "set"_h));
14570
14571
uint64_t xd = ReadXRegister(instr->GetRd());
14572
uint64_t xn = ReadXRegister(instr->GetRn());
14573
uint64_t xs = ReadXRegister(instr->GetRs());
14574
14575
while (xn--) {
14576
LogWrite(instr->GetRs(), GetPrintRegPartial(kPrintRegLaneSizeB), xd);
14577
if (!MemWrite<uint8_t>(xd++, xs)) return;
14578
}
14579
WriteXRegister(instr->GetRd(), xd);
14580
WriteXRegister(instr->GetRn(), 0);
14581
}
14582
14583
void Simulator::SimulateSetE(const Instruction* instr) {
14584
USE(instr);
14585
VIXL_ASSERT(instr->IsConsistentMOPSTriplet<"set"_h>());
14586
VIXL_ASSERT(instr->IsMOPSEpilogueOf(GetLastExecutedInstruction(), "set"_h));
14587
// This implementation does nothing in the epilogue; all setting is completed
14588
// in the "main" part.
14589
}
14590
14591
void Simulator::SimulateSetGP(const Instruction* instr) {
14592
MOPSPHelper<"setg"_h>(instr);
14593
14594
uint64_t xd = ReadXRegister(instr->GetRd());
14595
uint64_t xn = ReadXRegister(instr->GetRn());
14596
14597
if ((xn > 0) && !IsAligned(xd, kMTETagGranuleInBytes)) {
14598
VIXL_ALIGNMENT_EXCEPTION();
14599
}
14600
14601
if (!IsAligned(xn, kMTETagGranuleInBytes)) {
14602
VIXL_ALIGNMENT_EXCEPTION();
14603
}
14604
14605
LogSystemRegister(NZCV);
14606
}
14607
14608
void Simulator::SimulateSetGM(const Instruction* instr) {
14609
uint64_t xd = ReadXRegister(instr->GetRd());
14610
uint64_t xn = ReadXRegister(instr->GetRn());
14611
14612
int tag = GetAllocationTagFromAddress(xd);
14613
while (xn) {
14614
meta_data_.SetMTETag(xd, tag);
14615
xd += 16;
14616
xn -= 16;
14617
}
14618
SimulateSetM(instr);
14619
}
14620
14621
void Simulator::DoTrace(const Instruction* instr) {
14622
VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14623
(instr->GetImmException() == kTraceOpcode));
14624
14625
// Read the arguments encoded inline in the instruction stream.
14626
uint32_t parameters;
14627
uint32_t command;
14628
14629
VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
14630
memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
14631
memcpy(&command, instr + kTraceCommandOffset, sizeof(command));
14632
14633
switch (command) {
14634
case TRACE_ENABLE:
14635
SetTraceParameters(GetTraceParameters() | parameters);
14636
break;
14637
case TRACE_DISABLE:
14638
SetTraceParameters(GetTraceParameters() & ~parameters);
14639
break;
14640
default:
14641
VIXL_UNREACHABLE();
14642
}
14643
14644
WritePc(instr->GetInstructionAtOffset(kTraceLength));
14645
}
14646
14647
14648
void Simulator::DoLog(const Instruction* instr) {
14649
VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14650
(instr->GetImmException() == kLogOpcode));
14651
14652
// Read the arguments encoded inline in the instruction stream.
14653
uint32_t parameters;
14654
14655
VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
14656
memcpy(&parameters, instr + kTraceParamsOffset, sizeof(parameters));
14657
14658
// We don't support a one-shot LOG_DISASM.
14659
VIXL_ASSERT((parameters & LOG_DISASM) == 0);
14660
// Print the requested information.
14661
if (parameters & LOG_SYSREGS) PrintSystemRegisters();
14662
if (parameters & LOG_REGS) PrintRegisters();
14663
if (parameters & LOG_VREGS) PrintVRegisters();
14664
14665
WritePc(instr->GetInstructionAtOffset(kLogLength));
14666
}
14667
14668
14669
void Simulator::DoPrintf(const Instruction* instr) {
14670
VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14671
(instr->GetImmException() == kPrintfOpcode));
14672
14673
// Read the arguments encoded inline in the instruction stream.
14674
uint32_t arg_count;
14675
uint32_t arg_pattern_list;
14676
VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
14677
memcpy(&arg_count, instr + kPrintfArgCountOffset, sizeof(arg_count));
14678
memcpy(&arg_pattern_list,
14679
instr + kPrintfArgPatternListOffset,
14680
sizeof(arg_pattern_list));
14681
14682
VIXL_ASSERT(arg_count <= kPrintfMaxArgCount);
14683
VIXL_ASSERT((arg_pattern_list >> (kPrintfArgPatternBits * arg_count)) == 0);
14684
14685
// We need to call the host printf function with a set of arguments defined by
14686
// arg_pattern_list. Because we don't know the types and sizes of the
14687
// arguments, this is very difficult to do in a robust and portable way. To
14688
// work around the problem, we pick apart the format string, and print one
14689
// format placeholder at a time.
14690
14691
// Allocate space for the format string. We take a copy, so we can modify it.
14692
// Leave enough space for one extra character per expected argument (plus the
14693
// '\0' termination).
14694
const char* format_base = ReadRegister<const char*>(0);
14695
VIXL_ASSERT(format_base != NULL);
14696
size_t length = strlen(format_base) + 1;
14697
char* const format = new char[length + arg_count];
14698
14699
// A list of chunks, each with exactly one format placeholder.
14700
const char* chunks[kPrintfMaxArgCount];
14701
14702
// Copy the format string and search for format placeholders.
14703
uint32_t placeholder_count = 0;
14704
char* format_scratch = format;
14705
for (size_t i = 0; i < length; i++) {
14706
if (format_base[i] != '%') {
14707
*format_scratch++ = format_base[i];
14708
} else {
14709
if (format_base[i + 1] == '%') {
14710
// Ignore explicit "%%" sequences.
14711
*format_scratch++ = format_base[i];
14712
i++;
14713
// Chunks after the first are passed as format strings to printf, so we
14714
// need to escape '%' characters in those chunks.
14715
if (placeholder_count > 0) *format_scratch++ = format_base[i];
14716
} else {
14717
VIXL_CHECK(placeholder_count < arg_count);
14718
// Insert '\0' before placeholders, and store their locations.
14719
*format_scratch++ = '\0';
14720
chunks[placeholder_count++] = format_scratch;
14721
*format_scratch++ = format_base[i];
14722
}
14723
}
14724
}
14725
VIXL_CHECK(placeholder_count == arg_count);
14726
14727
// Finally, call printf with each chunk, passing the appropriate register
14728
// argument. Normally, printf returns the number of bytes transmitted, so we
14729
// can emulate a single printf call by adding the result from each chunk. If
14730
// any call returns a negative (error) value, though, just return that value.
14731
14732
printf("%s", clr_printf);
14733
14734
// Because '\0' is inserted before each placeholder, the first string in
14735
// 'format' contains no format placeholders and should be printed literally.
14736
int result = printf("%s", format);
14737
int pcs_r = 1; // Start at x1. x0 holds the format string.
14738
int pcs_f = 0; // Start at d0.
14739
if (result >= 0) {
14740
for (uint32_t i = 0; i < placeholder_count; i++) {
14741
int part_result = -1;
14742
14743
uint32_t arg_pattern = arg_pattern_list >> (i * kPrintfArgPatternBits);
14744
arg_pattern &= (1 << kPrintfArgPatternBits) - 1;
14745
switch (arg_pattern) {
14746
case kPrintfArgW:
14747
part_result = printf(chunks[i], ReadWRegister(pcs_r++));
14748
break;
14749
case kPrintfArgX:
14750
part_result = printf(chunks[i], ReadXRegister(pcs_r++));
14751
break;
14752
case kPrintfArgD:
14753
part_result = printf(chunks[i], ReadDRegister(pcs_f++));
14754
break;
14755
default:
14756
VIXL_UNREACHABLE();
14757
}
14758
14759
if (part_result < 0) {
14760
// Handle error values.
14761
result = part_result;
14762
break;
14763
}
14764
14765
result += part_result;
14766
}
14767
}
14768
14769
printf("%s", clr_normal);
14770
14771
// Printf returns its result in x0 (just like the C library's printf).
14772
WriteXRegister(0, result);
14773
14774
// The printf parameters are inlined in the code, so skip them.
14775
WritePc(instr->GetInstructionAtOffset(kPrintfLength));
14776
14777
// Set LR as if we'd just called a native printf function.
14778
WriteLr(ReadPc());
14779
14780
delete[] format;
14781
}
14782
14783
14784
#ifdef VIXL_HAS_SIMULATED_RUNTIME_CALL_SUPPORT
14785
void Simulator::DoRuntimeCall(const Instruction* instr) {
14786
VIXL_STATIC_ASSERT(kRuntimeCallAddressSize == sizeof(uintptr_t));
14787
// The appropriate `Simulator::SimulateRuntimeCall()` wrapper and the function
14788
// to call are passed inlined in the assembly.
14789
VIXL_DEFINE_OR_RETURN(call_wrapper_address,
14790
MemRead<uintptr_t>(instr + kRuntimeCallWrapperOffset));
14791
VIXL_DEFINE_OR_RETURN(function_address,
14792
MemRead<uintptr_t>(instr + kRuntimeCallFunctionOffset));
14793
VIXL_DEFINE_OR_RETURN(call_type,
14794
MemRead<uint32_t>(instr + kRuntimeCallTypeOffset));
14795
auto runtime_call_wrapper =
14796
reinterpret_cast<void (*)(Simulator*, uintptr_t)>(call_wrapper_address);
14797
14798
if (static_cast<RuntimeCallType>(call_type) == kCallRuntime) {
14799
WriteRegister(kLinkRegCode,
14800
instr->GetInstructionAtOffset(kRuntimeCallLength));
14801
}
14802
runtime_call_wrapper(this, function_address);
14803
// Read the return address from `lr` and write it into `pc`.
14804
WritePc(ReadRegister<Instruction*>(kLinkRegCode));
14805
}
14806
#else
14807
void Simulator::DoRuntimeCall(const Instruction* instr) {
14808
USE(instr);
14809
VIXL_UNREACHABLE();
14810
}
14811
#endif
14812
14813
14814
void Simulator::DoConfigureCPUFeatures(const Instruction* instr) {
14815
VIXL_ASSERT(instr->Mask(ExceptionMask) == HLT);
14816
14817
typedef ConfigureCPUFeaturesElementType ElementType;
14818
VIXL_ASSERT(CPUFeatures::kNumberOfFeatures <
14819
std::numeric_limits<ElementType>::max());
14820
14821
// k{Set,Enable,Disable}CPUFeatures have the same parameter encoding.
14822
14823
size_t element_size = sizeof(ElementType);
14824
size_t offset = kConfigureCPUFeaturesListOffset;
14825
14826
// Read the kNone-terminated list of features.
14827
CPUFeatures parameters;
14828
while (true) {
14829
VIXL_DEFINE_OR_RETURN(feature, MemRead<ElementType>(instr + offset));
14830
offset += element_size;
14831
if (feature == static_cast<ElementType>(CPUFeatures::kNone)) break;
14832
parameters.Combine(static_cast<CPUFeatures::Feature>(feature));
14833
}
14834
14835
switch (instr->GetImmException()) {
14836
case kSetCPUFeaturesOpcode:
14837
SetCPUFeatures(parameters);
14838
break;
14839
case kEnableCPUFeaturesOpcode:
14840
GetCPUFeatures()->Combine(parameters);
14841
break;
14842
case kDisableCPUFeaturesOpcode:
14843
GetCPUFeatures()->Remove(parameters);
14844
break;
14845
default:
14846
VIXL_UNREACHABLE();
14847
break;
14848
}
14849
14850
WritePc(instr->GetInstructionAtOffset(AlignUp(offset, kInstructionSize)));
14851
}
14852
14853
14854
void Simulator::DoSaveCPUFeatures(const Instruction* instr) {
14855
VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14856
(instr->GetImmException() == kSaveCPUFeaturesOpcode));
14857
USE(instr);
14858
14859
saved_cpu_features_.push_back(*GetCPUFeatures());
14860
}
14861
14862
14863
void Simulator::DoRestoreCPUFeatures(const Instruction* instr) {
14864
VIXL_ASSERT((instr->Mask(ExceptionMask) == HLT) &&
14865
(instr->GetImmException() == kRestoreCPUFeaturesOpcode));
14866
USE(instr);
14867
14868
SetCPUFeatures(saved_cpu_features_.back());
14869
saved_cpu_features_.pop_back();
14870
}
14871
14872
void* Simulator::Mmap(
14873
void* address, size_t length, int prot, int flags, int fd, off_t offset) {
14874
// The underlying system `mmap` in the simulated environment doesn't recognize
14875
// PROT_BTI and PROT_MTE. Although the kernel probably just ignores the bits
14876
// it doesn't know, mask those protections out before calling is safer.
14877
int intenal_prot = prot;
14878
prot &= ~(PROT_BTI | PROT_MTE);
14879
14880
uint64_t address2 = reinterpret_cast<uint64_t>(
14881
mmap(address, length, prot, flags, fd, offset));
14882
14883
if (intenal_prot & PROT_MTE) {
14884
// The returning address of `mmap` isn't tagged.
14885
int tag = static_cast<int>(GenerateRandomTag());
14886
SetGranuleTag(address2, tag, length);
14887
address2 = GetAddressWithAllocationTag(address2, tag);
14888
}
14889
14890
return reinterpret_cast<void*>(address2);
14891
}
14892
14893
14894
int Simulator::Munmap(void* address, size_t length, int prot) {
14895
if (prot & PROT_MTE) {
14896
// Untag the address since `munmap` doesn't recognize the memory tagging
14897
// managed by the Simulator.
14898
address = AddressUntag(address);
14899
CleanGranuleTag(reinterpret_cast<char*>(address), length);
14900
}
14901
14902
return munmap(address, length);
14903
}
14904
14905
14906
} // namespace aarch64
14907
} // namespace vixl
14908
14909
#endif // VIXL_INCLUDE_SIMULATOR_AARCH64
14910
14911